diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 17:36:47 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 17:36:47 +0000 |
commit | 0441d265f2bb9da249c7abf333f0f771fadb4ab5 (patch) | |
tree | 3f3789daa2f6db22da6e55e92bee0062a7d613fe /pigeonhole | |
parent | Initial commit. (diff) | |
download | dovecot-0441d265f2bb9da249c7abf333f0f771fadb4ab5.tar.xz dovecot-0441d265f2bb9da249c7abf333f0f771fadb4ab5.zip |
Adding upstream version 1:2.3.21+dfsg1.upstream/1%2.3.21+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'pigeonhole')
942 files changed, 266274 insertions, 0 deletions
diff --git a/pigeonhole/AUTHORS b/pigeonhole/AUTHORS new file mode 100644 index 0000000..88a2e4b --- /dev/null +++ b/pigeonhole/AUTHORS @@ -0,0 +1,8 @@ +Stephan Bosch <stephan@rename-it.nl> + +This package is built for and partly based on the Dovecot Secure IMAP server +written by: + +Timo Sirainen <tss@iki.fi>. + +Grepping 'patch by' from ChangeLog shows up more people. diff --git a/pigeonhole/COPYING b/pigeonhole/COPYING new file mode 100644 index 0000000..98aa091 --- /dev/null +++ b/pigeonhole/COPYING @@ -0,0 +1,4 @@ +See AUTHORS file for list of copyright holders. + +Everything is licenced under LGPLv2.1 (see COPYING.LGPL) unless otherwise +mentioned at the beginning of the file. diff --git a/pigeonhole/COPYING.LGPL b/pigeonhole/COPYING.LGPL new file mode 100644 index 0000000..4362b49 --- /dev/null +++ b/pigeonhole/COPYING.LGPL @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/pigeonhole/ChangeLog b/pigeonhole/ChangeLog new file mode 100644 index 0000000..5768a2d --- /dev/null +++ b/pigeonhole/ChangeLog @@ -0,0 +1,38862 @@ +2023-08-30 15:48:42 +0300 Aki Tuomi <aki.tuomi@open-xchange.com> (f6cd4b8e) + + configure: Set version to 0.5.21 + + +M configure.ac + +2023-08-30 15:46:29 +0300 Aki Tuomi <aki.tuomi@open-xchange.com> (bf473e5c) + + NEWS: Add news for 0.5.21 + + +M NEWS + +2022-11-23 09:58:17 +0200 Aki Tuomi <aki.tuomi@open-xchange.com> (4d6323e5) + + NEWS: Add news for 2.3.20 + + +M NEWS + +2022-05-04 15:04:01 +0300 Aki Tuomi <aki.tuomi@open-xchange.com> (65e5508b) + + NEWS: Update date for 2.3.19 news + + +M NEWS + +2022-04-26 09:45:26 +0300 Aki Tuomi <aki.tuomi@open-xchange.com> (6c340655) + + NEWS: Add news for 0.5.19 + + +M NEWS + +2023-05-09 07:29:46 +0000 Marco Bettini <marco.bettini@open-xchange.com> (bea54d46) + + lib-sieve: act_redirect_execute() - Pick Message-id even if invalid + + This avoids adding another Message-id if one is already present but of bad + quality. + +M src/lib-sieve/cmd-redirect.c + +2023-06-20 01:13:08 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (8c3df357) + + lib-sieve: util: edit-mail - Fix assert occurring when bad header is + encountered. + + In that case, the header name and middle are empty, causing: + + Panic: file edit-mail.c: line 820 (edit_mail_headers_parse): assertion + failed: (body_offset > 0) + + Fixed by skipping the bad header for parsing altogether. + +M src/lib-sieve/util/edit-mail.c + +2023-03-30 01:58:09 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (ad58bdd4) + + managesieve: Disable debug logging while dumping capability + + It only causes confusing output. + +M src/managesieve/main.c + +2022-01-12 12:54:05 +0200 Aki Tuomi <aki.tuomi@open-xchange.com> (cf9d3352) + + NEWS: Add news for 0.5.18 + + +M NEWS + +2022-02-05 17:14:16 +0200 Martti Rannanjärvi <martti.rannanjarvi@open-xchange.com> (7927a415) + + managesieve-login: managesieve_proxy_parse_auth_reply() - Free input istream + + +M src/managesieve-login/managesieve-proxy.c + +2022-01-21 12:31:43 +0200 Martti Rannanjärvi <martti.rannanjarvi@open-xchange.com> (ede85010) + + configure.ac: Set pigeonhole version to 0.5.100 + + This is to match the version 2.3.100 used in core. + +M configure.ac + +2022-01-19 19:48:48 +0200 Aki Tuomi <aki.tuomi@open-xchange.com> (aba35b74) + + configure.ac: Fix version to 2.3 dovecot + + +M configure.ac + +2022-01-19 17:14:03 +0100 Timo Sirainen <timo.sirainen@open-xchange.com> (ca2cb5fb) + + configure: Update version to 0.5.devel + + +M configure.ac + +2021-11-30 12:50:17 +0200 Aki Tuomi <aki.tuomi@open-xchange.com> (c0951f32) + + NEWS: Add news for 0.5.17.1 + + +M NEWS + +2021-09-28 12:57:33 +0300 Aki Tuomi <aki.tuomi@open-xchange.com> (8bf12bb7) + + NEWS: Add news for 0.5.17 + + +M NEWS + +2021-12-03 09:05:16 +0200 Aki Tuomi <aki.tuomi@open-xchange.com> (df7907ae) + + lib-sieve-tool: Sieve tools do not need SSL settings + + Fixes argument list too long error. + +M src/lib-sieve-tool/sieve-tool.c + +2019-10-06 19:36:32 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (e8af1162) + + lib-sieve: sieve-stringlist - Assert that index for the index stringlist is + not 0. + + +M src/lib-sieve/sieve-stringlist.c + +2019-10-06 20:42:54 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (8c6a3928) + + lib-sieve: index extension: Do not accept :index tag with zero value. + + +M src/lib-sieve/plugins/index/tag-index.c +M tests/extensions/index/errors.svtest +M tests/extensions/index/errors/syntax.sieve + +2019-10-06 20:59:43 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (a46bb1a9) + + lib-sieve: plugins: index: Reformat tag-index.c. + + +M src/lib-sieve/plugins/index/tag-index.c + +2021-10-22 21:54:43 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (3e2a8df4) + + managesieve-login: Pass forward_ passdb args using XCLIENT command. + + +M src/managesieve-login/managesieve-proxy.c + +2021-10-22 21:51:08 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (a869b1a8) + + managesieve-login: Add FORWARD for XCLIENT. + + This allows passing passdb variables. They are prefixed with forward_ when + imported to extra fields. + +M src/managesieve-login/client.c + +2021-11-03 23:49:09 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (a1b4cea5) + + managesieve-login: managesieve-proxy - Fix pipelining beyond AUTHENTICATE. + + Upon login success, the next line was erroneously skipped. + +M src/managesieve-login/managesieve-proxy.c + +2021-06-22 17:06:58 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (b5e69c08) + + managesieve-login: Reformat managesieve-proxy.c. + + +M src/managesieve-login/managesieve-proxy.c + +2021-06-22 16:21:20 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (a38436fc) + + managesieve-login: Reformat client.h. + + +M src/managesieve-login/client.h + +2021-06-22 16:18:49 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (d92ad7b1) + + managesieve-login: Reformat client.c. + + +M src/managesieve-login/client.c + +2021-11-04 10:46:57 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (cbc1c489) + + lib-sieve: util: edit-mail - Fix returning buffer-full condition when data + was read. + + Fixes: + + Panic: file istream-crlf.c: line 24 (i_stream_crlf_read_common): assertion + failed: (ret != -2) Panic: file istream.h: line 228 (i_stream_read_more): + assertion failed: (ret != -2) + (various other similar panics are possible) + +M src/lib-sieve/util/edit-mail.c +M src/lib-sieve/util/test-edit-mail.c + +2020-08-26 00:38:15 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (b7b4d24d) + + lib-sieve: util: Reformat test-edit-mail.c. + + +M src/lib-sieve/util/test-edit-mail.c + +2020-08-26 00:00:04 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (ecc70828) + + lib-sieve: util: Reformat edit-mail.h. + + +M src/lib-sieve/util/edit-mail.h + +2020-08-25 23:55:28 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (a4a22309) + + lib-sieve: util: Reformat edit-mail.c. + + +M src/lib-sieve/util/edit-mail.c + +2021-11-02 09:54:08 -0400 Timo Sirainen <timo.sirainen@open-xchange.com> (29750ba5) + + managesieve: Use MASTER_SERVICE_FLAG_DISABLE_SSL_SET when dumping capability + + This prevents startup failures if ssl_ca has a large number of certificates. + +M src/managesieve/main.c + +2021-10-28 00:40:58 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (0b5e7b1a) + + lib-sieve: sieve-result - Fix panic occurring upon temp fail after committed + keep-equivalent action. + + The determination of whether a keep-equivalent action was already executed + is performed in sieve_result_implicit_keep_execute(), which can also be + called from sieve_result_implicit_keep_finalize(). But there, the + keep-equivalent status was checked before any call to + sieve_result_implicit_keep_execute(), which would thus yield the wrong + result. + + This change also makes the associated debug message more specific (otherwise + two identical debug messages are logged) and an assert is added that makes + sure the keep-equivalent action is actually finalized when the implicit keep + was supposed to be finalized. + + Panic was: + + Panic: file sieve-result.c: line 1706 (sieve_result_implicit_keep_finalize): + assertion failed: (aexec_keep->state == + SIEVE_ACTION_EXECUTION_STATE_EXECUTED) + +M src/lib-sieve/sieve-result.c + +2021-10-28 00:45:15 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (d1c44652) + + lib-sieve: sieve-result - Move finalize debug message for implicit keep. + + +M src/lib-sieve/sieve-result.c + +2021-09-20 22:09:48 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (27ab897f) + + plugins: imapsieve: imap-sieve-storage - Make sure mail_set_uid() is never + called with uid=0. + + +M src/plugins/imapsieve/imap-sieve-storage.c + +2021-08-04 13:06:23 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (c6d3cabf) + + NEWS: Add news for 0.5.16 + + +M NEWS + +2021-06-11 11:58:05 +0300 Aki Tuomi <aki.tuomi@open-xchange.com> (216e41c2) + + NEWS: Update release date + + +M NEWS + +2021-04-22 15:20:32 +0300 Aki Tuomi <aki.tuomi@open-xchange.com> (ab56f331) + + NEWS: Add news for 0.5.15 + + +M NEWS + +2021-09-17 11:40:41 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (837bd100) + + lib-sieve: plugins: duplicate: ext-duplicate-common - Add debug messages for + action finish stage. + + +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.c + +2021-06-08 03:50:53 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (5e66dfca) + + lib-sieve: Adjust to changes in mail-duplicate API. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.c +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.h +M src/lib-sieve/plugins/duplicate/tst-duplicate.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-execute.c +M src/lib-sieve/sieve-execute.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c +M src/plugins/imap-filter-sieve/imap-filter-sieve.c +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-script.c + +2021-09-19 13:18:24 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (0f2c9569) + + lib-sieve: Adjust to changes in Dovecot file-lock API. + + +M src/lib-sieve/sieve-binary-file.c + +2021-09-16 20:04:06 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (86170b0f) + + m4: dovecot.m4 - Sync with core + + +M m4/dovecot.m4 + +2021-07-21 00:07:21 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (79e51ecf) + + lib-sieve: Disable CPU time limit by default when Sieve is executed in mail + storage. + + +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve.c + +2021-08-18 13:27:50 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (4596d399) + + lib-sieve: sieve-result - Indicate in sieve_result_transaction_finalize() + debug message whether actions were committed. + + +M src/lib-sieve/sieve-result.c + +2021-08-18 13:26:26 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (65d771c1) + + lib-sieve: sieve-result - Indicate in sieve_result_transaction_execute() + debug message whether actions were executed. + + +M src/lib-sieve/sieve-result.c + +2021-08-18 02:43:05 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (dbf5b62b) + + lib-sieve: sieve-result - Add debug messages for temp failure handling. + + +M src/lib-sieve/sieve-result.c + +2021-08-18 13:29:41 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (81bd53d6) + + lib-sieve: sieve-result - Assert that implicit keep is executed in + sieve_result_implicit_keep_finalize(). + + +M src/lib-sieve/sieve-result.c + +2021-08-18 02:54:25 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (293f0027) + + lib-sieve: sieve-result - Fix resource leak occurring when implicit keep is + executed before temporary failure at commit. + + In the commit phase the implicit keep was never finalized, meaning that it + was not rolled back and thus not cleaned up properly. This leads to a memory + leak and a mailbox reference leak. This in turn causes an assert crash at + the end of delivery when the mail user is destroyed. + +M src/lib-sieve/sieve-result.c + +2021-08-18 02:56:32 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (f2b81cc6) + + lib-sieve: sieve-result - Fix handling of resource limit status after + implicit keep commit. + + +M src/lib-sieve/sieve-result.c + +2021-08-18 02:46:18 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (92b4b06d) + + lib-sieve: sieve-result - Skip implicit keep in execution stage upon temp + failure. + + It will be executed in the commit phase if necessary; don't do it early; it + will only be rolled back. + +M src/lib-sieve/sieve-result.c + +2021-08-18 02:26:32 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (c84e6e5d) + + lib-sieve: sieve-result - Move temp failure status checks into + sieve_result_implicit_keep_finalize(). + + +M src/lib-sieve/sieve-result.c + +2021-08-18 02:07:01 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (10e347e3) + + lib-sieve: sieve-result - Move temp failure status checks into + sieve_result_implicit_keep_execute(). + + +M src/lib-sieve/sieve-result.c + +2021-08-18 01:40:57 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (291f2fdb) + + lib-sieve: sieve-result - Remove success parameter from + sieve_result_implicit_keep_finalize(). + + +M src/lib-sieve/sieve-result.c + +2021-08-18 01:44:23 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (54e020c1) + + lib-sieve: sieve-result - Remove success parameter from + sieve_result_implicit_keep_execute(). + + +M src/lib-sieve/sieve-result.c + +2021-08-17 19:09:13 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (9f300239) + + lib-sieve: sieve-interpreter - Fix field mixup in debug message. + + +M src/lib-sieve/sieve-interpreter.c + +2021-08-19 02:46:22 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (4c0acd83) + + lib-sieve: sieve-binary-debug - Properly handle line decrements. + + +M src/lib-sieve/sieve-binary-debug.c + +2021-08-19 02:20:37 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (2cb70c69) + + lib-sieve: plugins: include: ext-include-common - Use ENUM_NEGATE() macro + where necessary. + + +M src/lib-sieve/plugins/include/ext-include-common.c + +2021-08-19 01:30:17 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (9222ce45) + + lib-sieve: sieve-ast - Use sieve_number_t for number values. + + +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h + +2021-08-19 01:29:48 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (efdb74cf) + + lib-sieve: sieve-lexer - Use sieve_number_t for number values. + + +M src/lib-sieve/sieve-lexer.h + +2021-08-19 01:26:25 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (ee9f9be3) + + lib-sieve: Add SIEVE_PRI_NUMBER definition. + + +M src/lib-sieve/sieve-common.h + +2020-10-12 21:21:12 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (37dfe0d8) + + lib-sieve: plugins: include: Reformat ext-include-common.c. + + +M src/lib-sieve/plugins/include/ext-include-common.c + +2020-03-09 23:55:33 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (031967f5) + + lib-sieve: Reformat sieve-ast.h. + + +M src/lib-sieve/sieve-ast.h + +2020-03-09 23:48:48 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (06213060) + + lib-sieve: Reformat sieve-ast.c. + + +M src/lib-sieve/sieve-ast.c + +2021-08-12 22:26:41 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (d6e0a9e3) + + lib-sieve: cmd-redirect - Avoid cancelling implicit keep upon mail loop + detection. + + +M src/lib-sieve/cmd-redirect.c + +2021-08-13 00:36:58 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (87df7e30) + + lib-sieve: cmd-redirect - Move dupeid to action exection transaction struct. + + +M src/lib-sieve/cmd-redirect.c + +2021-08-13 00:26:20 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (b25a511f) + + lib-sieve: cmd-redirect - Move msg_id to action exection transaction struct. + + +M src/lib-sieve/cmd-redirect.c + +2021-08-13 00:08:25 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (19335d87) + + lib-sieve: Remove spurious whitespace in cmd-redirect.c. + + +M src/lib-sieve/cmd-redirect.c + +2021-08-10 17:31:30 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (9e4160d6) + + lib-sieve: sieve-result - Fix omission of action finalization happening upon + result execution failure. + + This occurred because the code that checks for a deferred keep action in + sieve_result_implicit_keep_execute() could end up "finding" an action that + wasn't actually a deferred keep. That action was then erroneously promoted + to the FINALIZED state, which meant that commit/rollback was never executed. + +M src/lib-sieve/sieve-result.c + +2021-06-30 01:36:33 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (3f66b725) + + lib-sieve: plugins: enotify: mailto: uri-mailto - Change _is_qchar() to + accept char parameter. + + It is used like that everywhere and ubsan complains about passing char to + unsigned char parameter. + +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c + +2020-03-26 17:21:07 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (a679bce4) + + lib-sieve: plugins: enotify: mailto: Reformat uri-mailto.c. + + +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c + +2021-05-10 16:23:45 +0100 Siavash Tavakoli <siavash.tavakoli@open-xchange.com> (0aa68128) + + sieve-dict: Adjust to core dict API changes + + +M src/lib-sieve/storage/dict/sieve-dict-script.c +M src/lib-sieve/storage/dict/sieve-dict-storage.c + +2021-06-02 23:19:46 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (7090e625) + + lib-sieve: sieve-result - Never allow side-effect definition to be NULL. + + This had no real purpose and could cause NULL pointer dereference. + + Found by Clang scan-build. + +M src/lib-sieve/sieve-result.c + +2021-06-02 22:57:19 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (0dcf81e3) + + lib-sieve: sieve-binary-file - Fix potential NULL pointer dereference in + sieve_binary_file_update_resource_usage(). + + Found by Clang scan-build. + +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h + +2021-06-03 20:23:11 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (25c6a0a1) + + lib-managesieve: managesieve-parser - Parse literal size using as same + algorithm as str_parse*(). + + This prevents wrapping the integer value and fixes an ubsan complaint. + +M src/lib-managesieve/managesieve-parser.c + +2021-06-03 19:52:58 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (d40dd502) + + lib-managesieve: managesieve-parser - Fix 8 bit atom check to use unsigned + char. + + +M src/lib-managesieve/managesieve-parser.c + +2021-06-03 19:46:14 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (691d8493) + + lib-managesieve: Reformat managesieve-parser.h. + + +M src/lib-managesieve/managesieve-parser.h + +2021-06-03 19:45:53 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (d4ef956d) + + lib-managesieve: Reformat managesieve-parser.c. + + +M src/lib-managesieve/managesieve-parser.c + +2020-03-09 11:13:52 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (7de596ba) + + testsuite: Debug logging was unnecessarily growing data stack size + + +M src/testsuite/testsuite-log.c + +2021-05-27 01:14:02 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (cc1d13f9) + + lib-sieve: plugins: enotify: vmodf-encodeurl - Remove erroneous type cast. + + Fixes ubsan runtime error. + +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c + +2021-05-27 01:13:11 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (a98d9f59) + + global: Fix negation with constants to match target type + + +M src/lib-sieve/sieve-binary-file.c + +2021-05-27 01:10:22 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (b6955345) + + global: Use ENUM_NEGATE() macro where necessary + + +M src/lib-sieve/sieve-binary-file.c + +2021-04-22 23:06:48 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (37e62d89) + + lib-sieve: sieve-result - Add debug messages for implicit keep execution. + + +M src/lib-sieve/sieve-result.c + +2021-04-07 00:57:08 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (c3fdcb67) + + lib-sieve: sieve-result - Add debug messages for result execution. + + +M src/lib-sieve/sieve-result.c + +2021-04-07 01:18:26 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (eecaa6b5) + + lib-sieve: sieve-action - Add debug messages for store action. + + +M src/lib-sieve/sieve-actions.c + +2021-04-07 01:12:45 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (5e8c385f) + + lib-sieve: sieve - Add debug messages for multiscript execution. + + +M src/lib-sieve/sieve.c + +2021-05-10 22:19:06 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (f577a53d) + + lib-sieve: sieve-interpreter - Add status to debug message emitted when + script is finished. + + +M src/lib-sieve/sieve-interpreter.c + +2021-05-10 21:56:31 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (12cf5cca) + + lib-sieve: sieve - Add sieve_execution_exitcode_to_str(). + + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h + +2021-05-10 21:30:14 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (2d3c446f) + + lib-sieve: sieve-result - Provide proper execution context for action side + effects. + + This is currently not used, but prevents mishaps once such code is written. + +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/special-use/tag-specialuse.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c + +2021-05-08 03:37:51 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (cd092803) + + lib-sieve: sieve-result - Make execution struct available for action side + effects. + + +M src/lib-sieve/sieve-result.c + +2021-05-10 20:40:00 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (224b393a) + + lib-sieve: sieve-result - Always call the post_commit method of side-effects + if present. + + This is not currently used, but the absence of the call could cause memory + leaks in the future. + +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c + +2021-05-10 20:37:00 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (58486f18) + + lib-sieve: sieve-result - Move side-effect execution activities to separate + functions. + + +M src/lib-sieve/sieve-result.c + +2021-05-10 20:33:59 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (fb1e8fe0) + + lib-sieve: sieve-result - Make calls to sieve_action_execution_pre/post() + more logical. + + Call sieve_action_execution_pre() just before the first action activity and + always call sieve_action_execution_post() at the end of each action + activity. This makes things clearer and it makes the next commit easier. + +M src/lib-sieve/sieve-result.c + +2021-05-10 19:29:14 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (1583eea2) + + lib-sieve: sieve-result - Remove code duplication between implicit keep and + normal action execution. + + +M src/lib-sieve/sieve-result.c + +2021-04-26 03:31:30 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (e3135559) + + lib-sieve: sieve-result - Move action execution state to a separate struct. + + +M src/lib-sieve/sieve-result.c + +2021-05-10 12:07:58 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (ea20148c) + + lib-sieve: sieve-result - Rename rac local variables to aexec. + + Preparation for next commit. + +M src/lib-sieve/sieve-result.c + +2021-04-11 00:23:48 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (49b0df02) + + lib-sieve: sieve-actions - Remove parameter last from action finish method. + + +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c + +2021-04-23 10:59:35 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (b1720551) + + lib-sieve: sieve-actions - Avoid logging about rolled-back successful + implicit keep. + + This will now readily happen when executed (not committed) success implicit + keep is replaced by a failure implicit keep. + +M src/lib-sieve/sieve-actions.c + +2021-04-22 23:08:07 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (61a33b14) + + lib-sieve: sieve-result - Commit actions only at the end of an execution + sequence. + + Before, actions were executed and committed in full after each script in a + sequence. With this change, actions can still be rolled back until the end + of all Sieve script and action execution. + +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2021-04-20 01:49:48 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (c11beda2) + + lib-sieve: sieve-result - Add separate committed flag to struct + sieve_result_execution. + + The committed flag is set when at least one action was committed + successfully. The existing executed flag is repurposed to signal successful + execution of at least one action. These flags are now also properly managed + for the keep action. + +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2021-05-10 18:58:11 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (2c216d7c) + + lib-sieve: sieve-result - Move local seen_delivery flag to struct + sieve_result_execution. + + Allows doing the check in the action finalization function. + +M src/lib-sieve/sieve-result.c + +2021-04-20 01:33:46 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (386f1636) + + lib-sieve: sieve-result - Move executed_delivery flag to struct + sieve_result_execution. + + +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve.c + +2021-04-20 01:26:29 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (19e69f3b) + + lib-sieve: sieve-result - Move executed flag to struct + sieve_result_execution. + + +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2021-04-16 01:06:28 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (0b19d378) + + lib-sieve: sieve-result - Always iterate through all actions while + executing. + + +M src/lib-sieve/sieve-result.c + +2021-04-20 02:00:29 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (21683788) + + lib-sieve: sieve-result - Remove sieve_result_finish(). + + It is no longer used. + +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2021-04-16 00:32:37 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (551293ad) + + lib-sieve: sieve-result - Use proper state field for executed actions. + + +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c + +2021-04-11 22:42:49 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (c52ef960) + + lib-sieve: sieve-result - Only perform implicit keep inside + sieve_result_execute(). + + Adds status parameter to sieve_result_execute(). + +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-result.c + +2021-04-11 11:51:33 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (3f01d89d) + + lib-sieve: sieve-result - Avoid use of result->last_attempted_action in + sieve_result_print(). + + +M src/lib-sieve/sieve-result.c + +2021-04-11 11:49:04 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (c4d89e43) + + lib-sieve: sieve-result - Restructure sieve_result_print(). + + +M src/lib-sieve/sieve-result.c + +2021-04-11 11:32:25 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (37047790) + + lib-sieve: sieve-result - Use execution sequence counter to distinguish old + and new actions. + + +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2021-04-10 23:49:21 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (93ad05b4) + + lib-sieve: sieve-result - Record per-action error handler. + + Makes sure it is consistent for a later commit when action exection is more + fragmented. + +M src/lib-sieve/sieve-result.c + +2021-04-10 23:39:50 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (32b8af52) + + lib-sieve: sieve-result - Move execution status to struct + sieve_result_execution. + + +M src/lib-sieve/sieve-result.c + +2021-04-10 23:14:18 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (891784ee) + + lib-sieve: sieve-result - Record action execution status as full integer + status. + + +M src/lib-sieve/sieve-result.c + +2021-04-10 22:14:38 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (508fa1f7) + + lib-sieve: sieve-result - Move keep status to sieve_result_execution. + + +M src/lib-sieve/sieve-result.c + +2021-04-10 21:15:00 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (df07ff62) + + lib-sieve: sieve-result - Split _sieve_result_implicit_keep() into execute + and finalize phases. + + +M src/lib-sieve/sieve-result.c + +2021-04-10 17:39:03 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (3abfdaf0) + + lib-sieve: sieve-result - Move keep side effects to struct + sieve_result_execution. + + +M src/lib-sieve/sieve-result.c + +2021-04-10 17:24:56 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (b5929739) + + lib-sieve: sieve-result - Change rollback to success parameter in + _sieve_result_implicit_keep(). + + +M src/lib-sieve/sieve-result.c + +2021-04-10 17:20:31 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (e43a4544) + + lib-sieve: sieve-result - Always perform search for keep-equal actions + during implicit keep. + + +M src/lib-sieve/sieve-result.c + +2021-04-10 15:31:04 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (55ef4edc) + + lib-sieve: sieve-result - Move keep action context to struct + sieve_result_execution. + + +M src/lib-sieve/sieve-result.c + +2021-04-10 15:22:09 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (4eb8298a) + + lib-sieve: sieve-result - Move keep execute status to struct + sieve_result_execution. + + +M src/lib-sieve/sieve-result.c + +2021-04-10 15:08:17 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (7b213ac4) + + lib-sieve: sieve-result - Change action parameter of + sieve_action_execution_pre() to result action. + + +M src/lib-sieve/sieve-result.c + +2021-04-10 14:58:51 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (001d4cab) + + lib-sieve: sieve-result - Rename keep return argument for + sieve_result_execute() to keep_r. + + +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve.c +M src/testsuite/testsuite-result.c + +2021-04-10 14:37:06 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (7ffdaf07) + + lib-sieve: sieve-result - Move keep action to struct sieve_result_execution. + + +M src/lib-sieve/sieve-result.c + +2021-05-10 01:24:09 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (e082eb15) + + lib-sieve: sieve-result - Split off sieve_result_action_finish(). + + +M src/lib-sieve/sieve-result.c + +2021-05-10 01:19:22 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (9a0ae786) + + lib-sieve: sieve-result - Move sieve_result_action_commit_or_rollback(). + + +M src/lib-sieve/sieve-result.c + +2021-05-10 01:17:55 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (d1bf5928) + + lib-sieve: sieve-result - Move sieve_result_action_rollback(). + + +M src/lib-sieve/sieve-result.c + +2021-05-10 01:16:40 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (ebea306b) + + lib-sieve: sieve-result - Move sieve_result_action_commit(). + + +M src/lib-sieve/sieve-result.c + +2021-04-10 13:55:20 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (aa524676) + + lib-sieve: sieve-result - Split off sieve_result_action_execute(). + + +M src/lib-sieve/sieve-result.c + +2021-05-10 00:14:18 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (10826af0) + + lib-sieve: sieve-result - Split off sieve_result_action_start(). + + +M src/lib-sieve/sieve-result.c + +2021-04-23 10:51:23 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (59809e2d) + + lib-sieve: sieve-result - Consistently use sieve_action_execution_post() at + end of execution. + + +M src/lib-sieve/sieve-result.c + +2021-04-10 13:19:27 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (228801cf) + + lib-sieve: sieve-result - Rename sieve_result_finish_action_env() to + sieve_action_execution_post(). + + +M src/lib-sieve/sieve-result.c + +2021-04-10 13:19:16 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (d523a01f) + + lib-sieve: sieve-result - Rename sieve_result_prepare_action_env() to + sieve_action_execution_pre(). + + +M src/lib-sieve/sieve-result.c + +2021-04-10 13:06:23 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (3081c100) + + lib-sieve: sieve-result - Change execution API to use separate struct. + + +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve.c +M src/testsuite/testsuite-result.c + +2021-04-09 02:12:53 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (e6af7659) + + lib-sieve: sieve - Merge sieve_multiscript_tempfail() into + sieve_multiscript_finish(). + + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/imap-filter-sieve/imap-filter-sieve.c +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-script.c + +2021-04-23 10:40:21 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (c0384971) + + lib-sieve: sieve - Make sieve_multiscript_finish/tempfail(NULL, ...) a + no-op. + + +M src/lib-sieve/sieve.c + +2021-04-09 01:51:46 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (8bbcc9cd) + + lib-sieve: sieve - Move multiscript API cleanup to separate function. + + +M src/lib-sieve/sieve.c + +2021-05-21 02:57:04 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (14dc2bc1) + + lib-sieve: sieve - Modify mscript->keep directly in + sieve_multiscript_execute/test(). + + Avoids unnecessary pointer parameter. + +M src/lib-sieve/sieve.c + +2021-05-21 01:44:57 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (85b3d400) + + lib-sieve: sieve - Remove unused keep_r argument from execution functions. + + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/imap-filter-sieve/imap-filter-sieve.c +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-script.c + +2021-04-08 23:52:35 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (84ad4043) + + lib-sieve: sieve-result - Move result action keep field to public action + struct. + + +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c + +2021-04-11 12:09:15 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (9d5979b5) + + lib-sieve: sieve-actions - Make sure mail error is handled properly in store + action. + + +M src/lib-sieve/sieve-actions.c + +2021-04-11 12:07:48 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (447cebed) + + lib-sieve: sieve-actions - Restructure commit phase of store action. + + +M src/lib-sieve/sieve-actions.c + +2021-04-06 23:33:45 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (d8a8ebd0) + + lib-sieve: sieve-actions - Move store transaction cleanup to separate + function. + + +M src/lib-sieve/sieve-actions.c + +2021-02-12 22:09:27 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (f015a391) + + lib-sieve: sieve-actions - Move implicit keep handling to execute phase of + action execution. + + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c +M src/plugins/sieve-extprograms/cmd-pipe.c + +2021-05-10 11:09:08 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (af0d634a) + + lib-sieve: sieve-result - Rename first_/last_action to actions_head/_tail. + + +M src/lib-sieve/sieve-result.c + +2021-03-29 00:10:04 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (6ca5e567) + + plugins: sieve-extprograms: Reformat cmd-pipe.c. + + +M src/plugins/sieve-extprograms/cmd-pipe.c + +2020-04-05 23:27:49 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (38380092) + + lib-sieve: plugins: imap4flags: Reformat tag-flags.c. + + +M src/lib-sieve/plugins/imap4flags/tag-flags.c + +2021-03-29 00:03:37 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (b73dc428) + + lib-sieve: plugins: copy: Reformat ext-copy.c. + + +M src/lib-sieve/plugins/copy/ext-copy.c + +2021-04-11 12:29:16 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (99f1c8a1) + + lib-sieve: Reformat sieve-actions.c. + + +M src/lib-sieve/sieve-actions.c + +2020-08-25 22:22:10 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (a41f4337) + + testsuite: testsuite-mailstore - Check mail index validity in + testsuite_mailstore_mail_index(). + + Providing an out-of-range index caused an assert panic. + + Panic was: + + Panic: file mail-index-transaction-update.c: line 19 + (mail_index_transaction_lookup): assertion failed: (seq >= t->first_new_seq + && seq <= t->last_new_seq) + +M Makefile.am +M src/testsuite/testsuite-mailstore.c +A tests/failures/fuzz3.svtest + +2020-08-25 22:28:06 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (a5d77dca) + + testsuite: testsuite-mailstore - Return struct testsuite_mailstore_mail from + testsuite_mailstore_open(). + + This is more flexible and needed in subsequent commit. + +M src/testsuite/testsuite-mailstore.c + +2021-04-20 02:07:23 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (c4322964) + + lib-sieve: sieve-result - Prevent executing implicit keep upon resource + limit transgression. + + +M src/lib-sieve/sieve-result.c + +2021-03-08 17:15:52 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (827cab0d) + + managesieve: Fix crash when processing pipelined input after AUTHENTICATE + + Attempting to pipeline any commands with the AUTHENTICATE command resulted + in crash. + + Fixes: Panic: file istream.c: line 317 (i_stream_read_memarea): assertion + failed: (old_size <= _stream->pos - _stream->skip) + +M src/managesieve/main.c + +2021-03-08 17:12:08 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (bae10a75) + + managesieve: Move finishing istream to client_create_finish() + + +M src/managesieve/main.c +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h + +2021-02-24 19:08:33 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (953daba7) + + plugins: sieve-extprograms: Adjust to program_client_run() API change + + +M src/plugins/sieve-extprograms/sieve-extprograms-common.c + +2021-02-13 00:00:49 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (151eec1e) + + plugin tests: Do not use valgrind for child processes. + + Those are currently exclusively system tools and we cannot control whether + those have memory leaks. + +M Makefile.am + +2021-02-13 00:00:28 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (3b375f86) + + Update m4/dovecot.m4. + + +M m4/dovecot.m4 + +2020-04-08 09:39:20 -0400 Josef 'Jeff' Sipek <jeff.sipek@open-xchange.com> (8bc82b3b) + + lib-sieve: Include year in log file header + + Even on a well configured system, the log may accumulate the occasion error. + Because of the rare nature, it is impossible to know if the error from + yesterday is really a year old error that doesn't matter anymore. + +M src/lib-sieve/sieve-error.c + +2020-09-11 02:42:20 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (d07a8bae) + + testsuite: testsuite-mailstore - Check validity of folder argument. + + This is actually a secondary test. The command calling this should already + have checked this. + +M src/testsuite/testsuite-mailstore.c + +2020-09-11 02:41:34 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (6d4b1ea5) + + testsuite: cmd-test-message - Properly check folder argument validity. + + +M Makefile.am +M src/testsuite/cmd-test-message.c +A tests/failures/mailbox-bad-utf8.svtest + +2020-09-11 02:52:51 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (1a661ed1) + + testsuite: testsuite-common - Make expected test failure more clear in the + output. + + +M src/testsuite/testsuite-common.c + +2021-05-05 21:36:32 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (c70db20f) + + global: Adjust to env_put() API change + + +M src/lib-sieve/storage/ldap/sieve-ldap-storage-settings.c +M src/managesieve-login/managesieve-login-settings-plugin.c + +2021-02-11 16:33:26 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (9c8c06f0) + + global: Use array_foreach_elem() where possible + + +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/sieve-validator.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-delete.c +M src/plugins/imapsieve/imap-sieve-storage.c + +2021-03-02 10:56:54 +0200 Aki Tuomi <aki.tuomi@open-xchange.com> (35dd5386) + + NEWS: Update news for 0.5.14 + + +M NEWS + +2021-02-17 13:30:46 +0200 Aki Tuomi <aki.tuomi@open-xchange.com> (307bf115) + + NEWS: Add news for 0.5.14.rc1 + + +M NEWS + +2021-04-13 17:24:01 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (26537156) + + global: Adjust to buffer_t API change + + +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve/managesieve-settings.c + +2021-03-23 10:51:00 +0200 Aki Tuomi <aki.tuomi@open-xchange.com> (ad0d57b2) + + managesieve: parent_event was renamed to event_parent + + +M src/managesieve/main.c + +2020-04-16 11:09:17 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (1c7173a8) + + global: Adjust to settings-parser API changes + + +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve/managesieve-capabilities.c +M src/managesieve/managesieve-settings.c + +2021-03-15 18:27:02 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (0605bd02) + + lib-sieve: sieve-interpreter - Adjust to cpu-limit API change + + +M src/lib-sieve/sieve-interpreter.c + +2021-03-15 18:26:32 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (bd6e75f9) + + lib-sieve: sieve-interpreter - Fix crash if max_cpu_time_secs==0 + + +M src/lib-sieve/sieve-interpreter.c + +2021-02-03 22:45:11 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (a7439203) + + global: Use mailbox_get_last_internal_error() + + mailbox_get_last_error() should be used only for client-visible errors. The + internal errors should be used for logging. + +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/special-use/tst-specialuse-exists.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-storage-sync.c +M src/lib-sieve/util/edit-mail.c +M src/lib-sieve/util/mail-raw.c +M src/lib-sieve/util/test-edit-mail.c +M src/plugins/imapsieve/imap-sieve-storage.c +M src/sieve-tools/sieve-filter.c + +2021-02-03 22:25:38 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (093fd3e5) + + managesieve: Standardize disconnection log message + + +M src/managesieve/cmd-getscript.c +M src/managesieve/cmd-putscript.c +M src/managesieve/managesieve-client.c + +2021-02-03 22:16:30 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (8b58503f) + + managesieve-login: Use client_destroy_iostream_error() + + +M src/managesieve-login/client-authenticate.c + +2021-02-03 22:04:50 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (79a6118d) + + managesieve-login: Replace "Aborted login" with "Disconnected: Aborted login + by logging out" + + +M src/managesieve-login/client.c + +2021-02-03 22:02:00 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (2cd21f54) + + managesieve-login: Remove duplicate "Disconnected: " log prefixes + + client_destroy() already adds it. + +M src/managesieve-login/client-authenticate.c +M src/managesieve-login/client.c + +2021-03-02 17:06:42 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (505b765c) + + managesieve: Fix using mail_log_prefix when client is disconnected due to + server shutdown + + +M src/managesieve/main.c +M src/managesieve/managesieve-client.c + +2020-12-07 23:42:04 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (d99c69b8) + + plugins: lda-sieve: Implement cumulative resource limits on script + execution. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2020-12-07 23:41:41 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (63fe1864) + + plugins: imap-sieve: Implement cumulative resource limits on script + execution. + + +M src/plugins/imapsieve/imap-sieve.c + +2020-12-07 23:41:00 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (f9ebcd45) + + plugins: imap-filter-sieve: Implement cumulative resource limits on script + execution. + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2020-12-04 12:19:28 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (8d6d9e9f) + + lib-sieve: sieve-types - Add SIEVE_EXEC_RESOURCE_LIMIT exit code. + + It indicates that script execution exceeded a resource limit (currently only + CPU time limit). + +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-types.h +M src/plugins/imap-filter-sieve/imap-filter-sieve.c +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite.c + +2020-12-04 03:47:04 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (c3807e32) + + plugins: lda-sieve: Restructure lda_sieve_execute_script(). + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2020-12-04 03:30:33 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (50fe61c8) + + plugins: lda-sieve: Change return type of lda_sieve_execute_script*() to + int. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2020-12-04 03:17:17 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (4b5ced2c) + + plugins: imap-filter-sieve: Restructure imap_sieve_filter_run_scripts(). + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2020-12-04 03:12:01 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (0f5113e1) + + plugins: imap-filter-sieve: Make temporary failure and corrupt binary errors + fatal. + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2020-12-04 03:08:12 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (9d2fa4de) + + plugins: imap-filter-sieve: Add support for fatal script execute errors. + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c +M src/plugins/imap-filter-sieve/imap-filter-sieve.h +M src/plugins/imap-filter-sieve/imap-filter.c + +2021-01-04 16:09:00 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (3f007c7d) + + plugins: imap-filter-sieve: Make sure an (internal) error message is + available for failed compile. + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2021-01-04 05:22:40 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (552611e2) + + plugins: imap-filter-sieve: Fix useless addition of internal error message + to FILTER SIEVE errors. + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2020-12-04 02:54:58 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (f043569d) + + plugins: imapsieve: Restructure imap_sieve_run_scripts(). + + +M src/plugins/imapsieve/imap-sieve.c + +2020-12-04 02:45:50 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (d083bdab) + + plugins: imapsieve: Make temporary failure and corrupt binary errors fatal. + + +M src/plugins/imapsieve/imap-sieve.c + +2020-12-04 02:36:36 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (dd1e4248) + + plugins: imapsieve: Add support for fatal script execute errors. + + +M src/plugins/imapsieve/imap-sieve-storage.c +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/imapsieve/imap-sieve.h + +2020-12-03 03:23:55 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (7f50cd8e) + + lib-sieve: sieve-interpreter - Record last resource usage in struct + sieve_exec_status. + + +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-types.h + +2020-11-27 04:25:39 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (19fb7699) + + lib-sieve: sieve-binary-dumper - Dump information from file header. + + +M src/lib-sieve/sieve-binary-dumper.c + +2021-01-04 19:07:11 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (5a794cc8) + + lib-sieve: sieve - Add sieve_check_executable(). + + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h + +2020-12-06 03:20:20 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (0c84d613) + + lib-sieve: sieve - Add sieve_record_resource_usage(). + + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h + +2020-12-06 03:19:36 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (bcff0f7e) + + lib-sieve: sieve - Check binary for resource limits before opening in + sieve_script_open(). + + +M src/lib-sieve/sieve.c + +2020-12-06 03:16:23 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (62f4b4fc) + + lib-sieve: sieve-binary - Add sieve_binary_check_executable(). + + Checks whether binary is suitable for execution. + +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary.h + +2020-12-08 01:27:54 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (54b120d4) + + lib-sieve: sieve - Retain resource usage statistics across script recompile + in sieve_open*(). + + +M src/lib-sieve/sieve.c + +2020-12-10 00:54:37 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (015b1fda) + + lib-sieve: sieve - Restructure sieve_open_script(). + + Move part within data stack frame to separate function. + +M src/lib-sieve/sieve.c + +2020-11-27 04:15:42 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (a01173c6) + + lib-sieve: sieve-binary - Add support for recording cumulative resource + usage. + + Currently, only CPU time is supported. + +M INSTALL +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-types.h + +2020-12-03 03:36:06 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (77d56fd5) + + lib-sieve: sieve - Add API for resource usage manipulation and evaluation. + + +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h + +2020-12-23 03:05:12 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (0b9acda1) + + lib-sieve: sieve-binary-file - Associate saved binary with save path if no + path is set. + + +M src/lib-sieve/sieve-binary-file.c + +2020-11-27 02:50:06 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (0aaf8a2f) + + lib-sieve: sieve-binary-file - Record file header in binary struct. + + +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-binary.c + +2020-11-27 02:18:21 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (5e6e44c4) + + lib-sieve: sieve-binary-file - Split off sieve_binary_fd_open(). + + +M src/lib-sieve/sieve-binary-file.c + +2020-11-27 00:10:14 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (489a8469) + + lib-sieve: sieve-binary-file - Change binary file header format to include + header size and flags. + + +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-binary.h + +2020-12-08 00:29:06 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (8b489404) + + lib-sieve: sieve-binary-file - Move struct sieve_binary_header to + sieve-binary-private.h. + + +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h + +2020-11-27 00:10:14 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (3ce88199) + + lib-sieve: sieve-binary-file - Split off sieve_binary_file_read_header(). + + +M src/lib-sieve/sieve-binary-file.c + +2020-11-27 01:23:34 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (16f2ef6e) + + lib-sieve: sieve-binary-file - Add error_r return parameter to + _sieve_binary_open(). + + +M src/lib-sieve/sieve-binary-file.c + +2020-11-27 02:56:27 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (c89a110d) + + lib-sieve: sieve-binary-file - Change return type of + sieve_binary_file_read(). + + +M src/lib-sieve/sieve-binary-file.c + +2020-11-27 02:01:12 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (3c438a32) + + lib-sieve: sieve-binary-file - Remove unnecessary file load function + pointers. + + There is only one implementation now. + +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h + +2020-11-27 02:06:38 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (5c58aa91) + + lib-sieve: sieve-binary-file - Change return type of + sieve_binary_file_open(). + + +M src/lib-sieve/sieve-binary-file.c + +2020-11-27 04:10:20 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (b729f228) + + lib-sieve: sieve-binary-file - Make sieve_binary_file_close(NULL) a no-op. + + +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary.c + +2020-12-08 01:31:48 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (81b90f89) + + lib-sieve: sieve - Change sieve_script_open() to use sieve_binary_close() + internally. + + +M src/lib-sieve/sieve.c + +2020-11-27 03:46:02 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (99b4888a) + + lib-sieve: sieve - Change sieve_close() to use sieve_binary_close() + internally. + + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h + +2020-11-27 03:43:21 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (d9a02e46) + + lib-sieve: sieve-binary - Add sieve_binary_close(). + + +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h + +2020-11-27 03:33:23 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (710d01e5) + + lib-sieve: sieve-binary - Make sieve_binary_unref(NULL) a no-op. + + +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-script.c + +2020-10-28 20:16:17 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (68505e44) + + lib-sieve: Enforce CPU time limit on Sieve script execution. + + +M INSTALL +M Makefile.am +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-settings.c +A tests/execute/errors-cpu-limit.svtest +A tests/execute/errors/cpu-limit.sieve + +2020-03-09 23:58:01 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (40b13e53) + + lib-sieve: Reformat sieve-binary-dumper.h. + + +M src/lib-sieve/sieve-binary-dumper.h + +2020-03-09 23:56:33 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (190727bb) + + lib-sieve: Reformat sieve-binary-dumper.c. + + +M src/lib-sieve/sieve-binary-dumper.c + +2020-11-27 03:58:45 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (dc3edc2b) + + lib-sieve: Reformat sieve-binary-file.c. + + +M src/lib-sieve/sieve-binary-file.c + +2020-03-12 03:39:36 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (715b95ce) + + lib-sieve: Reformat sieve-settings.h. + + +M src/lib-sieve/sieve-settings.h + +2020-03-12 03:37:15 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (3ee39f42) + + lib-sieve: Reformat sieve-settings.c. + + +M src/lib-sieve/sieve-settings.c + +2020-10-29 01:32:04 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (8463029f) + + lib-sieve: Reformat sieve-limits.h. + + +M src/lib-sieve/sieve-limits.h + +2020-03-24 17:25:52 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (7047a6d8) + + lib-sieve: Reformat sieve.h. + + +M src/lib-sieve/sieve.h + +2020-11-27 00:35:58 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (501c5700) + + lib-sieve: Reformat sieve.c. + + +M src/lib-sieve/sieve.c + +2020-04-08 16:19:18 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (457e2a4f) + + lib-sieve: sieve-script - Fix leak of script object in + sieve_script_binary_dump_metadata(). + + +M src/lib-sieve/sieve-script.c + +2021-01-13 18:05:15 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (821a9516) + + plugins: imap-filter-sieve: cmd-filter-sieve - Avoid using + imap_arg_as_nstring() in cmd_filter_sieve_script_parse_value_arg() + + The argument can only be a quoted string here, so imap_arg_as_string() will + suffice. + +M src/plugins/imap-filter-sieve/cmd-filter-sieve.c + +2021-01-13 17:58:16 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (bba3a530) + + plugins: imap-filter-sieve: cmd-filter-sieve - Do not allow NIL as script + name argument + + This was not supposed to be accepted and led to unexpected behavior: + + - FILTER SIEVE PERSONAL NIL was handled as FILTER SIEVE DELIVERY, + - FILTER SIEVE GLOBAL NIL caused an internal error. + +M src/plugins/imap-filter-sieve/cmd-filter-sieve.c + +2021-01-13 18:12:38 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (58d792cd) + + plugins: imap-fitler-sieve: Reformat cmd-filter-sieve.c + + +M src/plugins/imap-filter-sieve/cmd-filter-sieve.c + +2020-12-12 19:47:56 +0200 Aki Tuomi <aki.tuomi@open-xchange.com> (7a9a3219) + + NEWS: Add news for 0.5.13 + + +M NEWS + +2020-11-10 11:46:47 +0200 Aki Tuomi <aki.tuomi@open-xchange.com> (8e405770) + + m4: dovecot.m4 - Sync with core + + +M m4/dovecot.m4 + +2020-06-18 00:28:02 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (a1c1ca78) + + lib-sieve: plugins: editheader: Fix infinite loop occurring when header + setting is invalid. + + +M src/lib-sieve/plugins/editheader/ext-editheader-common.c +M tests/extensions/editheader/protected.svtest + +2020-03-25 20:36:15 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (4187a868) + + lib-sieve: plugins: editheader: Reformat ext-editheader-common.h. + + +M src/lib-sieve/plugins/editheader/ext-editheader-common.h + +2020-03-25 20:33:38 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (879d2121) + + lib-sieve: plugins: editheader: Reformat ext-editheader-common.c. + + +M src/lib-sieve/plugins/editheader/ext-editheader-common.c + +2020-06-11 20:53:26 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (fc605f10) + + testsuite: cmd-test-mailbox - Check mailbox name validity. + + Fixes assert failure occurring either at compiletime or at runtime + (depending on whether the value originates from variable). + +M src/testsuite/cmd-test-mailbox.c + +2020-06-11 20:53:24 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (5c0c25fd) + + lib-sieve: plugins: special-use: tst-specialuse-exists - Check mailbox name + validity. + + Fixes assert failure occurring either at compiletime or at runtime + (depending on whether the value originates from variable). + +M src/lib-sieve/plugins/special-use/tst-specialuse-exists.c +M tests/extensions/special-use/errors.svtest +A tests/extensions/special-use/errors/specialuse_exists-bad-utf8.sieve +M tests/extensions/special-use/errors/syntax.sieve + +2020-06-11 20:53:23 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (c65f1c4c) + + lib-sieve: plugins: mailbox: tst-mailboxexists - Check mailbox name validity + at runtime. + + Fixes assert failure occurring at runtime (when value originates from + variable). + +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M tests/extensions/mailbox/errors.svtest +A tests/extensions/mailbox/errors/mailboxexists-bad-utf8.sieve + +2020-06-11 20:53:23 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (0659935e) + + lib-sieve: ext-fileinto - Consistently use sieve_mailbox_check_name(). + + +M src/lib-sieve/ext-fileinto.c + +2020-06-11 22:33:36 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (dcb93b58) + + tests: extensions: metadata: Add tests for bad UTF-8 in mailbox names. + + +M tests/extensions/metadata/errors.svtest +A tests/extensions/metadata/errors/metadata-bad-utf8.sieve +A tests/extensions/metadata/errors/metadataexists-bad-utf8.sieve +M tests/extensions/metadata/errors/syntax.sieve + +2020-06-11 21:56:44 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (f87ddf2b) + + tests: extensions: mailbox: Add tests for syntax errors. + + +M Makefile.am +A tests/extensions/mailbox/errors.svtest +A tests/extensions/mailbox/errors/syntax.sieve + +2020-06-11 21:35:47 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (b62d83a2) + + tests: execute: Add tests for fileinto command executed with bad UTF-8 in + folder name. + + Compile error is avoided by putting the mailbox name in a variable, which is + (currently) only evaluated at runtime. + +M tests/execute/errors.svtest +A tests/execute/errors/fileinto-bad-utf8.sieve + +2020-06-11 21:26:56 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (cb916cca) + + tests: compile: Add tests for fileinto command compile errors. + + +M tests/compile/errors.svtest +A tests/compile/errors/fileinto.sieve + +2020-06-11 20:53:22 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (01b3eaa3) + + lib-sieve: sieve-actions - Fix error message in sieve_mailbox_check_name(). + + +M src/lib-sieve/sieve-actions.c + +2020-06-11 20:53:22 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (2085ed3d) + + lib-sieve: plugins: metadata: tst-metadataexists - Fix warning message + prefix in tst_metadataexists_operation_execute(). + + +M src/lib-sieve/plugins/metadata/tst-metadataexists.c + +2020-06-11 20:53:22 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (ac91b1fa) + + testsuite: cmd-test-mailbox - Move runtime execution to separate functions. + + Reduces code indent. + +M src/testsuite/cmd-test-mailbox.c + +2020-06-11 20:53:21 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (2ada0123) + + lib-sieve: plugins: special-use: tst-specialuse-exists - Restructure + tst_specialuse_exists_operation_execute(). + + Reduces indent. + +M src/lib-sieve/plugins/special-use/tst-specialuse-exists.c + +2020-06-11 20:53:21 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (ceb4a50b) + + lib-sieve: plugins: special-use: tst-specialuse-exists - Split off + tst_specialuse_exists_check_flag(). + + Reduces code indent. + +M src/lib-sieve/plugins/special-use/tst-specialuse-exists.c + +2020-06-11 20:53:20 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (3bf389e2) + + lib-sieve: plugins: metadata: tst-metadataexists - Split off + tst_metadataexists_check_annotation(). + + Reduces code indent. + +M src/lib-sieve/plugins/metadata/tst-metadataexists.c + +2020-06-11 20:53:20 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (d58ba0b3) + + lib-sieve: plugins: mailbox: tst-mailboxexists - Restructure + tst_mailboxexists_operation_execute(). + + Reduces code indent. + +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c + +2020-06-11 20:53:20 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (d27a2ca2) + + lib-sieve: plugins: mailbox: tst-mailboxexists - Split off + tst_mailboxexists_test_mailbox(). + + Reduces code indent. + +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c + +2020-06-11 20:53:19 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (06034e01) + + lib-sieve: ext-fileinto - Improve error message for invalid folder name. + + +M src/lib-sieve/ext-fileinto.c + +2020-06-11 20:53:19 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (3a8094f0) + + lib-sieve: ext-fileinto - Always check validity of folder name at runtime. + + +M src/lib-sieve/ext-fileinto.c + +2020-06-11 20:53:19 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (d09d71a8) + + testsuite: cmd-test-mailbox - Fix comment in + cmd_test_mailbox_operation_execute(). + + +M src/testsuite/cmd-test-mailbox.c + +2020-06-11 20:53:18 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (aed6f90c) + + lib-sieve: plugins: special-use: Reformat tst-specialuse-exists.c. + + +M src/lib-sieve/plugins/special-use/tst-specialuse-exists.c + +2020-06-11 20:53:18 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (7793c0dc) + + lib-sieve: plugins: metadata: Reformat tst-metadataexists.c. + + +M src/lib-sieve/plugins/metadata/tst-metadataexists.c + +2020-06-11 20:53:17 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (22e3c512) + + lib-sieve: plugins: metadata: Reformat tst-metadata.c. + + +M src/lib-sieve/plugins/metadata/tst-metadata.c + +2020-06-11 20:53:15 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (64ec8a73) + + lib-sieve: plugins: mailbox: Reformat tst-mailboxexists.c. + + +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c + +2020-06-11 20:53:08 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (c80f315d) + + lib-sieve: Reformat ext-fileinto.c. + + +M src/lib-sieve/ext-fileinto.c + +2020-08-13 20:25:11 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (529fc691) + + testsuite: cmd-test-fail - Remove unused _get_generator_context(). + + +M src/testsuite/cmd-test-fail.c + +2020-05-19 15:40:04 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (33c8d372) + + lib-sieve: Adjust to message_parser_init() API change + + +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/sieve-message.c + +2020-06-30 11:53:28 +0300 Aki Tuomi <aki.tuomi@open-xchange.com> (cf9062c7) + + NEWS: Add news for 0.5.11 + + +M NEWS + +2020-07-09 02:45:26 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (d8bd2c73) + + lib-sieve: plugins: duplicate: Only save duplicate entry when the last + script executed successfully. + + This prevents prematurely marking duplicates when errors occur during result + execution. Before, the pending duplicate database changes were committed + after each script executed in the sequence. If a later script failed, + duplicate tests would mark duplicate messages prematurely. + + Disadvantage is that actions in earlier scripts that are shielded by a + duplicate test can be executed twice erroneously when errors occurred in + later scripts in the previous delivery. Still, unexpected duplicate action + execution is better than losing mail due to erroneous duplicate detections. + + Fixing this properly requires extensively restructuring result execution. + +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.c + +2020-07-27 22:27:09 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (caca3091) + + lib-sieve: sieve - Explicitly finish the result in + sieve_multiscript_finish(). + + +M src/lib-sieve/sieve.c + +2020-07-27 22:26:39 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (ab3bb29b) + + lib-sieve: sieve-result - Add sieve_result_finish(). + + +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2019-10-01 21:49:33 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (b3899bd5) + + lib-sieve: sieve-actions - Add "last" parameter to action finish method. + + This indicates whether the last script in the sequence is being executed. + +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve.c +M src/testsuite/testsuite-result.c + +2020-07-09 02:42:29 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (58d81c59) + + lib-sieve: plugins: duplicate: ext-duplicate-common - Restructure + act_duplicate_mark_finish(). + + +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.c + +2020-06-08 19:26:58 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (d71045c1) + + testsuite: Reliably terminate tests upon failure. + + Before, it would only terminate the test when it failed explicitly using the + test_fail command. + +M Makefile.am +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +A tests/failures/fuzz1.svtest +A tests/failures/fuzz2.svtest + +2020-06-10 12:27:08 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (6359033b) + + testsuite: testsuite-mailstore - Preserve all allocated mails until result + is reset. + + The actions contained in the result may keep references to the overriden + mail struct, so these need to be preserved. + +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite-result.c + +2020-06-08 19:26:50 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (2f20547d) + + testsuite: testsuite-message - Preserve all allocated mails until result is + reset. + + The actions contained in the result may keep references to the overriden + mail struct, so these need to be preserved. + +M src/testsuite/cmd-test-result.c +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite.c + +2020-06-08 19:26:47 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (c3fca0a1) + + testsuite: Drop needless result reference in testsuite_run(). + + This holds a reference to the initial result, causing it to linger after + test_result_reset, thereby also holding a reference to the message context, + preventing it from being cleared. This in turn, can keep references to + modified message versions that cause the main message object to remain + referenced. This causes a panic in specific cases upon test_result_reset: + + Panic: Input stream data unexpectedly has references + +M src/testsuite/testsuite.c +M tests/extensions/editheader/execute.svtest + +2020-06-08 19:26:45 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (4635acae) + + testsuite: Properly check address value parsed from message. + + Caused a panic when input was not valid. This is only relevant to the test + suite and doesn't occur anywhere else (apart from the previous similar + commit for lib-sieve-tool). + + Panic was: + + Panic in file smtp-address.c: line 684 (smtp_address_write): assertion + failed: (smtp_char_is_qpair(*p))` + +M src/testsuite/testsuite-message.c +M tests/extensions/vacation/smtp.svtest + +2020-06-10 13:02:10 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (39e9b39e) + + lib-sieve-tool: sieve-tool - Properly check address value parsed from + message. + + +M src/lib-sieve-tool/sieve-tool.c + +2020-06-08 19:26:42 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (89ddd79d) + + lib-sieve-tool: Add sieve_tool_get_mail_raw_user(). + + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h + +2020-06-08 19:26:40 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (571964e9) + + lib-sieve: sieve-interpreter - Add sieve_interpreter_program_jump_to(). + + +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h + +2020-06-08 19:26:38 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (b5ccedae) + + lib-sieve: sieve-interpreter - Split off + sieve_interpreter_do_program_jump(). + + +M src/lib-sieve/sieve-interpreter.c + +2020-06-08 19:26:35 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (3e0a599e) + + lib-sieve: sieve-interpreter - Split off + sieve_interpreter_check_program_jump(). + + +M src/lib-sieve/sieve-interpreter.c + +2020-06-08 19:26:33 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (ad7bb544) + + lib-sieve: sieve-interpreter - Restructure sieve_interpreter_program_jump(). + + +M src/lib-sieve/sieve-interpreter.c + +2020-06-08 19:26:30 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (cba117cc) + + lib-sieve: sieve-interpreter - Drop needless result reference in + sieve_interpreter_run(). + + It is immediately referenced in sieve_interpreter_continue(), called from + there. + +M src/lib-sieve/sieve-interpreter.c + +2020-06-08 19:26:19 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (de09a841) + + lib-sieve: sieve-address - Require error_r parameters to not be NULL. + + The error string is currently always used and it must be, so there is no + need to allow for the error_r paramerter to be NULL and unused. + +M src/lib-sieve/sieve-address.c + +2020-07-30 23:33:04 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (2028ada8) + + testsuite: Add support for test cases with expected failure. + + +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite.c + +2020-06-09 12:43:16 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (2f645637) + + testsuite: Reformat cmd-test.c. + + +M src/testsuite/cmd-test.c + +2020-06-09 12:37:48 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (ecc4a3ac) + + testsuite: Reformat cmd-test-result.c. + + +M src/testsuite/cmd-test-result.c + +2020-06-09 12:32:42 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (6d250020) + + testsuite: Reformat cmd-test-message.c. + + +M src/testsuite/cmd-test-message.c + +2020-06-09 12:15:54 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (2dbd2890) + + testsuite: Reformat cmd-test-mailbox.c. + + +M src/testsuite/cmd-test-mailbox.c + +2020-06-09 12:08:22 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (89dd012a) + + testsuite: Reformat cmd-test-fail.c. + + +M src/testsuite/cmd-test-fail.c + +2020-06-09 12:00:28 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (bc26d8b6) + + testsuite: Reformat testsuite-mailstore.h. + + +M src/testsuite/testsuite-mailstore.h + +2020-06-09 12:00:13 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (ad35af9c) + + testsuite: Reformat testsuite-mailstore.c. + + +M src/testsuite/testsuite-mailstore.c + +2020-06-09 02:36:54 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (0324c6dd) + + testsuite: Reformat testsuite-common.c. + + +M src/testsuite/testsuite-common.c + +2020-06-09 02:30:42 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (f5a7bbb0) + + testsuite: Reformat testsuite-common.h. + + +M src/testsuite/testsuite-common.h + +2020-06-09 11:51:38 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (6dc7b477) + + lib-sieve-tool: Reformat sieve-tool.h. + + +M src/lib-sieve-tool/sieve-tool.h + +2020-06-09 11:51:09 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (76d6da31) + + lib-sieve-tool: Reformat sieve-tool.c. + + +M src/lib-sieve-tool/sieve-tool.c + +2020-03-09 10:50:07 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (fc8940b1) + + lib-sieve: Reformat sieve-address.h. + + +M src/lib-sieve/sieve-address.h + +2020-03-09 10:49:57 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (f8effd5c) + + lib-sieve: Reformat sieve-address.c. + + +M src/lib-sieve/sieve-address.c + +2020-06-11 14:49:24 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (0cf888a0) + + lib-sieve: plugins: relational: Fix segfault occurring in + mcht_relational_validate(). + + The segfault happens when this match type is the last argument of the test + command. This situation is not possible in a valid script; positional + arguments are normally present after that, which would prevent the segfault. + A variant of this bug occurs when the match type also has no argument of its + own. In either case the segfault is caused by referring to absent tag + arguments, which causes a NULL dereference. + +M src/lib-sieve/plugins/relational/ext-relational-common.c +M tests/extensions/relational/errors.svtest +A tests/extensions/relational/errors/syntax.sieve + +2020-06-17 23:54:17 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (0b96fb53) + + lib-sieve: plugins: relational: Reformat ext-relational-common.h. + + +M src/lib-sieve/plugins/relational/ext-relational-common.h + +2020-06-17 23:53:56 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (81083e3e) + + lib-sieve: plugins: relational: Reformat ext-relational-common.c. + + +M src/lib-sieve/plugins/relational/ext-relational-common.c + +2020-05-20 02:03:17 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (1b9b5ce2) + + tests: plugins: extprograms: pipe/errors.svtest - Fix "Timeout" test. + + +M tests/plugins/extprograms/pipe/errors.svtest + +2020-05-07 14:44:12 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (1a8be20e) + + managesieve-login: proxy - Forward remote AUTHENTICATE TRYLATER failures + + +M src/managesieve-login/managesieve-proxy.c + +2020-05-06 20:37:03 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (bb5c14a1) + + managesieve-login: proxy: Reconnect on temporary authentication failures + + +M src/managesieve-login/managesieve-proxy.c + +2020-05-07 15:01:43 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (613eb103) + + managesieve-login: proxy - Parse AUTHENTICATE reply more correctly + + It's still not fully correct, but we don't have existing code that supports + parsing it. + +M src/managesieve-login/managesieve-proxy.c + +2020-05-06 20:40:14 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (b817b261) + + managesieve-login: Adjust to proxy_error() -> proxy_failed() API change + + +M src/managesieve-login/client.c +M src/managesieve-login/managesieve-proxy.c +M src/managesieve-login/managesieve-proxy.h + +2020-05-06 18:10:30 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (27bb1903) + + managesieve-login: Replace e_error()+client_proxy_failed() calls with + login_proxy_failed() + + +M src/managesieve-login/managesieve-proxy.c + +2020-05-06 16:54:15 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (7a6cc989) + + managesieve-login: Remove redundant/early freeing of proxy_password + + +M src/managesieve-login/managesieve-proxy.c + +2020-02-18 23:27:03 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (038274fe) + + global: Properly parse Message-ID header. + + Use mail_get_message_id() instead of just mail_get_first_header(). + +M src/lib-sieve/plugins/duplicate/tst-duplicate.c +M src/plugins/imap-filter-sieve/imap-filter-sieve.c +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-message.c + +2020-04-21 18:31:13 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (72bed3a5) + + testsuite: testsuite-message - Give all global variables a "testsuite_" + prefix. + + +M src/testsuite/testsuite-message.c + +2020-04-21 18:27:33 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (06b29fd6) + + testsuite: Reformat testsuite-message.h. + + +M src/testsuite/testsuite-message.h + +2020-04-21 18:25:38 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (6b2bc756) + + testsuite: Reformat testsuite-message.c. + + +M src/testsuite/testsuite-message.c + +2020-04-21 23:15:52 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (1bcf28c8) + + managesieve: Fix debug event's printf format type + + +M src/managesieve/cmd-havespace.c + +2020-04-24 13:05:01 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (6c81309a) + + managesieve-login: Correctly adjust to core login-common API changes. + + Previous commit was accidentally for an earlier version of the API change. + +M src/managesieve-login/client.c + +2020-04-10 01:02:50 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (568c72e7) + + managesieve-login: Adjust to core login-common API changes. + + +M src/managesieve-login/client.c +M src/managesieve-login/managesieve-proxy.c + +2020-04-05 01:25:02 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (464a0f92) + + lib-sieve: Use "sieve" category as parent for "sieve-*" categories + + +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-execute.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-storage.c + +2020-03-11 15:43:47 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (7b97795e) + + managesieve: Change managesieve_max_line_length setting type to "size" + + +M src/managesieve/managesieve-settings.c +M src/managesieve/managesieve-settings.h + +2020-03-24 17:59:18 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (ff7d9089) + + global: Remove dead assignments + + Found by latest clang scan-build. + +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/sieve-message.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.c + +2020-03-24 17:56:20 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (da702576) + + plugins: imap-filter-sieve: SIEVE SCRIPT - Reorder if checks to remove + unnecessary indenting + + Nothing changes in the code logic. + +M src/plugins/imap-filter-sieve/cmd-filter-sieve.c + +2020-03-24 17:44:18 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (f69f9fe1) + + plugins: imap-filter-sieve: SIEVE SCRIPT - Cleanup istream return value + checking + + The old code seems to have worked correctly already, but now it's a bit + clearer how it was intended to work. + +M src/plugins/imap-filter-sieve/cmd-filter-sieve.c + +2020-03-24 17:40:28 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (919704e7) + + lib-sieve: plugins: body: Fix compiler warning + + Fixes "warning: cast to smaller integer type" with new clang. + +M src/lib-sieve/plugins/body/tst-body.c + +2020-03-17 09:33:24 -0400 Josef 'Jeff' Sipek <jeff.sipek@open-xchange.com> (301a5c44) + + global: use %zu directly instead of PRIuSIZE_T + + +M src/lib-managesieve/managesieve-arg.c +M src/lib-managesieve/managesieve-quote.c +M src/lib-sieve/plugins/editheader/cmd-addheader.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/storage/ldap/sieve-ldap-db.c +M src/managesieve/cmd-havespace.c +M src/managesieve/managesieve-quota.c +M src/plugins/imap-filter-sieve/cmd-filter-sieve.c +M src/plugins/imap-filter-sieve/imap-filter.c + +2020-03-09 14:54:04 +0200 Aki Tuomi <aki.tuomi@open-xchange.com> (5992e367) + + NEWS: Fix news for 0.5.10 + + +M NEWS + +2020-03-03 13:59:43 +0200 Aki Tuomi <aki.tuomi@open-xchange.com> (2e6a4515) + + NEWS: Add news for v0.5.10 + + +M NEWS + +2019-11-29 13:38:53 +0200 Aki Tuomi <aki.tuomi@open-xchange.com> (9c520dcf) + + NEWS: Add news for v0.5.9 + + +M NEWS + +2019-11-29 13:34:40 +0200 Aki Tuomi <aki.tuomi@open-xchange.com> (fec11941) + + NEWS: Sync missing news from v0.5.7-v0.5.8 + + +M NEWS + +2020-02-07 11:21:15 +0200 Aki Tuomi <aki.tuomi@open-xchange.com> (3bcdac3a) + + Update m4 from core + + +M m4/dovecot.m4 + +2020-01-24 23:43:57 +0200 Timo Sirainen <timo.sirainen@open-xchange.com> (7b16a827) + + lib-sieve: Replace gettimeofday() calls with i_gettimeofday() + + +M src/lib-sieve/sieve-message.c +M src/lib-sieve/storage/file/sieve-file-storage-active.c +M src/lib-sieve/storage/ldap/sieve-ldap-db.c + +2020-01-07 22:16:19 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (408aa45c) + + plugins: imap-filter-sieve: Add IMAP UID prefix to result action log + messages. + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2020-01-07 22:15:38 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (d6b55a3d) + + plugins: imapsieve: Add IMAP UID prefix to result action log messages. + + +M src/plugins/imapsieve/imap-sieve.c + +2020-01-07 22:21:19 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (4610f795) + + plugins: lda-sieve: Also amend debug messages with Message-ID prefix. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2020-01-07 22:10:21 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (818655d4) + + plugins: imapsieve: Make current mail available in struct + imap_sieve_context. + + +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/imapsieve/imap-sieve.h + +2020-01-07 22:07:46 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (fa882b62) + + plugins: imap-filter-sieve: Make current mail available in struct + imap_filter_sieve_context. + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c +M src/plugins/imap-filter-sieve/imap-filter-sieve.h + +2020-01-07 22:13:53 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (895b035a) + + lib-sieve: Add flag that determines whether result actions are logged as + debug or info. + + Default is now debug logging, which is used for the IMAP plugins. The LDA + Sieve plugin uses info logging. + +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-types.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c + +2020-01-05 17:54:20 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (23de7368) + + sieve-tools: Reformat sieve-filter.c. + + +M src/sieve-tools/sieve-filter.c + +2020-01-05 17:27:02 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (8df0409c) + + sieve-tools: Reformat sieve-test.c. + + +M src/sieve-tools/sieve-test.c + +2019-10-06 17:13:02 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (f5993afe) + + plugins: imapsieve: imap-sieve-storage - Fix bug in composing the sorted + rule array. + + When no insertion point was found, it would always insert the new rule at + the beginning, rather than at the end. + +M src/plugins/imapsieve/imap-sieve-storage.c + +2019-12-11 10:23:45 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (4efeaa21) + + lib-sieve: plugins: vacation: cmd-vacation - Perform all address comparisons + case-insensitively. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M tests/extensions/vacation/reply.svtest + +2019-12-10 21:46:53 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (87d7c1ee) + + lib-sieve: plugins: vacation: cmd-vacation - Consolidate message address + comparison in separate function. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2019-12-08 13:40:28 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (ef3509c3) + + lib-sieve: plugins: vacation: cmd-vacation - Restructure + _get_full_reply_recipient(). + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2019-12-08 13:29:24 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (400566cc) + + lib-sieve: plugins: vacation: cmd-vacation - Restructure + _contains_my_address(). + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2019-11-27 15:45:25 -0500 Josef 'Jeff' Sipek <jeff.sipek@open-xchange.com> (2774971b) + + sieve: Change rename event's script name fields for consistency + + Core is using {old,new}_foo for the RENAME IMAP command event, so let's + follow suit. + +M src/lib-sieve/sieve-script.c + +2019-11-27 15:27:57 -0500 Josef 'Jeff' Sipek <jeff.sipek@open-xchange.com> (3fcbfe87) + + managesieve: Change rename event's script name fields for consistency + + Core is using {old,new}_foo for the RENAME IMAP command event, so let's + follow suit. + +M src/managesieve/cmd-renamescript.c + +2019-11-13 15:17:18 -0500 Josef 'Jeff' Sipek <jeff.sipek@open-xchange.com> (e0d24a23) + + global: Remove sieve_ event field prefixes + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-storage.c +M src/managesieve/cmd-putscript.c +M src/managesieve/cmd-setactive.c +M src/plugins/sieve-extprograms/cmd-pipe.c + +2019-11-13 14:57:30 -0500 Josef 'Jeff' Sipek <jeff.sipek@open-xchange.com> (0828b452) + + global: Remove managesieve_ event field prefixes + + +M src/managesieve/cmd-deletescript.c +M src/managesieve/cmd-getscript.c +M src/managesieve/cmd-havespace.c +M src/managesieve/cmd-putscript.c +M src/managesieve/cmd-renamescript.c +M src/managesieve/cmd-setactive.c +M src/managesieve/managesieve-client.c + +2018-08-28 23:02:03 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (775c6d60) + + plugins: imap-filter-sieve: Add headers to trace log file. + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2019-10-29 10:16:10 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (71853c63) + + plugins: imap-filter-sieve: Restructure imap_filter_sieve_init_trace_log(). + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2018-08-28 23:01:44 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (4f77ad35) + + plugins: imapsieve: Add headers to trace log file. + + +M src/plugins/imapsieve/imap-sieve.c + +2019-10-29 10:06:09 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (e8ddc4a0) + + plugins: imapsieve: Restructure imap_sieve_run_init_trace_log(). + + +M src/plugins/imapsieve/imap-sieve.c + +2018-08-28 23:00:46 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (c338c755) + + plugins: lda-sieve: Add header to trace log file. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2019-10-29 10:01:55 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (e22d9fff) + + plugins: lda-sieve: Initialize trace log in a separate function. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2018-08-28 23:22:30 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (43eb04ee) + + plugins: imap-filter-sieve: Create a single trace file for a single IMAP + command. + + Before, it created a separate trace file for each individual filtered + message. + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c +M src/plugins/imap-filter-sieve/imap-filter-sieve.h + +2018-08-28 23:08:06 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (d285de14) + + plugins: imapsieve: Create a single trace file for a single IMAP command. + + Before, it created a separate trace file for each individual filtered + message. + +M src/plugins/imapsieve/imap-sieve.c + +2018-08-29 00:21:22 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (035f23f0) + + plugins: imap-filter-sieve: Make filter context available in Sieve context. + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c +M src/plugins/imap-filter-sieve/imap-filter-sieve.h + +2018-08-28 22:01:38 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (12178738) + + lib-sieve: Add sieve_trace_log_printf(), which allows writing to the trace + log directly. + + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h + +2018-08-28 21:43:14 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (806ac6d5) + + lib-sieve: Remove optional label from trace log file name. + + It is generally a bad idea to add a potentially unlimited string to a + filename, especially when it contains a mailbox name. + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/imap-filter-sieve/imap-filter-sieve.c +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2019-10-29 21:48:40 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (9c24ea28) + + plugins: imapsieve: Reformat imap-sieve.c. + + +M src/plugins/imapsieve/imap-sieve.c + +2019-10-28 22:40:17 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (fbfd773f) + + managesieve: cmd-setactive - Add event fields for compile errors and + warnings. + + +M src/managesieve/cmd-setactive.c + +2019-10-28 22:33:50 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (d558b050) + + managesieve: cmd-setactive - Add "error" event field for all error events. + + Before, only storage errors had the "error" field set. + +M src/managesieve/cmd-setactive.c + +2019-10-28 22:38:08 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (31b09187) + + managesieve: cmd-putscript - Add event fields for compile errors and + warnings. + + +M src/managesieve/cmd-putscript.c + +2019-10-28 22:32:33 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (abd18dbc) + + managesieve: cmd-putscript - Add "error" event field for all error events. + + Before, only storage errors had the "error" field set. + +M src/managesieve/cmd-putscript.c + +2019-10-28 22:21:59 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (9cfb06c7) + + managesieve: managesieve-quota - Add "error" field for the command event + when the quota check fails. + + +M src/managesieve/managesieve-quota.c + +2019-10-28 22:17:49 +0100 Stephan Bosch <stephan.bosch@open-xchange.com> (75da0600) + + managesieve: managesieve-client - Rename "args" command event field to + "managesieve_command_args". + + This makes more sense with the managesieve_command_name field. + +M src/managesieve/managesieve-client.c + +2019-10-22 21:47:23 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (1dc7b2bc) + + managesieve: Emit command events. + + +M src/managesieve/cmd-deletescript.c +M src/managesieve/cmd-getscript.c +M src/managesieve/cmd-havespace.c +M src/managesieve/cmd-listscripts.c +M src/managesieve/cmd-putscript.c +M src/managesieve/cmd-renamescript.c +M src/managesieve/cmd-setactive.c +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h +M src/managesieve/managesieve-quota.c + +2019-10-23 22:16:22 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (286bb6f1) + + managesieve: cmd-putscript - Handle storage error in a common function. + + +M src/managesieve/cmd-putscript.c + +2019-10-23 22:11:47 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (06793ee3) + + managesieve: managesieve-quota - Use command context rather than client as + parameter. + + +M src/managesieve/cmd-havespace.c +M src/managesieve/cmd-putscript.c +M src/managesieve/managesieve-quota.c +M src/managesieve/managesieve-quota.h + +2019-10-16 23:58:23 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (969386f5) + + managesieve: managesieve-client - Use client event for Sieve storage. + + +M src/managesieve/managesieve-client.c + +2018-08-02 10:01:04 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (6e17ae3d) + + managesieve: Add client_command_context.event and use it as global event + while running. + + +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h + +2018-08-02 09:44:12 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (94c84bed) + + managesieve: Add client.event and use it as mail_*user's parent event. + + +M src/managesieve/main.c +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h +M src/managesieve/managesieve-common.h + +2019-10-17 23:28:31 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (292a46a9) + + managesieve: Store command args to client command contexts for debugging + purposes. + + +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h + +2019-10-24 01:04:39 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (cc73a587) + + lib-sieve: sieve-storage - Emit events for saving Sieve scripts. + + +M src/lib-sieve/sieve-storage-private.h +M src/lib-sieve/sieve-storage.c + +2019-10-24 00:41:00 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (2ae307bd) + + lib-sieve: sieve-storage - Emit event for storage deactivation. + + +M src/lib-sieve/sieve-storage.c + +2019-10-24 14:37:04 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (af2b31cc) + + lib-sieve: sieve-storage - Better keep track of whether saving a script has + failed. + + +M src/lib-sieve/sieve-storage.c + +2019-10-23 23:41:10 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (c0c04bbc) + + lib-sieve: sieve-script - Emit events for various script manipulations. + + +M src/lib-sieve/sieve-script.c + +2019-10-23 23:45:16 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (69959aad) + + lib-sieve: sieve-script - Split off sieve_script_copy_from_default() from + sieve_script_rename(). + + +M src/lib-sieve/sieve-script.c + +2019-10-23 22:50:05 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (a8f74fee) + + lib-sieve: sieve-script - Add more event fields. + + +M src/lib-sieve/sieve-script.c + +2019-10-23 22:57:34 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (2b0bdd68) + + lib-sieve: sieve-script - Use sieve-storage event as event parent. + + +M src/lib-sieve/sieve-script.c + +2019-10-24 00:16:43 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (397a184b) + + lib-sieve: sieve-storage - Add more event fields. + + +M src/lib-sieve/sieve-storage.c + +2019-10-24 00:07:00 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (f832fcf5) + + lib-sieve: sieve-storage - Add sieve-storage event category. + + +M src/lib-sieve/sieve-storage.c + +2019-10-24 15:21:56 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (9326853d) + + lib-sieve: sieve-storage - Restructure alloc/free of script save context. + + +M src/lib-sieve/sieve-storage-private.h +M src/lib-sieve/sieve-storage.c +M src/lib-sieve/storage/file/sieve-file-storage-save.c +M src/lib-sieve/storage/file/sieve-file-storage.c +M src/lib-sieve/storage/file/sieve-file-storage.h + +2019-10-17 23:26:05 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (a69a0c1d) + + lib-managesieve: managesieve-arg - Add functions for converting an argument + list to a string. + + +M src/lib-managesieve/managesieve-arg.c +M src/lib-managesieve/managesieve-arg.h + +2019-10-22 22:34:56 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (527e75dc) + + managesieve: cmd-deletescript - Restructure cmd_deletescript(). + + +M src/managesieve/cmd-deletescript.c + +2019-10-22 21:51:29 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (90262f2e) + + managesieve: cmd-setactive - Remove empty line from + cmd_setactive_activate(). + + +M src/managesieve/cmd-setactive.c + +2019-10-22 22:28:08 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (ed8cfba4) + + lib-sieve: sieve-script - sieve_script_unref(NULL) should be a no-op. + + +M src/lib-sieve/sieve-script.c + +2019-10-22 20:31:42 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (0e2806aa) + + lib-managesieve: Reformat managesieve-arg.c. + + +M src/lib-managesieve/managesieve-arg.c + +2019-10-22 20:27:52 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (a71cf469) + + lib-managesieve: Reformat managesieve-arg.h. + + +M src/lib-managesieve/managesieve-arg.h + +2019-10-20 14:49:48 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (1f6c2662) + + managesieve: cmd-setactive - Restructure cmd_setactive(). + + +M src/managesieve/cmd-setactive.c + +2019-10-20 14:37:58 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (5b0b3317) + + managesieve: cmd-putscript - Restructure cmd_putscript_finish_parsing(). + + +M src/managesieve/cmd-putscript.c + +2019-10-20 14:14:34 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (6efa7b09) + + managesieve: cmd-capability - Restructure cmd_capability(). + + +M src/managesieve/cmd-capability.c + +2019-10-20 14:10:59 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (ae9301db) + + managesieve: managesieve-quota - Restructure managesieve_quota_check_all(). + + +M src/managesieve/managesieve-quota.c + +2019-10-20 14:06:38 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (5d231d8e) + + managesieve: Reformat managesieve-commands.c. + + +M src/managesieve/managesieve-commands.c + +2019-10-20 14:05:09 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (21d3fba3) + + managesieve: Reformat managesieve-settings.c. + + +M src/managesieve/managesieve-settings.c + +2019-10-20 14:03:22 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (f2f157a3) + + managesieve: Reformat managesieve-capabilities.c. + + +M src/managesieve/managesieve-capabilities.c + +2019-10-20 14:00:59 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (24bd78e0) + + managesieve: Reformat managesieve-quota.h. + + +M src/managesieve/managesieve-quota.h + +2019-10-20 14:00:16 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (2ae19412) + + managesieve: Reformat managesieve-quota.c. + + +M src/managesieve/managesieve-quota.c + +2019-10-20 13:57:32 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (6d6603da) + + managesieve: Reformat cmd-setactive.c. + + +M src/managesieve/cmd-setactive.c + +2019-10-20 13:53:05 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (1ee76ad6) + + managesieve: Reformat cmd-renamescript.c. + + +M src/managesieve/cmd-renamescript.c + +2019-10-20 13:52:22 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (60d31c4a) + + managesieve: Reformat cmd-putscript.c. + + +M src/managesieve/cmd-putscript.c + +2019-10-20 13:43:51 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (4b3e8629) + + managesieve: Reformat cmd-noop.c. + + +M src/managesieve/cmd-noop.c + +2019-10-20 13:43:08 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (55507ca6) + + managesieve: Reformat cmd-logout.c. + + +M src/managesieve/cmd-logout.c + +2019-10-20 13:42:39 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (36babb7a) + + managesieve: Reformat cmd-capability.c. + + +M src/managesieve/cmd-capability.c + +2019-10-20 13:39:24 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (c42bf0f9) + + managesieve: Reformat cmd-listscripts.c. + + +M src/managesieve/cmd-listscripts.c + +2019-10-20 13:38:13 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (e214f94e) + + managesieve: Reformat cmd-havespace.c. + + +M src/managesieve/cmd-havespace.c + +2019-10-20 13:36:41 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (d11a7ee3) + + managesieve: Reformat cmd-getscript.c. + + +M src/managesieve/cmd-getscript.c + +2019-10-20 13:33:04 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (44a58eee) + + managesieve: Reformat cmd-deletescript.c. + + +M src/managesieve/cmd-deletescript.c + +2019-10-16 23:04:49 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (4e47d097) + + managesieve: Reformat main.c. + + +M src/managesieve/main.c + +2019-10-16 22:59:17 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (e75d0fe3) + + managesieve: Reformat managesieve-client.h. + + +M src/managesieve/managesieve-client.h + +2019-10-16 22:55:46 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (41778e8d) + + managesieve: Reformat managesieve-client.c. + + +M src/managesieve/managesieve-client.c + +2019-10-13 13:52:59 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (de1f2da7) + + lib-sieve: plugins: special-use: tag-special-use - Fix handling of variable + argument. + + The use of a variable substitution erroneously produced a runtime syntax + error. + +M src/lib-sieve/plugins/special-use/tag-specialuse.c +M tests/extensions/special-use/execute.svtest + +2019-10-13 13:36:51 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (5abbfb0f) + + lib-sieve: plugins: special-use: tag-special-use - Fix error message + prefixes. + + +M src/lib-sieve/plugins/special-use/tag-specialuse.c + +2019-10-13 13:34:13 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (024dd76e) + + lib-sieve: plugins: special-use: ext-special-use-common.h - Fix comment. + + +M src/lib-sieve/plugins/special-use/ext-special-use-common.h + +2019-10-13 13:30:36 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (e4d5748f) + + lib-sieve: plugins: special-use: ext-special-use - Fix extension status + information. + + +M src/lib-sieve/plugins/special-use/ext-special-use.c + +2019-10-10 15:36:28 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (fa3da3a5) + + lib-sieve: sieve-actions - Fix autocreate and autosubscribe for keep and + fileinto actions. + + This was broken by recent adjustments to changes in Dovecot lib-storage API. + +M src/lib-sieve/sieve-actions.c + +2016-10-03 16:51:46 +0200 Stephan Bosch <stephan@dovecot.fi> (1cda7a5b) + + lib-sieve: Implement support for the "special-use" extension. + + +M Makefile.am +M configure.ac +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/special-use/Makefile.am +A src/lib-sieve/plugins/special-use/ext-special-use-common.c +A src/lib-sieve/plugins/special-use/ext-special-use-common.h +A src/lib-sieve/plugins/special-use/ext-special-use.c +A src/lib-sieve/plugins/special-use/tag-specialuse.c +A src/lib-sieve/plugins/special-use/tst-specialuse-exists.c +M src/lib-sieve/sieve-extensions.c +A tests/extensions/special-use/errors.svtest +A tests/extensions/special-use/errors/syntax.sieve +A tests/extensions/special-use/execute.svtest + +2017-10-02 00:20:19 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (3acd20dd) + + lib-sieve: store action: Don't open the mailbox until act_store_execute(). + + This allows side-effects to open a different mailbox than what is allocated + initially in act_store_start(). + +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/sieve-actions.c + +2017-10-02 01:07:59 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (2298ecf1) + + lib-sieve: store action: Properly allocate error in act_store_start(). + + +M src/lib-sieve/sieve-actions.c + +2017-10-02 00:59:49 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (5d3b67f3) + + lib-sieve: store action: Allow side-effects to change the mailbox identifier + used in action logging. + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h + +2017-10-02 00:47:40 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (afa5e258) + + lib-sieve: plugins: mailbox: tag-mailbox-create - Add variable for + trans->box in seff_mailbox_create_pre_execute(). + + +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c + +2017-10-02 00:45:15 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (763607ed) + + lib-sieve: sieve-actions - Add variable for trans->box in + act_store_execute(). + + +M src/lib-sieve/sieve-actions.c + +2017-10-02 00:39:34 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (550f90f5) + + lib-sieve: sieve-actions - Move recording of the last used storage to an + earlier instance. + + +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/sieve-actions.c + +2017-10-02 00:13:28 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (b29e683d) + + lib-sieve: store action: Improve sieve_act_store_get_storage_error(). + + Use mailbox_get_last_error() shorthand rather than + mail_storage_get_last_error(). + +M src/lib-sieve/sieve-actions.c + +2017-10-02 00:06:54 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (b540702e) + + lib-sieve: store action: Move checking of keywords to the result execution. + + This way, the mailbox does not need to be opened until result execution. + +M src/lib-sieve/sieve-actions.c + +2017-10-01 23:56:17 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (f578b181) + + lib-sieve: plugins: mailbox: Use the new mailbox_alloc_for_user() for the + mailboxexists test. + + By setting the MAILBOX_FLAG_POST_SESSION flag, this makes sure the result + of this test closely matches what would happen for a real delivery action + using + "fileinto". + +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c + +2017-10-01 23:46:46 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (b111fa06) + + lib-sieve: plugins: mailbox: tag-mailbox-create - Improve error handling. + + +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c + +2017-10-01 20:57:38 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (94f8e03a) + + lib-sieve: sieve-result - Sort action side effects based on precedence + value. + + This way, the execution order can be made explicit. + +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c + +2019-10-10 00:49:08 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (2208be4e) + + lib-sieve: sieve-error - Add sieve_error_from_external() utility function + and use it. + + +M src/lib-sieve/plugins/metadata/tst-metadata.c +M src/lib-sieve/plugins/metadata/tst-metadataexists.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-script.c + +2019-10-03 13:46:06 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (f69e172a) + + lib-sieve: Adjust to changes in Dovecot mailbox_alloc*() API. + + +M src/lib-sieve/sieve-actions.c + +2019-10-03 21:08:54 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (cf851a45) + + lib-sieve: sieve-message - Adjust to changes in Dovecot struct smtp_address. + + +M src/lib-sieve/sieve-message.c + +2018-09-18 23:54:18 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (72868144) + + plugins: imap-filter-sieve: Fix mixup between tag and problem part of the + FILTER response for compile error. + + +M src/plugins/imap-filter-sieve/cmd-filter-sieve.c + +2018-09-18 23:45:41 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (e8b9f4da) + + plugins: imap-filter-sieve: Perform main initialization of Sieve script + execution environment only once. + + This way, any configuration errors can be reported as a single FILTER ERRORS + response, rather than a FILTERED ERRORS response for each filtered message. + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c +M src/plugins/imap-filter-sieve/imap-filter-sieve.h +M src/plugins/imap-filter-sieve/imap-filter.c + +2018-09-18 22:39:38 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (6aecd317) + + plugins: imap-filter-sieve: Make sure user gets to see at least one error + when script execution fails. + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2019-05-17 10:39:25 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (10c5cbe8) + + lib-managesieve: Make sure str_unescape() won't be writing past allocated + memory + + The previous commit should already prevent this, but this makes sure it + can't become broken in the future either. It makes the performance a tiny + bit worse, but that's not practically noticeable. + +M src/lib-managesieve/managesieve-parser.c + +2019-05-10 19:43:55 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (16e047c5) + + lib-managesieve: Don't accept strings with NULs + + ManageSieve doesn't allow NULs in strings. + + This fixes a bug with unescaping a string with NULs: str_unescape() could + have been called for memory that points outside the allocated string, + causing heap corruption. This could cause crashes or theoretically even + result in remote code execution exploit. + + Found by Nick Roessler and Rafi Rubin + +M src/lib-managesieve/managesieve-parser.c + +2018-08-17 10:00:09 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (5cd8cfc1) + + lib-sieve: duplicate extension: Fix caching of duplicate checks to also + compare the actual hashes. + + Before, it only compared the handles, which would cause duplicate tests with + different values to be cached as the same duplicate test. + +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.c + +2019-08-12 22:35:51 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (36ff477b) + + managesieve-login: Remove duplicate code denying anonymous logins. + + Also explicitly initialize login_binary->anonymous_login_acceptable to FALSE + to make clear that anonymous logins are intentionally not allowed for + ManageSieve. + +M src/managesieve-login/client-authenticate.c +M src/managesieve-login/client.c + +2019-08-09 01:06:59 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (fcb23499) + + managesieve-login: client.c - Use designated initializer for struct + client_vfuncs. + + +M src/managesieve-login/client.c + +2019-07-31 22:50:57 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (e7babff7) + + lib-sieve: sieve-result - Assert that an action name is available in + _sieve_result_add_action(). + + Addresses a Coverity report. + +M src/lib-sieve/sieve-result.c + +2019-07-31 22:37:47 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (8cfd3ff6) + + global: Rename all sieve action events to a uniform "sieve_action_finished". + + The action name can be determined from the sieve_action_name field that + existed before. + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/sieve-actions.c +M src/plugins/sieve-extprograms/cmd-pipe.c + +2019-07-31 22:35:20 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (a16a56d8) + + lib-sieve: plugins: enotify: ext-enotify-common - Add + sieve_enotify_create_finish_event(). + + +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h + +2019-07-31 22:17:46 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (4d033fa2) + + lib-sieve: sieve-action - Add sieve_action_create_finish_event(). + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h + +2019-07-31 22:14:45 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (a69c8364) + + lib-sieve: sieve-action - Drop unused definition of + sieve_action_get_location() from header file. + + +M src/lib-sieve/sieve-actions.h + +2019-07-07 14:34:41 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (f64bd39b) + + plugins: imap-filter-sieve: imap-filter-sieve - Use imap client event as + parent for sieve event. + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2019-07-07 14:33:49 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (ae080252) + + plugins: imapsieve: imap-sieve - Use imap client event as parent for sieve + event. + + +M src/plugins/imapsieve/imap-sieve.c + +2019-07-07 14:33:01 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (2e459125) + + plugins: lda-sieve: lda-sieve-plugin - Use deliver event as parent for sieve + event. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2019-06-28 21:20:45 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (ed58d960) + + lib-sieve: Emit named event for successfully executed actions. + + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/sieve-actions.c +M src/plugins/sieve-extprograms/cmd-pipe.c + +2019-07-06 23:03:02 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (f459db4c) + + lib-sieve: sieve-interpreter - Emit events for start and finish of script + runtime. + + +M src/lib-sieve/sieve-interpreter.c + +2019-07-03 13:44:15 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (0e68299a) + + lib-sieve: sieve-error - Drop error handler hierarchy. + + It is no longer used. + +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c + +2019-07-03 13:34:35 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (04f40d52) + + lib-sieve: sieve-error - Drop prefix error handler. + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h + +2019-07-07 13:19:19 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (77a7010c) + + lib-sieve: plugins: enotify: Add sieve_enotify_event_log(). + + +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h + +2019-07-19 21:18:49 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (b3fb5d5d) + + lib-sieve: plugins: enotify: mailto: Use event API to handle the "mailto + URI" log prefix. + + +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c + +2019-07-19 21:18:08 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (399c1c53) + + lib-sieve: plugins: enotify: Use event API to handle the notify + command/action log prefix. + + +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h + +2019-07-19 20:27:08 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (c562b1ff) + + lib-sieve: plugins: enotify: mailto: uri-mailto - Restructure error + handling. + + Avoid using a Sieve error handler directly. + +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.h + +2019-07-03 21:58:39 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (6f744723) + + lib-sieve: sieve-result - Handle action log prefix at a central location + using the event. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/sieve-result.c +M src/plugins/sieve-extprograms/cmd-pipe.c + +2019-07-03 21:57:32 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (9a048328) + + lib-sieve: sieve-error - Compose both the event and the error handler log + message once using the event API. + + +M src/lib-sieve/sieve-error.c + +2019-07-03 17:06:44 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (8f6ccd14) + + lib-sieve: sieve-error - Change error handler log function to accept direct + message string. + + Before, it used format string and arguments. + +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/testsuite/testsuite-log.c + +2019-07-03 13:32:01 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (9178d40f) + + plugins: lda-sieve: Drop custom action error handler. + + +M src/plugins/lda-sieve/Makefile.am +D src/plugins/lda-sieve/lda-sieve-log.c +D src/plugins/lda-sieve/lda-sieve-log.h + +2019-07-03 13:29:11 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (b0354cc1) + + sieve-tools: sieve-test - Use the new result message amendment callback + rather than the prefix error handler. + + +M src/sieve-tools/sieve-test.c + +2019-07-03 13:26:28 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (9712e4dd) + + sieve-tools: sieve-filter - Use the new result message amendment callback + rather than the prefix error handler. + + +M src/sieve-tools/sieve-filter.c + +2019-07-03 13:24:01 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (c209f9ab) + + plugins: lda-sieve: Use the new result message amendment callback rather + than a special error handler. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2019-07-03 13:20:14 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (359188af) + + lib-sieve: sieve-result - Add support for amending result log messages. + + +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-types.h + +2019-06-27 13:35:55 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (bff3aee2) + + lib-sieve: sieve-result - Allow specifying an explicit name for actions + added to the result. + + Before it always used the name of the action definition, which is confusing + e.g. for the keep and fileinto actions, which both map to the same "store" + action definition. + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/plugins/sieve-extprograms/cmd-pipe.c + +2019-06-28 21:15:14 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (1d85af11) + + lib-sieve: sieve-result - Add sieve_result_event_log*(). + + This allows logging action messages through a different (child) event. + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2019-07-03 13:37:51 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (4cd9b2c2) + + lib-sieve: sieve-error - Add sieve_event_log(). + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h + +2019-07-03 13:08:54 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (14fcdf1f) + + lib-sieve: sieve-error - Make enum sieve_error_flags public. + + +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.h + +2019-06-22 22:12:37 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (8dd08fcd) + + lib-sieve: sieve-result - Define "sieve-action" event category. + + Applies to Sieve actions being executed. + +M src/lib-sieve/sieve-result.c + +2019-06-22 09:38:13 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (c52d25ad) + + lib-sieve: sieve-interpreter - Define "sieve-runtime" event category. + + Applies to Sieve scripts being evaluated before the actual action execution. + +M src/lib-sieve/sieve-interpreter.c + +2019-06-22 09:27:15 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (b538ebba) + + lib-sieve: sieve-execute - Define "sieve-execute" event category. + + Applies to Sieve scripts being executed in general. + +M src/lib-sieve/sieve-execute.c + +2019-06-22 09:25:06 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (054c2e85) + + lib-sieve: Define "sieve" event category. + + +M src/lib-sieve/sieve.c + +2019-06-22 18:05:17 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (cddd93d2) + + lib-sieve: sieve-result - Use action event for all action execution log + messages. + + +M src/lib-sieve/sieve-result.c + +2019-06-22 18:03:13 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (8e4bf3f6) + + lib-sieve: sieve-result - Add event support for individual actions. + + +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c + +2019-06-22 10:44:34 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (e937ff93) + + lib-sieve: sieve-interpreter - Use runtime event for all runtime log + messages. + + +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/tst-size.c + +2019-06-22 10:43:51 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (d6e84096) + + lib-sieve: sieve-error - Add support for logging through events other than + the main instance event. + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h + +2019-06-22 09:43:10 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (692f6ca4) + + lib-sieve: sieve-result - Add event support to action execute environment. + + +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c + +2019-06-22 09:30:39 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (39b6eb9c) + + lib-sieve: sieve-runtime - Add event support to runtime environment. + + +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-runtime.h + +2019-06-22 09:16:16 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (b539a50f) + + lib-sieve: sieve-execute - Add event support to execute environment. + + +M src/lib-sieve/sieve-execute.c +M src/lib-sieve/sieve-execute.h + +2019-07-07 13:36:55 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (2f398324) + + lib-sieve: Add username field to main instance event. + + +M src/lib-sieve/sieve.c + +2019-06-22 11:40:49 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (318c6a61) + + lib-sieve: sieve-actions - Remove action argument from action and + side-effect definition functions. + + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c +M src/plugins/sieve-extprograms/cmd-pipe.c + +2019-06-22 11:15:51 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (62913ca7) + + lib-sieve: sieve-actions - Add current action to action execution + environment. + + +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c + +2019-06-21 00:23:43 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (90ba06f3) + + lib-sieve: Handle init/deinit of execute context in separate functions. + + Always associate a pool with the execute context. + +M src/lib-sieve/Makefile.am +A src/lib-sieve/sieve-execute.c +M src/lib-sieve/sieve-execute.h +M src/lib-sieve/sieve.c +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-script.c + +2019-06-22 18:01:20 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (ada6ab95) + + lib-sieve: sieve-action - Add sieve_action_name() macro. + + +M src/lib-sieve/sieve-actions.h + +2019-07-06 23:04:55 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (f77fb4c7) + + lib-sieve: sieve-interpreter - Turn bools in struct sieve_interpreter into + bit fields. + + +M src/lib-sieve/sieve-interpreter.c + +2019-06-22 09:46:32 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (1db9c46a) + + lib-sieve: sieve-result - Make direct result pointer avalable as local + variable in sieve_result_unref(). + + +M src/lib-sieve/sieve-result.c + +2019-07-16 23:59:09 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (5a00d2ff) + + lib-sieve: sieve-erorr - Add sieve_internal_error_params() and use it. + + This allows passing error parameters struct from sieve_critical*(). + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h + +2019-06-29 09:59:18 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (7a677e81) + + lib-sieve: sieve-error - Compose message prefixes in a single place for all + error handler variants. + + +M src/lib-sieve/sieve-error.c + +2019-06-28 21:07:05 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (e1d909c5) + + lib-sieve: sieve-error - Remove varexpand error handler. + + It is no longer used. + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h + +2019-07-03 21:23:34 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (688f8a2e) + + testsuite: testsuite-log - Change error message structure to match rest of + Pigeonhole. + + +M src/testsuite/testsuite-log.c + +2019-06-22 16:41:16 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (6b5cb2e5) + + testsuite: testsuite-log - Uninstall testsuite error handler upon deinit. + + This prevents segfaults e.g. when dovecot/lib wants to log errors at + lib_deinit(). + +M src/testsuite/testsuite-log.c + +2019-07-17 12:33:09 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (382b1eac) + + doveadm-sieve: Shared attribute iteration shouldn't list Sieve scripts + + Trying to get them as shared instead of as private resulted in failure. + +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c + +2019-07-09 22:39:35 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (c7c3e55a) + + lib-sieve: plugins: vnd.dovecot: report: cmd-report - Fix resource leak + occurring when the SMTP submission fails. + + Properly abort the SMTP transaction upon failure. + +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c + +2019-07-09 22:38:14 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (65491e1b) + + lib-sieve: plugins: vacation: cmd-vacation - Fix resource leak occurring + when the SMTP submission fails. + + Properly abort the SMTP transaction upon failure. + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2019-07-09 22:36:15 +0200 Stephan Bosch <stephan.bosch@open-xchange.com> (2fda1f95) + + lib-sieve: cmd-redirect - Fix resource leak occurring when the SMTP + submission fails. + + Properly abort the SMTP transaction upon failure. + +M src/lib-sieve/cmd-redirect.c + +2019-06-17 23:26:25 +0300 Martti Rannanjärvi <martti.rannanjarvi@open-xchange.com> (b1198f7b) + + lib-sieve: storage: file: sieve-file-storage-save - Fix error message to + include the intended path value rather than NULL. + + +M src/lib-sieve/storage/file/sieve-file-storage-save.c + +2019-06-18 10:59:24 +0300 Martti Rannanjärvi <martti.rannanjarvi@open-xchange.com> (cf66d379) + + lib-sieve: Expand SMTP_ADDRESS_LITERAL() macro + + This makes the use of compound literal explicit. + +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-message.c + +2019-06-18 10:56:11 +0300 Martti Rannanjärvi <martti.rannanjarvi@open-xchange.com> (68472b3c) + + testsuite: Fix invalid compound literal use + + The lifetime of compound literals changes in gcc 9, and the old one + segfaults there. + +M src/testsuite/testsuite-message.c + +2019-06-18 10:40:52 +0300 Martti Rannanjärvi <martti.rannanjarvi@open-xchange.com> (70834d27) + + testsuite: Expand SMTP_ADDRESS_LITERAL() macro + + This makes the use of compound literal explicit. + +M src/testsuite/testsuite-message.c + +2019-05-27 20:48:43 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (d30a8dee) + + lib-sieve: Use common context for both script evaluation and action + execution. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.c +M src/lib-sieve/plugins/duplicate/tst-duplicate.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/ihave/tst-ihave.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/metadata/tst-metadata.c +M src/lib-sieve/plugins/metadata/tst-metadataexists.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-items.c +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-common.h +A src/lib-sieve/sieve-execute.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-runtime.h +M src/lib-sieve/sieve.c +M src/lib-sieve/tst-size.c +M src/plugins/imapsieve/ext-imapsieve-environment.c +M src/plugins/sieve-extprograms/cmd-execute.c +M src/plugins/sieve-extprograms/cmd-filter.c +M src/plugins/sieve-extprograms/cmd-pipe.c +M src/testsuite/cmd-test-config.c +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-result.h +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite.c + +2019-05-27 22:45:15 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (3ca5c4ed) + + testsuite: Reformat cmd-test-config.c. + + +M src/testsuite/cmd-test-config.c + +2019-05-27 20:50:04 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (159e8e9e) + + testsuite: Reformat testsuite-result.h. + + +M src/testsuite/testsuite-result.h + +2019-05-27 20:45:49 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (2a3b0472) + + testsuite: Reformat testsuite-result.c. + + +M src/testsuite/testsuite-result.c + +2019-05-27 21:01:23 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (75a5b17f) + + testsuite: Reformat testsuite-script.h. + + +M src/testsuite/testsuite-script.h + +2019-05-27 20:33:51 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (b46bd650) + + testsuite: Reformat testsuite-script.c. + + +M src/testsuite/testsuite-script.c + +2019-05-27 20:23:36 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (e2700a46) + + testsuite: Reformat testsuite.c. + + +M src/testsuite/testsuite.c + +2019-05-28 21:49:40 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (02b7ad0c) + + plugins: sieve-extprograms: Reformat cmd-pipe.c. + + +M src/plugins/sieve-extprograms/cmd-pipe.c + +2019-05-28 21:33:38 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (49e2334c) + + plugins: sieve-extprograms: Reformat cmd-filter.c. + + +M src/plugins/sieve-extprograms/cmd-filter.c + +2019-05-28 21:14:46 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (a8bf5d38) + + plugins: sieve-extprograms: Reformat cmd-execute.c. + + +M src/plugins/sieve-extprograms/cmd-execute.c + +2019-05-28 20:43:04 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (647e7c67) + + plugins: imapsieve: Reformat ext-imapsieve-environment.c. + + +M src/plugins/imapsieve/ext-imapsieve-environment.c + +2019-05-30 01:03:01 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (9f696496) + + lib-sieve: plugins: vnd.dovecot: report: Reformat cmd-report.c. + + +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c + +2019-05-30 00:31:18 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (588d8322) + + lib-sieve: plugins: vnd.dovecot: environment: Reformat + ext-vnd-environment-items.c. + + +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-items.c + +2019-05-30 00:27:49 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (9692ec74) + + lib-sieve: plugins: variables: Reformat ext-variables-common.h. + + +M src/lib-sieve/plugins/variables/ext-variables-common.h + +2019-05-30 00:23:33 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (efc85b7c) + + lib-sieve: plugins: variables: Reformat ext-variables-common.c. + + +M src/lib-sieve/plugins/variables/ext-variables-common.c + +2019-05-30 00:00:07 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (22212e16) + + lib-sieve: plugins: vacation: Reformat cmd-vacation.c. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2019-05-29 23:13:41 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (f339c68d) + + lib-sieve: plugins: vacation: Reformat ext-vacation.c. + + +M src/lib-sieve/plugins/vacation/ext-vacation.c + +2019-05-29 02:04:44 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (afebb6bb) + + lib-sieve: plugins: notify: Reformat cmd-notify.c. + + +M src/lib-sieve/plugins/notify/cmd-notify.c + +2019-05-29 02:08:57 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (7fb079f3) + + lib-sieve: plugins: notify: Reformat ext-notify-common.h. + + +M src/lib-sieve/plugins/notify/ext-notify-common.h + +2019-05-29 01:40:17 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (e1f0de5c) + + lib-sieve: plugins: notify: Reformat ext-notify-common.c. + + +M src/lib-sieve/plugins/notify/ext-notify-common.c + +2019-05-29 01:29:24 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (4bb6061e) + + lib-sieve: plugins: metadata: Reformat tst-metadataexists.c. + + +M src/lib-sieve/plugins/metadata/tst-metadataexists.c + +2019-05-29 01:14:51 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (4135e8f4) + + lib-sieve: plugins: metadata: Reformat tst-metadata.c. + + +M src/lib-sieve/plugins/metadata/tst-metadata.c + +2019-05-29 00:54:28 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (ca727928) + + lib-sieve: plugins: mailbox: Reformat tst-mailboxexists.c. + + +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c + +2019-05-29 00:37:52 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (42ade3f1) + + lib-sieve: plugins: mailbox: Reformat tag-mailbox-create.c. + + +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c + +2019-05-29 23:03:23 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (6f2ea423) + + lib-sieve: plugins: include: Reformat ext-include-common.h. + + +M src/lib-sieve/plugins/include/ext-include-common.h + +2019-05-29 00:24:20 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (7f516a65) + + lib-sieve: plugins: include: Reformat ext-include-common.c. + + +M src/lib-sieve/plugins/include/ext-include-common.c + +2019-05-28 23:55:49 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (ee7fef8e) + + lib-sieve: plugins: ihave: Reformat tst-ihave.c. + + +M src/lib-sieve/plugins/ihave/tst-ihave.c + +2019-05-29 22:57:26 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (dc00dd6a) + + lib-sieve: plugins: environment: Reformat ext-environment-common.h. + + +M src/lib-sieve/plugins/environment/ext-environment-common.h + +2019-05-28 23:44:48 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (8f68dd73) + + lib-sieve: plugins: environment: Reformat ext-environment-common.c. + + +M src/lib-sieve/plugins/environment/ext-environment-common.c + +2019-05-28 23:33:04 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (633ba5fc) + + lib-sieve: plugins: enotify: Reformat cmd-notify.c. + + +M src/lib-sieve/plugins/enotify/cmd-notify.c + +2019-05-29 22:54:29 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (e86147eb) + + lib-sieve: plugins: enotify: Reformat ext-enotify-common.h. + + +M src/lib-sieve/plugins/enotify/ext-enotify-common.h + +2019-05-28 23:13:24 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (15f41903) + + lib-sieve: plugins: enotify: Reformat ext-enotify-common.c. + + +M src/lib-sieve/plugins/enotify/ext-enotify-common.c + +2019-05-28 22:26:46 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (71604b93) + + lib-sieve: plugins: duplicate: Reformat tst-duplicate.c. + + +M src/lib-sieve/plugins/duplicate/tst-duplicate.c + +2019-05-29 02:10:24 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (441a41fb) + + lib-sieve: plugins: duplicate: Reformat ext-duplicate-common.h. + + +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.h + +2019-05-28 22:06:34 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (b895fd46) + + lib-sieve: plugins: duplicate: Reformat ext-duplicate-common.c. + + +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.c + +2019-05-27 22:28:11 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (1884824f) + + lib-sieve: Reformat tst-size.c. + + +M src/lib-sieve/tst-size.c + +2019-05-27 22:16:48 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (dcb7aafa) + + lib-sieve: Reformat ext-reject.c. + + +M src/lib-sieve/ext-reject.c + +2019-05-27 21:58:48 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (3ff73e55) + + lib-sieve: Reformat ext-envelope.c. + + +M src/lib-sieve/ext-envelope.c + +2019-05-27 21:34:59 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (7ae7d35e) + + lib-sieve: Reformat cmd-redirect.c. + + +M src/lib-sieve/cmd-redirect.c + +2019-05-27 21:19:33 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (caf973d4) + + lib-sieve: Reformat cmd-discard.c. + + +M src/lib-sieve/cmd-discard.c + +2019-05-22 23:35:14 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (cd091d47) + + lib-sieve: Reformat sieve-actions.c. + + +M src/lib-sieve/sieve-actions.c + +2019-05-22 22:55:46 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (eff1beea) + + lib-sieve: Reformat sieve-actions.h. + + +M src/lib-sieve/sieve-actions.h + +2019-05-27 09:43:25 +0300 Aki Tuomi <aki.tuomi@open-xchange.com> (0e91911d) + + doveadm-sieve: Fix script synchronization + + When dsyncing, this codepath is always called with prefix "". There is no + point checking the prefix at all. + + Broken in 479c5e57046dec76078597df844daccbfc0eb75f + +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c + +2019-05-16 10:44:12 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (cf4e2004) + + doc: example-config: Remove recipient_delimiter + + It defaults to the global recipient_delimiter, which should always be used + anyway. Don't add confusion by documenting the legacy setting that only + exists for backwards compatibility. + +M doc/example-config/conf.d/90-sieve.conf + +2019-05-09 13:38:15 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (83ff4c7f) + + doc: draft-bosch-imap-filter-sieve-00.txt - update FILTERED replies and + editheader+keep + + +M doc/rfc/draft-bosch-imap-filter-sieve-00.txt + +2019-05-15 13:25:44 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (a77eb7f0) + + lib-sieve: sieve-error - Simplify if-statement for global logging + sieve_direct_logv(). + + Use local variables to pre-declare conditions that are used more than once. + +M src/lib-sieve/sieve-error.c + +2019-05-14 23:22:09 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (260d7bb5) + + lib-sieve: sieve-error - Fix NULL value dereference in sieve_direct_logv(). + + Caused by recent event API changes. + +M src/lib-sieve/sieve-error.c + +2019-05-15 13:13:37 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (d26d5726) + + lib-sieve: sieve-error - Restore condition that got erroneously removed in + sieve_direct_logv(). + + +M src/lib-sieve/sieve-error.c + +2019-05-15 13:10:55 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (6488fd4e) + + lib-sieve: sieve-error - Merge nested if-statements in sieve_direct_logv(). + + +M src/lib-sieve/sieve-error.c + +2019-05-14 13:00:42 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (71a49a1f) + + Fix compilation for GCC 4. + + Caused by recent event API changes. + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-validator.c + +2019-05-09 20:39:31 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (436599b7) + + lib-sieve: sieve_message_parts_add_missing() - Fix NULL checks to make + scan-build happy + + +M src/lib-sieve/sieve-message.c + +2019-05-09 13:20:29 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (6aae4545) + + plugins: imap-filter-sieve: Fix accessing uninitialized variable + + It happened only when returning error, so the caller wouldn't have cared + about it anyway. This makes static analyzers happier though. + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2019-04-29 15:02:12 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (23f7375d) + + plugins: imap-filter-sieve: Send FILTERED reply only if the filter did + changes + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c +M src/plugins/imap-filter-sieve/imap-filter-sieve.h +M src/plugins/imap-filter-sieve/imap-filter.c + +2019-05-02 16:01:42 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (ef6614a0) + + plugins: imap-filter-sieve: Cleanup - write FILTERED reply to string first + + Simplifies the next commit. + +M src/plugins/imap-filter-sieve/imap-filter.c + +2019-04-29 15:00:39 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (50dfe260) + + plugins: imap-filter-sieve: Handle each mail in a separate data stack frame + + Avoids growing memory usage excessively when filtering a lot of mails. + +M src/plugins/imap-filter-sieve/imap-filter.c + +2019-04-29 14:59:10 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (f3d98102) + + plugins: imap-filter-sieve: Don't delete mails if script gets aborted + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2019-04-29 14:57:56 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (176c337e) + + lib-sieve: Add sieve_exec_status.significant_action_executed + + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-types.h + +2019-04-29 14:57:25 +0300 Timo Sirainen <timo.sirainen@open-xchange.com> (b7a7e767) + + lib-sieve: Fix minor logic bug in handling duplicate keep actions + + This didn't seem to result in any visible bugs though. + +M src/lib-sieve/sieve-result.c + +2019-03-11 00:07:20 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (37d93ef3) + + lib-sieve: sieve-error - Change master logging to use event API. + + +M src/lib-sieve/sieve-error.c + +2019-04-07 12:51:42 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (5e320859) + + lib-sieve: Drop system error handler. + + +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/plugins/imap-filter-sieve/imap-filter-sieve.c +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-log.c + +2019-04-24 17:58:50 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (2da440e8) + + lib-sieve: sieve-error - Always use master log for system/global log + messages. + + +M src/lib-sieve/sieve-error.c + +2019-04-24 19:06:58 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (5f508971) + + lib-sieve: sieve-error - Move logging to master log to a separate function. + + +M src/lib-sieve/sieve-error.c + +2019-04-07 11:02:51 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (a21fe6e2) + + lib-sieve: sieve-error - Add flag that marks whether error handler logs to + master log. + + This is needed to avoid duplicating log lines there when the system log + handler is removed from the Sieve context. + +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c + +2019-04-07 10:51:32 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (c37c6e9c) + + lib-sieve: sieve-error - Reorder struct definitions. + + +M src/lib-sieve/sieve-error-private.h + +2019-03-11 00:19:09 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (2bb479d4) + + lib-sieve: sieve-error - Remove prefix support from master error handler. + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-activate.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-put.c +M src/plugins/imap-filter-sieve/imap-filter-sieve.c +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2019-04-23 20:32:25 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (a2744819) + + lib-sieve: sieve-error - Make c-source filename and line number available to + error handlers. + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h + +2019-04-24 18:31:09 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (052097be) + + lib-sieve: sieve-error - Rename sieve_vcritical() to sieve_criticalv(). + + This way, it matches the new sieve_logv(). + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-result.c + +2019-04-23 19:47:48 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (516333d3) + + lib-sieve: sieve-error - Add log_type to struct sieve_error_params. + + This reduces the number of log functions for the error handler from four to + just one. + +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-validator.c +M src/plugins/lda-sieve/lda-sieve-log.c +M src/testsuite/testsuite-log.c + +2019-04-24 14:38:55 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (f055883a) + + lib-sieve: sieve-error - Move location log parameter to a generic parameters + struct. + + +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-validator.c +M src/plugins/lda-sieve/lda-sieve-log.c +M src/testsuite/testsuite-log.c + +2019-03-10 23:58:10 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (f73ce51d) + + lib-sieve: Drop sieve_sys_* log functions. + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h + +2019-04-09 19:48:39 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (162ce2cb) + + lib-sieve: sieve-script - Drop sieve_script_sys_*() log functions. + + +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c + +2019-04-09 19:27:03 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (fa020da2) + + lib-sieve: sieve-storage - Drop sieve_storage_sys_*() log functions. + + +M src/lib-sieve/sieve-storage-private.h +M src/lib-sieve/sieve-storage.c + +2019-03-10 21:53:31 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (7507ddc6) + + plugins: imap-filter-sieve: imap-filter-sieve - Replace sieve_sys_*() with + e_*(). + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2019-03-10 21:38:25 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (d1b6776e) + + plugins: imapsieve: imap-sieve - Replace sieve_sys_*() with e_*(). + + +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/imapsieve/sieve-imapsieve-plugin.c + +2019-03-10 21:18:57 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (94d131e4) + + plugins: lda-sieve: lda-sieve-plugin - Replace sieve_sys_*() with e_*(). + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2019-04-09 19:47:57 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (61a9770a) + + lib-sieve: Replace sieve_script_sys_debug() with e_debug(). + + +M src/lib-sieve/sieve-script.c +M src/lib-sieve/storage/dict/sieve-dict-script.c +M src/lib-sieve/storage/file/sieve-file-script.c +M src/lib-sieve/storage/ldap/sieve-ldap-script.c + +2019-04-09 19:46:28 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (f114f313) + + lib-sieve: Replace sieve_script_sys_error() with e_error(). + + +M src/lib-sieve/sieve-script.c +M src/lib-sieve/storage/dict/sieve-dict-script.c +M src/lib-sieve/storage/file/sieve-file-script.c +M src/lib-sieve/storage/ldap/sieve-ldap-script.c + +2019-04-09 19:26:14 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (dbdfb777) + + lib-sieve: Replace sieve_storage_sys_debug() with e_debug(). + + +M src/lib-sieve/sieve-storage-sync.c +M src/lib-sieve/sieve-storage.c +M src/lib-sieve/storage/dict/sieve-dict-storage.c +M src/lib-sieve/storage/file/sieve-file-storage-active.c +M src/lib-sieve/storage/file/sieve-file-storage.c +M src/lib-sieve/storage/ldap/sieve-ldap-db.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.c + +2019-04-09 19:25:19 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (168eca74) + + lib-sieve: Replace sieve_storage_sys_info() with e_info(). + + +M src/lib-sieve/storage/file/sieve-file-storage-active.c + +2019-04-09 19:24:02 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (586d4629) + + lib-sieve: Replace sieve_storage_sys_warning() with e_warning(). + + +M src/lib-sieve/sieve-storage-sync.c +M src/lib-sieve/storage/file/sieve-file-storage-active.c +M src/lib-sieve/storage/file/sieve-file-storage-quota.c +M src/lib-sieve/storage/file/sieve-file-storage-save.c +M src/lib-sieve/storage/file/sieve-file-storage.c +M src/lib-sieve/storage/ldap/sieve-ldap-db.c + +2019-04-09 19:21:44 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (17b4a1f5) + + lib-sieve: Replace sieve_storage_sys_error() with e_error(). + + +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-storage.c +M src/lib-sieve/storage/file/sieve-file-script-sequence.c +M src/lib-sieve/storage/file/sieve-file-storage-list.c +M src/lib-sieve/storage/file/sieve-file-storage-save.c +M src/lib-sieve/storage/file/sieve-file-storage.c +M src/lib-sieve/storage/ldap/sieve-ldap-db.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage-settings.c + +2019-04-09 18:37:07 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (ae6a3742) + + lib-sieve: Replace sieve_sys_debug() with e_debug(). + + +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-storage.c +M src/lib-sieve/sieve.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.c +M src/plugins/sieve-extprograms/sieve-extprograms-plugin.c + +2019-04-09 18:36:40 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (62998517) + + lib-sieve: Replace sieve_sys_info() with e_info(). + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-storage.c + +2019-04-09 18:34:51 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (6a024d83) + + lib-sieve: Replace sieve_sys_warning() with e_warning(). + + +M src/lib-sieve/plugins/editheader/ext-editheader-common.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/sieve-address-source.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-storage.c + +2019-04-09 18:31:50 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (fcaffaff) + + lib-sieve: Replace sieve_sys_error() with e_error(). + + +M src/lib-sieve/plugins/ihave/ext-ihave-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-storage.c +M src/lib-sieve/sieve.c +M src/lib-sieve/tst-size.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-message.c + +2019-05-01 00:16:44 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (8ba34ff6) + + lib-sieve: sieve-binary - Replace sieve_sys_error() with e_error(). + + +M src/lib-sieve/sieve-binary-file.c + +2019-04-30 23:43:12 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (0a812d89) + + lib-sieve: sieve-binary - Replace sieve_sys_debug() with e_debug(). + + +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary.c + +2019-04-30 23:22:56 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (01329495) + + lib-sieve: sieve-binary - Add support for event API. + + +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-binary.c + +2019-04-09 19:44:21 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (6f26baaa) + + lib-sieve: sieve-script - Add support for event API. + + +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c + +2019-04-09 19:13:04 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (a4376980) + + lib-sieve: sieve-storage - Add support for event API. + + +M src/lib-sieve/sieve-storage-private.h +M src/lib-sieve/sieve-storage.c +M src/lib-sieve/storage/data/sieve-data-script.c +M src/lib-sieve/storage/file/sieve-file-storage.c + +2019-03-10 15:57:26 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (2b5aa172) + + lib-sieve: sieve - Add sieve_get_event(). + + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h + +2019-02-17 15:56:18 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (c09e6095) + + lib-sieve: Add support for event API. + + +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c + +2019-03-10 23:05:59 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (d5b8eee6) + + testsuite: testsuite-log - Handle log messages generated outside a sieve + error handler. + + +M src/testsuite/testsuite-log.c + +2019-05-03 02:11:03 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (9f86c469) + + lib-sieve: sieve-binary-file - Use binary rather than Sieve instance in + struct sieve_binary_file. + + +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h + +2019-05-03 02:30:19 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (1513486b) + + lib-sieve: sieve-binary-file - Refactor sieve_binary_file_close(). + + +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h + +2019-05-03 01:51:36 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (5dcb88e8) + + lib-sieve: sieve-binary-file - Make sieve_binary_file_open() static. + + +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h + +2019-05-01 09:40:03 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (6d4720e7) + + lib-sieve: Reformat sieve-binary-dumper.c. + + +M src/lib-sieve/sieve-binary-dumper.c + +2019-05-01 09:31:28 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (2a006148) + + lib-sieve: Reformat sieve-binary-debug.c. + + +M src/lib-sieve/sieve-binary-debug.c + +2019-05-01 09:23:14 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (887eb103) + + lib-sieve: Reformat sieve-binary-code.c. + + +M src/lib-sieve/sieve-binary-code.c + +2019-05-01 01:25:03 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (8efd7cb7) + + lib-sieve: Reformat sieve-binary-file.c. + + +M src/lib-sieve/sieve-binary-file.c + +2019-05-01 00:53:25 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (c816308f) + + lib-sieve: Reformat sieve-binary-private.h. + + +M src/lib-sieve/sieve-binary-private.h + +2019-05-01 00:44:05 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (717a7ea5) + + lib-sieve: Reformat sieve-binary.h. + + +M src/lib-sieve/sieve-binary.h + +2019-05-01 00:34:45 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (7448d1dc) + + lib-sieve: Reformat sieve-binary.c. + + +M src/lib-sieve/sieve-binary.c + +2019-04-30 14:26:16 +0300 Aki Tuomi <aki.tuomi@open-xchange.com> (9dab95d8) + + NEWS: Add news for v0.5.6 + + +M NEWS + +2019-04-24 08:57:05 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (9c6b1051) + + lib-sieve: sieve-parser - Remove unnecessary forward declaration of error + handling functions. + + +M src/lib-sieve/sieve-parser.c + +2019-04-24 08:55:04 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (069d5af9) + + lib-sieve: sieve-lexer - Remove unnecessary forward declaration of error + handling functions. + + +M src/lib-sieve/sieve-lexer.c + +2019-04-24 09:12:16 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (aaca4777) + + lib-sieve: sieve-validator - Remove spurious declaration of + sieve_validator_critical(). + + +M src/lib-sieve/sieve-validator.h + +2019-04-24 09:08:02 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (4019a724) + + lib-sieve: sieve-validator - Reorder error handling functions. + + +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h + +2019-04-24 08:48:42 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (7fc3b2cb) + + lib-sieve: sieve-generator - Reorder error handling functions. + + +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h + +2019-04-19 00:02:47 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (c69def7c) + + lib-sieve: sieve-error - Move sieve_internal_error(). + + +M src/lib-sieve/sieve-error.c + +2019-04-18 23:26:31 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (eb6aac65) + + lib-sieve: sieve-validator - Move error handling to the end of the file. + + +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h + +2019-04-18 22:21:18 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (16fb21b1) + + lib-sieve: sieve-generator - Move error handling to the end of the file. + + +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h + +2019-04-18 21:45:17 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (a894b255) + + lib-sieve: sieve-interpreter - Move error handling to the end of the file. + + +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h + +2019-03-10 15:41:34 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (6a82c9b4) + + lib-sieve: sieve-binary-file - Remove unused code. + + +M src/lib-sieve/sieve-binary-file.c + +2019-04-19 01:08:27 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (79090306) + + lib-sieve: sieve-result - Move error handling to the end of the file. + + +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2019-04-24 23:32:04 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (b1cd6b68) + + plugins: imap-filter-sieve: Reformat imap-filter-sieve.c. + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2019-04-24 23:18:38 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (9bf576f4) + + plugins: imapsieve: Reformat imap-sieve.h. + + +M src/plugins/imapsieve/imap-sieve.h + +2019-04-24 23:15:33 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (696d562e) + + plugins: imapsieve: Reformat imap-sieve.c. + + +M src/plugins/imapsieve/imap-sieve.c + +2019-04-24 21:33:22 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (8e528bc2) + + plugins: lda-sieve: Reformat lda-sieve-plugin.c. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2019-04-24 18:38:42 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (d3a0bda4) + + plugins: lda-sieve: Reformat lda-sieve-log.h. + + +M src/plugins/lda-sieve/lda-sieve-log.h + +2019-04-24 18:37:48 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (3fcf493e) + + plugins: lda-sieve: Reformat lda-sieve-log.c. + + +M src/plugins/lda-sieve/lda-sieve-log.c + +2019-04-24 18:19:33 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (f32d00e2) + + testsuite: Reformat testsuite-log.h. + + +M src/testsuite/testsuite-log.h + +2019-04-24 18:18:14 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (eb521641) + + testsuite: Reformat testsuite-log.c. + + +M src/testsuite/testsuite-log.c + +2019-04-24 16:50:03 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (b79f8fb4) + + lib-sieve: Reformat sieve-parser.h. + + +M src/lib-sieve/sieve-parser.h + +2019-04-24 16:47:20 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (25ed1cdc) + + lib-sieve: Reformat sieve-parser.c. + + +M src/lib-sieve/sieve-parser.c + +2019-04-24 16:22:46 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (7f643de2) + + lib-sieve: Reformat sieve-lexer.h. + + +M src/lib-sieve/sieve-lexer.h + +2019-04-24 16:17:16 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (924bb302) + + lib-sieve: Reformat sieve-lexer.c. + + +M src/lib-sieve/sieve-lexer.c + +2019-04-19 01:03:47 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (36c6424a) + + lib-sieve: Reformat sieve-result.h. + + +M src/lib-sieve/sieve-result.h + +2019-04-19 00:57:27 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (00aac7d7) + + lib-sieve: Reformat sieve-result.c. + + +M src/lib-sieve/sieve-result.c + +2019-04-18 23:23:51 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (160d8f6d) + + lib-sieve: Reformat sieve-validator.h. + + +M src/lib-sieve/sieve-validator.h + +2019-04-18 23:14:19 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (2c40f4df) + + lib-sieve: Reformat sieve-validator.c. + + +M src/lib-sieve/sieve-validator.c + +2019-04-18 22:18:02 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (e24fa365) + + lib-sieve: Reformat sieve-generator.h. + + +M src/lib-sieve/sieve-generator.h + +2019-04-18 22:11:08 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (0014106f) + + lib-sieve: Reformat sieve-generator.c. + + +M src/lib-sieve/sieve-generator.c + +2019-04-18 21:42:13 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (088814fe) + + lib-sieve: Reformat sieve-interpreter.h. + + +M src/lib-sieve/sieve-interpreter.h + +2019-04-18 21:32:04 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (37c40ce1) + + lib-sieve: Reformat sieve-interpreter.c. + + +M src/lib-sieve/sieve-interpreter.c + +2019-04-18 23:49:40 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (fa530f84) + + lib-sieve: Reformat sieve-error-private.h. + + +M src/lib-sieve/sieve-error-private.h + +2019-04-10 21:12:33 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (89a0b67f) + + lib-sieve: Reformat sieve-error.h. + + +M src/lib-sieve/sieve-error.h + +2019-04-10 21:55:25 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (b95ae584) + + lib-sieve: Reformat sieve-error.c. + + +M src/lib-sieve/sieve-error.c + +2019-04-10 20:40:57 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (12514b42) + + lib-sieve: Reformat sieve-script-private.h. + + +M src/lib-sieve/sieve-script-private.h + +2019-04-10 20:37:13 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (6ab4da37) + + lib-sieve: Reformat sieve-script.c. + + +M src/lib-sieve/sieve-script.c + +2019-04-10 20:16:59 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (fa418a65) + + lib-sieve: Reformat sieve-script.h. + + +M src/lib-sieve/sieve-script.h + +2019-04-10 10:06:37 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (8a011cbb) + + lib-sieve: Reformat sieve-storage-private.h. + + +M src/lib-sieve/sieve-storage-private.h + +2019-04-10 09:42:24 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (4c7d8a4e) + + lib-sieve: Reformat sieve-storage.c. + + +M src/lib-sieve/sieve-storage.c + +2019-04-10 08:57:59 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (34ee26e0) + + lib-sieve: Reformat sieve-storage.h. + + +M src/lib-sieve/sieve-storage.h + +2019-03-10 16:40:03 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (8dc19b49) + + lib-sieve: Reformat sieve.c. + + +M src/lib-sieve/sieve.c + +2019-03-10 16:39:17 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (7ee00844) + + lib-sieve: Reformat sieve.h. + + +M src/lib-sieve/sieve.h + +2019-04-26 09:37:51 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (19969c5f) + + lib-sieve: sieve-storage: Fix memory leak occurring in + sieve_storage_check_script_direct(). + + +M src/lib-sieve/sieve-storage.c + +2019-04-25 23:04:23 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (ab0fcec5) + + plugins: imap-filter-sieve: imap-filter-sieve - Fix memory leak of global + script storage. + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2019-04-07 19:38:07 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (73ce81a2) + + plugins: doveadm-sieve: doveadm-sieve-cmd-put - Fix script memory leak + occurring when saved script is also activated. + + +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-put.c + +2019-04-26 11:33:38 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (078ff7fb) + + lib-sieve: sieve-script - Fix script memory leak occurring when renamed + script is also activated. + + +M src/lib-sieve/sieve-script.c + +2019-04-07 18:52:51 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (2fbd34a5) + + lib-sieve: sieve-storage - Fix script memory leak occurring when saved + script is implicitly activated. + + +M src/lib-sieve/sieve-storage.c + +2019-03-04 19:59:08 +0200 Aki Tuomi <aki.tuomi@open-xchange.com> (64f480ae) + + NEWS: Update master news file + + Add NEWS from releases to master branch too + +M NEWS + +2019-01-24 22:46:09 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (77cc9328) + + lib-sieve: Prevent execution of implicit keep upon temporary failure + occurring at runtime. + + +M src/lib-sieve/sieve.c + +2019-02-13 23:26:09 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (54febd73) + + Adjust to changes in Dovecot SMTP submit API. + + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2019-01-16 08:51:09 -0500 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> (65a6af4b) + + global: hash_table_destroy(NULL) is a no-op + + @@ expression E; + @@ + + - if (hash_table_is_created(E)) { + - hash_table_destroy(&E); + - } + + hash_table_destroy(&E); + +M src/lib-sieve/sieve-result.c +M src/plugins/imapsieve/imap-sieve-storage.c + +2018-12-12 18:46:50 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (43f5835b) + + lib-sieve: redirect action: Assert that dupeid is not NULL when + act_redirect_get_duplicate_id() is successful. + + Addresses scan-build report. + +M src/lib-sieve/cmd-redirect.c + +2018-12-12 18:45:00 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (114fe5f6) + + lib-sieve: redirect action: Fix lack of NULL checking in new + X-Sieve-Redirected-From header comparisons. + + Problem found by scan-build. + +M src/lib-sieve/cmd-redirect.c + +2018-12-11 10:43:37 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (5b813421) + + plugins: imapsieve: Remove useless NULL check for exec_status. + + In this context, it can never be NULL and the check confuses Coverity. + +M src/plugins/imapsieve/imap-sieve.c + +2018-12-11 10:41:51 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (993bb23b) + + plugins: imap-filter-sieve: Remove useless NULL check for exec_status. + + In this context, it can never be NULL and the check confuses Coverity. + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2018-12-11 17:29:18 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (78f5952c) + + lib-sieve: redirect action: Implement additional protection against mail + loops. + + Also check the X-Sieve-Redirected-From header for our own e-mail addresses. + This header is added by the redirect action itself and in a mail loop it + would see that same header with that same content. This is less reliable + than the other mail loop detection (sender may set such a header), so, + unlike the existing loop detection based on the duplicate db, the implicit + keep is not canceled when the new loop detection is triggered. + +M src/lib-sieve/cmd-redirect.c +M tests/execute/smtp.svtest + +2018-12-11 17:27:20 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (c42bbea8) + + lib-sieve: redirect action: Put msgdata->mail in local variable in + act_redirect_get_duplicate_id(). + + Serves as an abbreviation. + +M src/lib-sieve/cmd-redirect.c + +2018-12-11 17:26:56 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (f0639f18) + + lib-sieve: redirect action: Move composition of duplicate database ID to + separate function. + + +M src/lib-sieve/cmd-redirect.c + +2018-12-11 20:28:51 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (4cf91044) + + lib-sieve: redirect action: Give log messages emitted during execution a + uniform prefix. + + +M src/lib-sieve/cmd-redirect.c + +2018-12-11 17:25:12 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (51d87ff8) + + lib-sieve: redirect action: Report errors on original message in + act_redirect_commit(). + + It was errorneously using the (potentially) modified mail struct for error + reporting. + +M src/lib-sieve/cmd-redirect.c + +2018-12-11 17:24:38 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (8a8f9c1e) + + lib-sieve: redirect action: Update coding style of act_redirect_commit(). + + +M src/lib-sieve/cmd-redirect.c + +2018-12-11 20:25:12 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (b8f5acd7) + + lib-sieve: redirect action: Update coding style of act_redirect_send(). + + +M src/lib-sieve/cmd-redirect.c + +2018-12-11 17:23:06 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (607a95e8) + + lib-sieve: editheader extension: Protect the X-Sieve-Redirected-From header + against modification. + + This prevents users from messing with redirect loop detection. + +M src/lib-sieve/plugins/editheader/ext-editheader-common.c + +2018-12-11 12:53:13 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (7b862820) + + plugins: sieve-extprograms: Use sieve_ prefix consistently for sieve + elements visible as exported symbols. + + This fixes a symbol clash with the imap-filter-sieve plugin. Both modules + had the symbol "cmd_filter". + +M src/plugins/sieve-extprograms/cmd-execute.c +M src/plugins/sieve-extprograms/cmd-filter.c +M src/plugins/sieve-extprograms/cmd-pipe.c +M src/plugins/sieve-extprograms/ext-execute.c +M src/plugins/sieve-extprograms/ext-filter.c +M src/plugins/sieve-extprograms/ext-pipe.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.h +M src/plugins/sieve-extprograms/sieve-extprograms-plugin.c + +2018-12-05 10:57:37 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (fa6bec03) + + plugins: imapsieve: Expunge discarded messages when + imapsieve_expunge_discarded=yes. + + +M doc/plugins/imapsieve.txt +M src/plugins/imapsieve/imap-sieve-storage.c + +2018-12-05 10:08:18 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (9ac4e5b7) + + plugins: imap-filter-sieve: Properly discard the originally stored message + when a modified version is stored by Sieve. + + The Sieve interpreter can return a flag that indicates whether the original + message should be kept, but that was not actually being used. + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2018-12-04 23:45:01 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (5513cea1) + + plugins: imapsieve: Properly discard the originally stored message when a + modified version is stored by Sieve. + + The Sieve interpreter can return a flag that indicates whether the original + message should be kept, but that was not actually being used. + +M src/plugins/imapsieve/imap-sieve.c + +2018-12-04 15:45:01 +0200 sergey <sergey@dom.org> (1d23ca49) + + lib-sieve: Create empty mail_keywords structure for keywords updating when + there are no keywords + + +M src/lib-sieve/sieve-actions.c + +2018-11-26 09:44:49 +0200 Aki Tuomi <aki.tuomi@dovecot.fi> (8f7d3958) + + configure: Stop using DOVECOT_CFLAGS and LDFLAGS + + Instead use the detected ones. + +M configure.ac + +2018-11-26 09:44:40 +0200 Aki Tuomi <aki.tuomi@dovecot.fi> (a0a8f36a) + + m4: Update dovecot.m4 from upstream + + +M m4/dovecot.m4 + +2018-09-26 02:40:36 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (65909cfa) + + Don't try to send stats from Sieve command line tools (which includes + testsuite). + + +M src/lib-sieve-tool/sieve-tool.c + +2018-09-26 02:27:27 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (4c24c5bb) + + global: Don't try to send stats from unit tests. + + +M src/lib-sieve/util/test-edit-mail.c + +2018-09-05 21:27:58 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (8b9cf579) + + lib-sieve: Adjust to changes in Dovecot regarding the postmaster_address + setting. + + +M src/lib-sieve/sieve.c + +2018-09-06 19:53:33 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (a931fc35) + + managesieve: Don't enable stats when dumping capability + + Otherwise stats process startup can get into a loop. + +M src/managesieve/main.c + +2018-08-30 02:44:26 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (97cfb22e) + + plugins: imap-filter-sieve: Add assertion on attempting to execute at least + one script. + + Coverity complains about last_script possibly being empty in + imap_sieve_filter_run_scripts(), which is actually not possible, since the + function would not be called if there is no script to execute. Added + assertion to make that clear. + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2018-08-30 02:39:25 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (3dce3817) + + plugins: imap-filter-sieve: Fix segfault occurring in recently added debug + message. + + The debug message pertains to skipping secondary scripts that failed to + compile. This debug message will not actually be triggered in the current + implementation, but this will become problematic in the future. + + Problem found by Coverity. + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2018-08-26 17:26:05 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (41b9adcb) + + plugins: imap-filter-sieve: Fix assertion panic occurring after script + compile error. + + Compile errors occurring for Sieve scripts uploaded in multiple TCP frames + were not handled correctly. + +M src/plugins/imap-filter-sieve/cmd-filter-sieve.c + +2018-08-26 16:51:29 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (c7a83a3d) + + plugins: imap-filter-sieve: Ignore secondary scripts that failed to compile. + + The IMAP FILTER=SIEVE capability does not execute more than a single script + yet, but once it does, it should not assert fail on secondary scripts that + failed to compile. + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2018-08-15 16:09:41 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (7877454e) + + lib-sieve: util: Add tests for rfc2822_header_write(). + + +M src/lib-sieve/util/Makefile.am +A src/lib-sieve/util/test-rfc2822.c + +2018-08-15 15:41:36 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (5c8583f8) + + lib-sieve: util: rfc2822: Prevent writing header lines with trailing + whitespace in rfc2822_header_append(). + + +M src/lib-sieve/util/rfc2822.c + +2018-08-15 15:35:17 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (41107911) + + lib-sieve: util: rfc2822: Fix assert panic occurring in + rfc2822_header_append(). + + Panic was: "Buffer write out of range" + + With some rather weird (sender-provided!) input, the header folding + algorithm got confused, causing a pointer to the start of the current line + to exceed the parsing pointer. This caused str_append_data() to be called + with a negative size. Added an assertion to make any future similar problems + more obvious. + +M src/lib-sieve/util/rfc2822.c + +2018-08-10 11:46:00 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (c7bd7456) + + plugins: imap-filter-sieve: Fix FILTER SIEVE SCRIPT command parsing. + + After finishing reading the Sieve script, the command parsing sometimes + didn't continue with the search arguments. This is a time-critical bug that + likely only occurs when the Sieve script is sent in the next TCP frame. + +M src/plugins/imap-filter-sieve/cmd-filter-sieve.c + +2018-08-09 13:04:27 +0300 Aki Tuomi <aki.tuomi@dovecot.fi> (99af69d5) + + lib-sieve: Return test suite result in test-edit-mail + + +M src/lib-sieve/util/test-edit-mail.c + +2018-08-05 13:54:06 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (e51a625a) + + plugins: imapsieve: Fix assert panic occurring when a COPY event is + triggered on a virtual mailbox. + + Occurs when several mails from different backend mailboxes are involved in + the COPY event. Fixed by using mail_save_context->>copy_src_mail in + mailbox_copy() instead of the mail argument. The latter can point to the + backend mailbox for virtual mailboxes, which makes no sense to the imapsieve + plugin as it expects only one source mailbox. + + Panic was: + + Panic: file imap-sieve-storage.c: line 337 + (imap_sieve_add_mailbox_copy_event): assertion failed: (ismt->src_box == + NULL || ismt->src_box == src_mail->box) + +M src/plugins/imapsieve/imap-sieve-storage.c + +2018-07-07 17:51:42 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (5c77bc11) + + lib-sieve: vacation extension: Make construction of default message subject + configurable. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M tests/extensions/vacation/message.svtest + +2018-07-07 17:01:17 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (081eac2b) + + lib-sieve: vacation extension: Move construction of default subject to + separate function. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2018-07-18 17:54:51 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (98e9ee54) + + Adjust to changes in Dovecot message_address_parse() API. + + Change was: + + lib-mail: message_address_parse() - Change fill_missing parameter to flags + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-address.c +M src/testsuite/testsuite-message.c + +2018-07-01 20:52:47 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (870855ed) + + doc: Add documentation and specification for the IMAP FILTER=SIEVE plugin to + distribution. + + +M doc/plugins/Makefile.am +M doc/rfc/Makefile.am + +2018-06-28 20:03:11 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (97b8287e) + + test suite: enotify extension: Add tests for interaction between + ":encodeurl" and variable size limits. + + +M tests/extensions/enotify/encodeurl.svtest + +2018-06-28 00:29:15 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (ffa42e6e) + + test suite: variables extension: Add tests for variable size limits. + + +A tests/extensions/variables/limits.svtest + +2018-06-27 09:39:49 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (16ac8900) + + lib-sieve: enotify extension: Improve handling of variable size limit for + ":encodeurl" variable modifier. + + +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c + +2018-06-27 09:38:45 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (734292d4) + + lib-sieve: variables extension: Improve handling of variable size limit for + ":quotewildcard" modifier. + + +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c + +2018-06-27 09:37:47 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (61baadef) + + lib-sieve: variables extension: Add pointer to variables extension to + modifier instance. + + +M src/lib-sieve/plugins/mime/cmd-extracttext.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2018-06-27 09:33:52 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (3ffb5a4d) + + lib-sieve: variables extension: Pass modifier to modifier's modify method. + + +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2018-06-27 09:26:31 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (2998ab7e) + + lib-sieve: variables extension: Add sieve_variables_get_max_variable_size() + to public API. + + +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2018-06-01 00:30:06 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (daf4a721) + + lib-sieve: variables extension: Respect UTF-8 character sequence boundaries + when truncating variables. + + +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-operands.c + +2018-06-27 09:44:08 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (92caa9e2) + + lib-sieve: enotify extension: Make modify method of ":encodeurl" variable + modifier static. + + +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c + +2018-06-28 20:02:04 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (b54bd368) + + lib-sieve: variables extension: Make modify methods of pre-defined modifiers + static. + + +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c + +2018-06-13 00:49:54 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (97dc5366) + + managesieve: Free sieve instance when performing dump-capability + + Makes it easier to run with valgrind. + +M src/managesieve/main.c +M src/managesieve/managesieve-capabilities.c + +2018-06-12 18:52:03 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (5d2c3130) + + doveadm sieve plugin: Fix memory leak for "sieve get" command + + +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-get.c + +2018-06-01 10:08:36 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (eceb19e7) + + plugins: imap_filter_sieve: Put more effort in reconstructing a valid rcpt + address for the envelope. + + The sieve_user_email setting provides a fallback for when there is no + Delivered-To header. + +M src/plugins/imap-filter-sieve/imap-filter-sieve.c + +2018-05-28 14:12:49 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (678a14d7) + + lib-sieve: script storage: Fix leaking mailbox if opening INBOX fails + + +M src/lib-sieve/sieve-storage-sync.c + +2018-05-27 10:40:42 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (69cfb80b) + + plugins: imap_filter_sieve: Implement the UID FILTER command. + + Although it was documented and implemented in essence, it was not actually + available. + +M src/plugins/imap-filter-sieve/imap-filter-sieve-plugin.c + +2018-05-26 18:11:19 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (6535eab7) + + doc: imap_filter_sieve plugin specification: Updated Dovecot Oy office + address. + + +M doc/rfc/draft-bosch-imap-filter-sieve-00.txt + +2018-05-26 16:39:00 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (30c40f7e) + + imap-filter-sieve: Fix FILTER to work correctly with pipelining + + Fixes e.g. FILTER+LOGOUT pipelining crash: Panic: file imap-sync.c: line 832 + (cmd_sync_delayed_real): assertion failed: (client->mailbox != NULL) + +M src/plugins/imap-filter-sieve/imap-filter-sieve-plugin.c + +2018-05-12 00:56:19 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (ddab597c) + + tests: address test: Add tests for invalid addresses with UTF-8 in the + localpart. + + +M tests/test-address.svtest + +2018-05-11 23:44:37 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (cdb1a656) + + lib-sieve: Add more trace debugging output for address list iteration. + + +M src/lib-sieve/sieve-address.c + +2018-05-11 23:57:26 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (b58515a7) + + lib-sieve: Check iterated addresses in address list for validity as an SMTP + address. + + +M src/lib-sieve/sieve-address.c + +2018-05-12 00:08:19 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (9755beaf) + + lib-sieve: Try to skip individual invalid addresses while iterating an + address list. + + Before, the whole address list (header value) was returned as an invalid + address, ignoring any valid addresses it may still have contained. + +M src/lib-sieve/sieve-address.c + +2018-05-02 23:48:30 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (6fe1b102) + + plugins: Implement the vendor-defined IMAP FILTER=SIEVE capability. + + It adds the ability to manually invoke Sieve filtering in IMAP. + +M INSTALL +M TODO +M configure.ac +A doc/plugins/imap_filter_sieve.txt +A doc/rfc/draft-bosch-imap-filter-sieve-00.txt +M src/plugins/Makefile.am +A src/plugins/imap-filter-sieve/Makefile.am +A src/plugins/imap-filter-sieve/cmd-filter-sieve.c +A src/plugins/imap-filter-sieve/cmd-filter.c +A src/plugins/imap-filter-sieve/imap-filter-sieve-plugin.c +A src/plugins/imap-filter-sieve/imap-filter-sieve-plugin.h +A src/plugins/imap-filter-sieve/imap-filter-sieve.c +A src/plugins/imap-filter-sieve/imap-filter-sieve.h +A src/plugins/imap-filter-sieve/imap-filter.c +A src/plugins/imap-filter-sieve/imap-filter.h + +2018-05-07 11:04:09 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (a15235f0) + + plugins: imapsieve: Make sure responses are never sent. + + Use the new SIEVE_EXECUTE_FLAG_SKIP_RESPONSES flag to prevent any unforseen + mishaps. + +M src/plugins/imapsieve/imap-sieve.c + +2018-05-07 11:03:01 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (2a39311d) + + lib-sieve: Add SIEVE_EXECUTE_FLAG_SKIP_RESPONSES execute flag. + + This causes the reject and vacation response actions to be skipped without + error. + +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-types.h + +2018-05-02 23:46:27 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (fa816c6b) + + lib-sieve: Add support for compiling Sieve scripts from an input stream. + + +M configure.ac +M src/lib-sieve/Makefile.am +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-storage-private.h +M src/lib-sieve/storage/Makefile.am +A src/lib-sieve/storage/data/Makefile.am +A src/lib-sieve/storage/data/sieve-data-script.c +A src/lib-sieve/storage/data/sieve-data-storage.c +A src/lib-sieve/storage/data/sieve-data-storage.h + +2018-05-02 23:40:51 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (52085ae9) + + lib-sieve: Allow sieve_script_binary_save() error_r parameter to be NULL. + + +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h + +2018-04-17 20:48:56 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (483d8a74) + + lib-sieve: Always check the result returned from + smtp_address_init_from_msg(). + + +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2018-05-02 13:46:15 +0300 Phil Carmody <phil@dovecot.fi> (518dc8b6) + + ldap - fix stupid typo + + Signed-off-by: Phil Carmody <phil@dovecot.fi> + +M src/lib-sieve/storage/ldap/sieve-ldap-db.c + +2018-04-28 23:29:55 +0300 Phil Carmody <phil@dovecot.fi> (b86696e2) + + global: expand default temporary pool sizes + + The tests blow through these limits all of the time, which makes the logs + very noisy. These three cases are about 4/5ths of the test logs. Presumably + they're the ones that are also most often needing expansion in real world + use too. + + Signed-off-by: Phil Carmody <phil@dovecot.fi> + +M src/lib-sieve/sieve-message.c +M src/lib-sieve/storage/file/sieve-file-script.c +M src/lib-sieve/storage/file/sieve-file-storage.c + +2018-04-28 23:11:40 +0300 Phil Carmody <phil@dovecot.fi> (45bc4fb6) + + global: replace verbose strncmp()s with simpler str_begin()s + + Signed-off-by: Phil Carmody <phil@dovecot.fi> + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/storage/file/sieve-file-storage-save.c +M src/lib-sieve/storage/file/sieve-file-storage.c +M src/lib-sieve/storage/ldap/sieve-ldap-db.c +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c + +2018-04-27 17:28:03 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (51b7c26e) + + lib-sieve: util: test-edit-mail: Determine test directory at the beginning + of all tests. + + It is the initial working directory and that may change during testing, so + it is not a good idea to determine this per test. + +M src/lib-sieve/util/test-edit-mail.c + +2018-04-25 21:23:49 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (d51e6851) + + lib-sieve: util: test-edit-mail: Fix unused variable warning reported by + GCC. + + +M src/lib-sieve/util/test-edit-mail.c + +2018-04-18 10:16:29 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (890c6e26) + + lib-sieve: util: edit-mail: Fix assert panic occurring when streaming large + headers. + + The problem mainly arose because the stream buffer position was used to + determine how much was written, while the stream buffer position is + potentially decreased by i_stream_try_alloc(). + + Panic was: + + Panic: file istream.c: line 197 (i_stream_read): assertion failed: + ((size_t)ret+old_size == _stream->pos - _stream->skip) + +M src/lib-sieve/util/edit-mail.c +M src/lib-sieve/util/test-edit-mail.c + +2018-04-25 14:22:37 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (f0963ac9) + + global: Replace str_append_n() with str_append_data(). + + The str_append_n() function is now deprecated. At no occasion, the occurence + of NUL in the data is possible or relevant, so each instance is replaced + with str_append_data() rather than str_append_max(). + +M src/lib-managesieve/managesieve-quote.c +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/mime/cmd-extracttext.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/storage/ldap/sieve-ldap-db.c +M src/lib-sieve/util/edit-mail.c +M src/lib-sieve/util/rfc2822.c +M src/lib-sieve/util/test-edit-mail.c +M src/managesieve-login/client-authenticate.c +M src/testsuite/testsuite-arguments.c + +2018-04-24 00:24:52 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (a82f2c3a) + + lib-sieve: Never return SIEVE_EXEC_FAILURE from + sieve_multiscript_run_discard(). + + Always return SIEVE_EXEC_KEEP_FAILED instead. + +M src/lib-sieve/sieve.c + +2018-04-24 00:24:38 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (86827c4a) + + lib-sieve: Never return SIEVE_EXEC_FAILURE from keep action. + + Always return SIEVE_EXEC_KEEP_FAILED instead. + +M src/lib-sieve/sieve-result.c + +2018-04-16 21:49:08 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (f27aa69b) + + tests: vacation extension: Add tests for configuring the subject codepoint + limit. + + +M tests/extensions/vacation/message.svtest + +2018-04-16 20:42:46 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (ffbcd3bf) + + lib-sieve: vacation extension: Make codepoint limit for subject header + configurable. + + +M doc/extensions/vacation.txt +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h + +2018-04-16 20:41:59 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (e4b03a69) + + tests: vacation extension: Add tests for the truncation of long subject + lines. + + +M tests/extensions/vacation/message.svtest + +2018-04-16 19:49:15 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (f99afb6d) + + lib-sieve: vacation extension: Enforce subject header limit in Unicode + codepoints rather than bytes. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2018-04-13 02:50:46 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (0712e678) + + tests: envelope extension: Adjust to changes in Dovecot SMTP address parser. + + +M tests/extensions/envelope.svtest + +2018-03-06 23:17:14 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (e15c66c9) + + lib-sieve: Adjusted to changes in Dovecot message address to SMTP address + conversion. + + This conversion now includes a check that may fail. Pigeonhole currently + only uses this functionality to obtain an SMTP version of the postmaster + address. This code is now consolidated in the sieve_get_postmaster_smtp() + function, which provides postmaster address as an SMTP address. + +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/sieve-address-source.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve.c + +2018-03-29 00:07:47 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (9f09b81e) + + lda-sieve plugin: Do not execute the sieve_discard script when an error + occurs. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2018-03-29 00:13:34 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (b06b775c) + + lib-sieve: Never return TRUE from sieve_multiscript_will_discard() when + status is not successful. + + Errors will trigger an implicit keep, not discard. + +M src/lib-sieve/sieve.c + +2018-02-15 09:06:26 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (3846eb3e) + + lib-sieve: variables extension: Fix duplicate const in definition of + sieve_variables_modifier array. + + This is wrong and leads to Clang compiler warnings. + +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2018-03-06 23:52:40 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (5a71e7be) + + lib-sieve: Do not allow UTF-8 in localpart in addresses parsed from Sieve + script. + + +M src/lib-sieve/sieve-address.c +M tests/compile/errors.svtest +M tests/compile/errors/out-address.sieve + +2018-03-07 21:52:46 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (2c1c4220) + + plugins: imapsieve: Don't log messages that disappear concurrently as an + error. + + This is now logged as a debug message instead. + +M src/plugins/imapsieve/imap-sieve-storage.c + +2018-03-05 22:57:22 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (00190f91) + + lib-sieve: util: edit-mail: Remove useless assignment. + + This is a remnant of an older implementation and now triggered a scan-build + report. + +M src/lib-sieve/util/edit-mail.c + +2018-03-05 23:13:06 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (ab1f9582) + + Update Dovecot version from v2.2 to v2.4. + + +M README +M configure.ac +M doc/man/doveadm-sieve.1.in +M doc/man/pigeonhole.7.in +M doc/man/sieve-dump.1.in +M doc/man/sieve-filter.1.in +M doc/man/sieve-test.1.in +M doc/man/sievec.1.in + +2018-03-03 10:12:28 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (91920140) + + lib-sieve: Fix assert panic occurring when used command has external tag, + but is not registered. + + This occurred for example when the "fileinto" command is used with only the + "copy" extension in the require line. + + Panic message was: + + Panic: file hash.c: line 263 (hash_table_insert_node): assertion failed: + (opcode == HASH_TABLE_OP_UPDATE) + +M src/lib-sieve/sieve-validator.c + +2018-03-03 10:28:07 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (095b2e12) + + testsuite: Make SMTP actions also work inside executed sieve scripts. + + +M src/testsuite/testsuite-script.c + +2018-03-03 12:50:28 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (17ae453d) + + lib-sieve: util: Created basic test suite for edit-mail. + + Previously, this was only tested implicitly in the Sieve test suite. Now, it + is tested explicitly, which allows for more flexibility in the testing + scenario. + + It now extensively tests one scenario that used to fail. + +M src/lib-sieve/util/Makefile.am +A src/lib-sieve/util/test-edit-mail.c + +2018-03-03 17:50:59 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (b1cd8048) + + lib-sieve: util: edit-mail: istream: Fix bug in calculation of stream + position. + + This caused an assert panic when the application or child stream did not + skip all buffered data immediately. This was reproducible only when the + message input stream consisted of a concatenation of smaller streams, which + is used in LMTP to prepend a few headers. + + The panic was: + + Panic: file istream.c: line 329 (i_stream_read_memarea): assertion failed: + ((size_t)ret+old_size == _stream->pos - _stream->skip) + +M src/lib-sieve/util/edit-mail.c + +2018-03-03 17:54:14 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (0b4ed1a3) + + lib-sieve: util: edit-mail: istream: Remove useless check. + + This is tested already in the assertion that precedes it. + +M src/lib-sieve/util/edit-mail.c + +2018-03-03 11:42:29 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (b9cfdb83) + + lib-sieve: util: mail-raw: Implemented mail_raw_open_stream(). + + This allows using a seekable stream as mail directly. + +M src/lib-sieve/util/mail-raw.c +M src/lib-sieve/util/mail-raw.h + +2018-03-03 10:59:23 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (cd4507f0) + + Move mail-raw from lib-sieve-tool to lib-sieve/util. + + Needed for use in test suite. + +M src/lib-sieve-tool/Makefile.am +M src/lib-sieve/util/Makefile.am +R100 src/lib-sieve-tool/mail-raw.c src/lib-sieve/util/mail-raw.c +R100 src/lib-sieve-tool/mail-raw.h src/lib-sieve/util/mail-raw.h +M src/testsuite/Makefile.am + +2018-03-02 20:21:27 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (71d7283d) + + testsuite: Don't initialize mail storage with + mail_full_filesystem_access=yes. + + Recent changes in Dovecot make slashes allowed in mailbox names when this + flag is set. This flag is not useful for the test suite and it breaks one of + the tests because slashes are no longer invalid when this flag is set. + +M src/testsuite/testsuite-mailstore.c + +2018-03-02 00:14:55 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (dadedf97) + + lib-sieve: store action: Sanitize both specified and virtual mailbox names + in log strings. + + Before, the virtual mailbox name was not sanitized, which caused control + characters to be displayed in log messages. Also, the mailbox name would be + mentioned twice in the log message, once santized and once unsanitized. + +M src/lib-sieve/sieve-actions.c + +2018-03-02 01:25:43 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (19e012ee) + + lib-sieve: variables extension: Move top comment in sieve-ext-variables.h. + + The header guard defines should be on top. + +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2018-03-02 01:22:31 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (b7580860) + + Changed .h ifdef/defines to use <NAME>_H format. + + +M src/lib-managesieve/managesieve-arg.h +M src/lib-managesieve/managesieve-parser.h +M src/lib-managesieve/managesieve-quote.h +M src/lib-sieve-tool/mail-raw.h +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/copy/sieve-ext-copy.h +M src/lib-sieve/plugins/date/ext-date-common.h +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.h +M src/lib-sieve/plugins/editheader/ext-editheader-common.h +M src/lib-sieve/plugins/editheader/ext-editheader-limits.h +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify-limits.h +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.h +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/environment/ext-environment-common.h +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/lib-sieve/plugins/ihave/ext-ihave-binary.h +M src/lib-sieve/plugins/ihave/ext-ihave-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/sieve-ext-imap4flags.h +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-limits.h +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/index/ext-index-common.h +M src/lib-sieve/plugins/mailbox/ext-mailbox-common.h +M src/lib-sieve/plugins/mailbox/sieve-ext-mailbox.h +M src/lib-sieve/plugins/metadata/ext-metadata-common.h +M src/lib-sieve/plugins/mime/ext-mime-common.h +M src/lib-sieve/plugins/notify/ext-notify-common.h +M src/lib-sieve/plugins/notify/ext-notify-limits.h +M src/lib-sieve/plugins/regex/ext-regex-common.h +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/lib-sieve/plugins/variables/ext-variables-arguments.h +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-dump.h +M src/lib-sieve/plugins/variables/ext-variables-limits.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-name.h +M src/lib-sieve/plugins/variables/ext-variables-namespaces.h +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug-common.h +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-common.h +M src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.h +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address-source.h +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-objects.h +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-plugins.h +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-runtime-trace.h +M src/lib-sieve/sieve-runtime.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve-smtp.h +M src/lib-sieve/sieve-storage-private.h +M src/lib-sieve/sieve-storage.h +M src/lib-sieve/sieve-stringlist.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.h +M src/lib-sieve/storage/dict/sieve-dict-storage.h +M src/lib-sieve/storage/file/sieve-file-storage.h +M src/lib-sieve/storage/ldap/sieve-ldap-storage.h +M src/lib-sieve/util/edit-mail.h +M src/lib-sieve/util/rfc2822.h +M src/managesieve-login/client-authenticate.h +M src/managesieve-login/client.h +M src/managesieve-login/managesieve-login-settings-plugin.h +M src/managesieve-login/managesieve-login-settings.h +M src/managesieve-login/managesieve-proxy.h +M src/managesieve/managesieve-capabilities.h +M src/managesieve/managesieve-client.h +M src/managesieve/managesieve-commands.h +M src/managesieve/managesieve-common.h +M src/managesieve/managesieve-quota.h +M src/managesieve/managesieve-settings.h +M src/plugins/doveadm-sieve/doveadm-sieve-cmd.h +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.h +M src/plugins/imapsieve/ext-imapsieve-common.h +M src/plugins/imapsieve/imap-sieve-storage.h +M src/plugins/imapsieve/imap-sieve.h +M src/plugins/imapsieve/sieve-imapsieve-plugin.h +M src/plugins/lda-sieve/lda-sieve-log.h +M src/plugins/lda-sieve/lda-sieve-plugin.h +M src/plugins/sieve-extprograms/sieve-extprograms-common.h +M src/plugins/sieve-extprograms/sieve-extprograms-plugin.h +M src/testsuite/testsuite-arguments.h +M src/testsuite/testsuite-binary.h +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-log.h +M src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-objects.h +M src/testsuite/testsuite-result.h +M src/testsuite/testsuite-script.h +M src/testsuite/testsuite-settings.h +M src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite-substitutions.h +M src/testsuite/testsuite-variables.h + +2018-03-02 00:53:31 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (9f6db6f4) + + Remove copyright notices from header files. + + Dovecot core doesn't have copyright notices in header files. + +M src/lib-managesieve/managesieve-arg.h +M src/lib-managesieve/managesieve-parser.h +M src/lib-managesieve/managesieve-quote.h +M src/lib-sieve-tool/mail-raw.h +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/copy/sieve-ext-copy.h +M src/lib-sieve/plugins/date/ext-date-common.h +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.h +M src/lib-sieve/plugins/editheader/ext-editheader-common.h +M src/lib-sieve/plugins/editheader/ext-editheader-limits.h +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify-limits.h +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.h +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/environment/ext-environment-common.h +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/lib-sieve/plugins/ihave/ext-ihave-binary.h +M src/lib-sieve/plugins/ihave/ext-ihave-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/sieve-ext-imap4flags.h +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-limits.h +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/index/ext-index-common.h +M src/lib-sieve/plugins/mailbox/ext-mailbox-common.h +M src/lib-sieve/plugins/mailbox/sieve-ext-mailbox.h +M src/lib-sieve/plugins/metadata/ext-metadata-common.h +M src/lib-sieve/plugins/mime/ext-mime-common.h +M src/lib-sieve/plugins/notify/ext-notify-common.h +M src/lib-sieve/plugins/notify/ext-notify-limits.h +M src/lib-sieve/plugins/regex/ext-regex-common.h +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/lib-sieve/plugins/variables/ext-variables-arguments.h +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-dump.h +M src/lib-sieve/plugins/variables/ext-variables-limits.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-name.h +M src/lib-sieve/plugins/variables/ext-variables-namespaces.h +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug-common.h +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-common.h +M src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.h +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address-source.h +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-objects.h +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-plugins.h +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-runtime-trace.h +M src/lib-sieve/sieve-runtime.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve-smtp.h +M src/lib-sieve/sieve-storage-private.h +M src/lib-sieve/sieve-storage.h +M src/lib-sieve/sieve-stringlist.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.h +M src/lib-sieve/storage/dict/sieve-dict-storage.h +M src/lib-sieve/storage/file/sieve-file-storage.h +M src/lib-sieve/storage/ldap/sieve-ldap-storage.h +M src/lib-sieve/util/edit-mail.h +M src/lib-sieve/util/rfc2822.h +M src/managesieve-login/client-authenticate.h +M src/managesieve-login/client.h +M src/managesieve-login/managesieve-login-settings-plugin.h +M src/managesieve-login/managesieve-login-settings.h +M src/managesieve-login/managesieve-proxy.h +M src/managesieve/managesieve-capabilities.h +M src/managesieve/managesieve-client.h +M src/managesieve/managesieve-commands.h +M src/managesieve/managesieve-common.h +M src/managesieve/managesieve-quota.h +M src/managesieve/managesieve-settings.h +M src/plugins/doveadm-sieve/doveadm-sieve-cmd.h +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.h +M src/plugins/imapsieve/ext-imapsieve-common.h +M src/plugins/imapsieve/imap-sieve-plugin.h +M src/plugins/imapsieve/imap-sieve-storage.h +M src/plugins/imapsieve/imap-sieve.h +M src/plugins/imapsieve/sieve-imapsieve-plugin.h +M src/plugins/lda-sieve/lda-sieve-log.h +M src/plugins/lda-sieve/lda-sieve-plugin.h +M src/plugins/sieve-extprograms/sieve-extprograms-common.h +M src/plugins/sieve-extprograms/sieve-extprograms-plugin.h +M src/testsuite/testsuite-arguments.h +M src/testsuite/testsuite-binary.h +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-log.h +M src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-objects.h +M src/testsuite/testsuite-result.h +M src/testsuite/testsuite-script.h +M src/testsuite/testsuite-settings.h +M src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite-substitutions.h +M src/testsuite/testsuite-variables.h + +2018-02-15 09:47:09 +0200 Aki Tuomi <aki.tuomi@dovecot.fi> (907d3b00) + + imapsieve: Check more imapsieve contexts + + Satisfies static analyzer, these were forgotten from + b2de2aee75963a1ac5b229a3578f08bca0d23a0e + +M src/plugins/imapsieve/imap-sieve-storage.c + +2018-02-08 12:19:52 +0200 Aki Tuomi <aki.tuomi@dovecot.fi> (b2de2aee) + + imapsieve: Check imapsieve contexts + + Satisfies static analyzer + +M src/plugins/imapsieve/imap-sieve-storage.c + +2018-02-08 12:12:31 +0200 Aki Tuomi <aki.tuomi@dovecot.fi> (973963e5) + + doveadm-sieve-sync: Require sieve context + + +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c + +2018-02-13 09:51:48 +0200 Martti Rannanjärvi <martti.rannanjarvi@dovecot.fi> (36418e04) + + managesieve: Drop MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT flag + + The flag has been removed, and the setting is now the default. + +M src/managesieve/main.c + +2018-02-01 21:24:05 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (169dae70) + + plugins: imapsieve: Deal with messages being expunged concurrently by the + time Sieve filter is to be applied. + + Before, this was an assertion that got triggered transiently during + imaptest. + +M src/plugins/imapsieve/imap-sieve-storage.c + +2018-01-05 21:40:33 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (3a9ea428) + + tests: extprograms plugin: execute extension: Add test for large output from + program. + + +A tests/plugins/extprograms/bin/big +M tests/plugins/extprograms/execute/execute.svtest + +2018-01-05 21:44:29 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (d8d8cb8c) + + sieve-extprograms plugin: execute extension: Fix handling big output from + external program. + + The output buffer was on the data stack, which leads to big trouble when the + buffer needs to grow in a deeper stack level. + +M src/plugins/sieve-extprograms/cmd-execute.c + +2018-01-04 00:52:31 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (d4ee6c85) + + tests: imap4flags extension: Added more tests involving variables. + + +M tests/extensions/imap4flags/basic.svtest + +2018-01-04 00:39:38 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (8b9f5e2e) + + lib-sieve: imap4flags extension: Fix binary corruption occurring when + setflag/addflag/removeflag flag-list is a variable. + + The original implementation checked the first operand for being a variable. + Obviously, when the assigned flag string is just a variable, this doesn't + work. This causes the flag list to be recognized erroneously as a variable + flags string. Fixed the problem by explicitly emitting an omitted operand + when there is no second argument for a setflag/addflag/removeflag. + + Because the new byte code format is incompatible, the extension version is + bumped to 1. + +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c + +2018-01-01 20:09:40 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (00d2c5b7) + + Updated copyright notices to include the year 2018. + + +M doc/man/doveadm-sieve.1.in +M doc/man/pigeonhole.7.in +M doc/man/sieve-dump.1.in +M doc/man/sieve-filter.1.in +M doc/man/sieve-test.1.in +M doc/man/sievec.1.in +M src/lib-managesieve/managesieve-arg.c +M src/lib-managesieve/managesieve-arg.h +M src/lib-managesieve/managesieve-parser.c +M src/lib-managesieve/managesieve-parser.h +M src/lib-managesieve/managesieve-quote.c +M src/lib-managesieve/managesieve-quote.h +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/mail-raw.h +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/cmp-i-ascii-casemap.c +M src/lib-sieve/cmp-i-octet.c +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/copy/sieve-ext-copy.h +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/ext-date-common.h +M src/lib-sieve/plugins/date/ext-date.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.c +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.h +M src/lib-sieve/plugins/duplicate/ext-duplicate.c +M src/lib-sieve/plugins/duplicate/tst-duplicate.c +M src/lib-sieve/plugins/editheader/cmd-addheader.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.h +M src/lib-sieve/plugins/editheader/ext-editheader-limits.h +M src/lib-sieve/plugins/editheader/ext-editheader.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify-limits.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.h +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/environment/ext-environment-common.h +M src/lib-sieve/plugins/environment/ext-environment.c +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/ihave/cmd-error.c +M src/lib-sieve/plugins/ihave/ext-ihave-binary.c +M src/lib-sieve/plugins/ihave/ext-ihave-binary.h +M src/lib-sieve/plugins/ihave/ext-ihave-common.c +M src/lib-sieve/plugins/ihave/ext-ihave-common.h +M src/lib-sieve/plugins/ihave/ext-ihave.c +M src/lib-sieve/plugins/ihave/tst-ihave.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/imap4flags/sieve-ext-imap4flags.h +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-limits.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/index/ext-index-common.c +M src/lib-sieve/plugins/index/ext-index-common.h +M src/lib-sieve/plugins/index/ext-index.c +M src/lib-sieve/plugins/index/tag-index.c +M src/lib-sieve/plugins/mailbox/ext-mailbox-common.h +M src/lib-sieve/plugins/mailbox/ext-mailbox.c +M src/lib-sieve/plugins/mailbox/sieve-ext-mailbox.h +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/metadata/ext-metadata-common.h +M src/lib-sieve/plugins/metadata/ext-metadata.c +M src/lib-sieve/plugins/metadata/tst-metadata.c +M src/lib-sieve/plugins/metadata/tst-metadataexists.c +M src/lib-sieve/plugins/mime/cmd-break.c +M src/lib-sieve/plugins/mime/cmd-extracttext.c +M src/lib-sieve/plugins/mime/cmd-foreverypart.c +M src/lib-sieve/plugins/mime/ext-extracttext.c +M src/lib-sieve/plugins/mime/ext-foreverypart.c +M src/lib-sieve/plugins/mime/ext-mime-common.c +M src/lib-sieve/plugins/mime/ext-mime-common.h +M src/lib-sieve/plugins/mime/ext-mime.c +M src/lib-sieve/plugins/mime/tag-mime.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.h +M src/lib-sieve/plugins/notify/ext-notify-limits.h +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/plugins/regex/ext-regex-common.c +M src/lib-sieve/plugins/regex/ext-regex-common.h +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/lib-sieve/plugins/vacation/ext-vacation-seconds.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.h +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables-dump.h +M src/lib-sieve/plugins/variables/ext-variables-limits.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-name.c +M src/lib-sieve/plugins/variables/ext-variables-name.h +M src/lib-sieve/plugins/variables/ext-variables-namespaces.c +M src/lib-sieve/plugins/variables/ext-variables-namespaces.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug-common.h +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-common.h +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-items.c +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-variables.c +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment.c +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.c +M src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address-source.c +M src/lib-sieve/sieve-address-source.h +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary-code.c +M src/lib-sieve/sieve-binary-debug.c +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-objects.c +M src/lib-sieve/sieve-objects.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-plugins.c +M src/lib-sieve/sieve-plugins.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-runtime-trace.c +M src/lib-sieve/sieve-runtime-trace.h +M src/lib-sieve/sieve-runtime.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve-smtp.c +M src/lib-sieve/sieve-smtp.h +M src/lib-sieve/sieve-storage-private.h +M src/lib-sieve/sieve-storage-sync.c +M src/lib-sieve/sieve-storage.c +M src/lib-sieve/sieve-storage.h +M src/lib-sieve/sieve-stringlist.c +M src/lib-sieve/sieve-stringlist.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/storage/dict/sieve-dict-script.c +M src/lib-sieve/storage/dict/sieve-dict-storage.c +M src/lib-sieve/storage/dict/sieve-dict-storage.h +M src/lib-sieve/storage/file/sieve-file-script-sequence.c +M src/lib-sieve/storage/file/sieve-file-script.c +M src/lib-sieve/storage/file/sieve-file-storage-active.c +M src/lib-sieve/storage/file/sieve-file-storage-list.c +M src/lib-sieve/storage/file/sieve-file-storage-quota.c +M src/lib-sieve/storage/file/sieve-file-storage-save.c +M src/lib-sieve/storage/file/sieve-file-storage.c +M src/lib-sieve/storage/file/sieve-file-storage.h +M src/lib-sieve/storage/ldap/sieve-ldap-db.c +M src/lib-sieve/storage/ldap/sieve-ldap-script.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage-settings.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c +M src/lib-sieve/tst-truefalse.c +M src/lib-sieve/util/edit-mail.c +M src/lib-sieve/util/edit-mail.h +M src/lib-sieve/util/rfc2822.c +M src/lib-sieve/util/rfc2822.h +M src/managesieve-login/client-authenticate.c +M src/managesieve-login/client-authenticate.h +M src/managesieve-login/client.c +M src/managesieve-login/client.h +M src/managesieve-login/managesieve-login-settings-plugin.c +M src/managesieve-login/managesieve-login-settings-plugin.h +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve-login/managesieve-login-settings.h +M src/managesieve-login/managesieve-proxy.c +M src/managesieve-login/managesieve-proxy.h +M src/managesieve/cmd-capability.c +M src/managesieve/cmd-deletescript.c +M src/managesieve/cmd-getscript.c +M src/managesieve/cmd-havespace.c +M src/managesieve/cmd-listscripts.c +M src/managesieve/cmd-logout.c +M src/managesieve/cmd-noop.c +M src/managesieve/cmd-putscript.c +M src/managesieve/cmd-renamescript.c +M src/managesieve/cmd-setactive.c +M src/managesieve/main.c +M src/managesieve/managesieve-capabilities.c +M src/managesieve/managesieve-capabilities.h +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h +M src/managesieve/managesieve-commands.c +M src/managesieve/managesieve-commands.h +M src/managesieve/managesieve-common.h +M src/managesieve/managesieve-quota.c +M src/managesieve/managesieve-quota.h +M src/managesieve/managesieve-settings.c +M src/managesieve/managesieve-settings.h +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-activate.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-delete.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-get.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-list.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-put.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-rename.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd.h +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.h +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c +M src/plugins/imapsieve/ext-imapsieve-common.h +M src/plugins/imapsieve/ext-imapsieve-environment.c +M src/plugins/imapsieve/ext-imapsieve.c +M src/plugins/imapsieve/imap-sieve-plugin.c +M src/plugins/imapsieve/imap-sieve-plugin.h +M src/plugins/imapsieve/imap-sieve-storage.c +M src/plugins/imapsieve/imap-sieve-storage.h +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/imapsieve/imap-sieve.h +M src/plugins/imapsieve/sieve-imapsieve-plugin.c +M src/plugins/imapsieve/sieve-imapsieve-plugin.h +M src/plugins/lda-sieve/lda-sieve-log.c +M src/plugins/lda-sieve/lda-sieve-log.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/plugins/lda-sieve/lda-sieve-plugin.h +M src/plugins/settings/pigeonhole-settings.c +M src/plugins/sieve-extprograms/cmd-execute.c +M src/plugins/sieve-extprograms/cmd-filter.c +M src/plugins/sieve-extprograms/cmd-pipe.c +M src/plugins/sieve-extprograms/ext-execute.c +M src/plugins/sieve-extprograms/ext-filter.c +M src/plugins/sieve-extprograms/ext-pipe.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.h +M src/plugins/sieve-extprograms/sieve-extprograms-plugin.c +M src/plugins/sieve-extprograms/sieve-extprograms-plugin.h +M src/sieve-tools/sieve-dump.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-imap-metadata.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-result.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-arguments.c +M src/testsuite/testsuite-arguments.h +M src/testsuite/testsuite-binary.c +M src/testsuite/testsuite-binary.h +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-log.h +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-result.h +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-script.h +M src/testsuite/testsuite-settings.c +M src/testsuite/testsuite-settings.h +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite-substitutions.c +M src/testsuite/testsuite-substitutions.h +M src/testsuite/testsuite-variables.c +M src/testsuite/testsuite-variables.h +M src/testsuite/testsuite.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-action.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c + +2017-12-25 18:20:14 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (321a39be) + + plugins: sieve-extprograms: Fix segfault occurring when used in IMAPSieve + context. + + This was caused by recent lib-smtp changes. There is no envelope in + IMAPSieve context, so the rcpt parameters are NULL, causing the segfault. + +M src/plugins/sieve-extprograms/sieve-extprograms-common.c + +2017-12-23 16:37:27 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (480eb777) + + plugins: lda-sieve: Remove session ID prefix from log messages. + + The session ID is now already added by Dovecot. + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2017-12-18 21:11:31 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (15f05db9) + + lib-sieve: vacation extension: Use the correct address for "From:" outgoing + header when original envelope recipient is found. + + Caused by earlier adjustments for Dovecot lib-smtp. Copy-paste problem + detected by Coverity. + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2017-12-18 19:55:03 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (c8b4ade0) + + test suite: enotify extension: Remove stray test_message_print call. + + It is a remnant from debugging. + +M tests/extensions/enotify/mailto.svtest + +2017-12-16 02:04:09 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (6670190d) + + global: Change calls to array_idx_modifiable to array_idx_get_space. + + Only calls that require space allocation are to be changed. + +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-validator.c + +2017-12-16 01:31:38 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (82a16434) + + configure: Switched version number to 0.6.devel. + + +M configure.ac + +2017-12-03 13:17:24 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (1b2454cf) + + lib-sieve: Fixed writing address headers to outgoing messages. + + It erroneously applied another layer of MIME header encoding. The problem is + that existing Sieve scripts may rely on this behaviour; i.e. scripts may + contain addresesses with literal UTF8 in the phrase part. Therefore, this + change allows both behaviors. + +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M tests/extensions/enotify/mailto.svtest +M tests/extensions/vacation/utf-8.svtest + +2017-12-03 12:52:03 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (811f84f8) + + lib-sieve: util: rfc2822: Added rfc2822_header_write_address() which allows + adding a header with one or more addresses. + + It applies UTF8 encoding only when the address string somehow contains 8-bit + characters. Sieve addresses are supposed to have any UTF8 characters in the + phase MIME-encoded, not literal 8-bit characters. However, this has been + allowed from the beginning, so disabling the old behavior may break existing + installations. This function allows supporting both options. + +M src/lib-sieve/util/rfc2822.c +M src/lib-sieve/util/rfc2822.h + +2017-12-11 17:39:04 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (fe3b7c4b) + + managesieve: Include mail user variables in logout format + + Also dropped the single-letter identifier for most fields to prevent + conflicts with mail user variables; these were undocumented anyway. + +M src/managesieve/managesieve-client.c + +2017-12-11 17:35:07 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (95a0c04a) + + doc: example-config: Document remaining supported managesieve_logout_format + substitution variables. + + A few were still omitted. + +M doc/example-config/conf.d/20-managesieve.conf + +2017-12-11 17:14:27 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (dbc3f2f8) + + global: start relying on [io]_stream_unref(NULL) being a no-op + + Cleanup performed with the following semantic patch: + + @@ + expression E; + @@ + + - if (E != NULL) { + - i_stream_unref(&E); + - } + + i_stream_unref(&E); + + @@ + expression E; + @@ + + - if (E != NULL) { + - o_stream_unref(&E); + - } + + o_stream_unref(&E); + +M src/lib-managesieve/managesieve-parser.c +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve/sieve-script.c +M src/lib-sieve/storage/ldap/sieve-ldap-db.c +M src/lib-sieve/util/edit-mail.c + +2017-12-11 17:08:21 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (45cfd196) + + global: start relying on timeout_remove(NULL) being a no-op + + Cleanup performed with the following semantic patch: + + @@ + expression E; + @@ + + - if (E != NULL) { + - timeout_remove(&E); + - } + + timeout_remove(&E); + +M src/lib-sieve/storage/ldap/sieve-ldap-db.c +M src/managesieve-login/client.c +M src/managesieve/managesieve-client.c + +2017-12-11 17:04:28 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (ca1773cd) + + global: start relying on io_remove{,_closed}(NULL) being a no-op + + Cleanup performed with the following semantic patch: + + @@ + expression E; + @@ + + - if (E != NULL) { + - io_remove(&E); + - } + + io_remove(&E); + + @@ + expression E; + @@ + + - if (E != NULL) { + - io_remove_closed(&E); + - } + + io_remove_closed(&E); + +M src/lib-sieve/storage/ldap/sieve-ldap-db.c +M src/managesieve/managesieve-client.c + +2017-12-15 13:21:30 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (b5a9750a) + + lib-sieve: Adjusted to changes in handling of postmaster_address setting in + Dovecot. + + Error handling is delayed, so that we need to explicitly handle the error in + Sieve. This is now implemented by handling the error before executing the + scritpt and placing the parsed address in struct sieve_script_env. + +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c + +2017-12-15 12:46:54 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (15ddc4a0) + + lib-sieve: Added sieve_script_env_init() to initialize struct + sieve_script_env from struct mail_user. + + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite.c + +2017-12-15 12:31:34 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (68395161) + + plugins: lda-sieve: Restructured lda_sieve_execute() to reduce indent. + + Most code was put in an unnecessary else block. + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2017-12-13 19:57:39 +0200 Timo Sirainen <timo.sirainen@dovecot.fi> (32bdac72) + + lib-sieve: file storage: When autodetecting storage path, use home even if + it doesn't exist + + If a home directory is given, it's assumed that it will be autocreated even + if it doesn't initially exist. Earlier the autocreation may have been done + by lib-storage as it created the mail root directory, but this no longer + happens. + +M src/lib-sieve/storage/file/sieve-file-storage.c + +2017-12-12 16:35:55 +0200 Timo Sirainen <timo.sirainen@dovecot.fi> (cedc5e4b) + + global: Adjust to mail_user_alloc() API change + + The parent event doesn't really matter here, so NULL is used. + +M src/lib-sieve-tool/sieve-tool.c +M src/testsuite/testsuite-mailstore.c + +2017-12-11 16:45:58 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (624e1769) + + managesieve: Adjusted to lib-storage changes in Dovecot. + + This follows the following commits in Dovecot: lib-storage: Moved connection + information in struct mail_user into separate struct + mail_user_connection_data. lib-storage: mail-user: Added more information + about the client connection. + +M src/managesieve/main.c + +2017-12-03 13:01:53 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (37853002) + + lib-sieve: vnd.dovecot.report extension: Fixed creation of + "Original-Mail-From" and original "Original-Rcpt-To" headers. + + Recent changes relating to lib-smtp caused the paths to have duplicate '<' + '>'. + +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c + +2017-12-03 12:50:26 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (4a9bc3d2) + + lib-sieve: enotify extension: mailto method: Fixed parsing of mailto URI + with only a header part. + + +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c + +2017-01-20 19:16:06 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (fbedb2db) + + Adjusted to the lib-smtp changes in Dovecot. + + Now using struct smtp_address rather than sieve_address. In some cases, + struct message_address may prove to be more suitable, but this is the best + fit for now. Adjusted to the renamed fields in struct mail_deliver_context. + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.h +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.h +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address-source.c +M src/lib-sieve/sieve-address-source.h +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-smtp.c +M src/lib-sieve/sieve-smtp.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c +M src/plugins/imapsieve/ext-imapsieve-environment.c +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/Makefile.am +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite.c +M tests/execute/smtp.svtest +M tests/extensions/envelope.svtest +M tests/extensions/reject/smtp.svtest + +2017-11-16 00:07:14 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (89f1d4ab) + + lib-sieve: enotify extension: uri-mailto: Removed unused field. + + It doesn't serve a purpose either, since parsing "from" address from URI is + not allowed for notify mailto. + +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.h + +2017-11-25 11:51:02 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (81505779) + + lib-sieve: store action: Avoid NULL pointer dereference during rollback when + transaction context is somehow unassigned. + + This change matches the other transaction stages. This will not currently + happen though. Reported by Coverity. + +M src/lib-sieve/sieve-actions.c + +2017-11-25 11:45:52 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (972bafc4) + + lib-managesieve: managesieve-parser: Return error status in quoted string + stream immediately. + + Otherwise the error status is overwritten. Problem found by Coverity. + +M src/lib-managesieve/managesieve-parser.c + +2017-11-25 11:28:57 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (c9cf5650) + + lib-sieve: util: edit-mail: Fixed potential NULL dereference in + edit_mail_istream_seek(). + + Used the stream's cur_header field, rather than the local variable. Problem + found by Coverity. + +M src/lib-sieve/util/edit-mail.c + +2017-11-25 11:22:56 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (1e20fa6c) + + lib-sieve: util: edit-header: Fixed potential NULL dereference in + edit_mail_istream_read(). + + The merge_from_parent() function may not actually read anything, potentially + leaving the stream buffer unassigned. Problem found by Coverity. + +M src/lib-sieve/util/edit-mail.c + +2017-03-31 01:48:41 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (6f31aa72) + + lib-sieve: variables extension: Made the maximum scope and variable size + configurable. + + +M INSTALL +A doc/extensions/variables.txt +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/mime/cmd-extracttext.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables-limits.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/plugins/sieve-extprograms/cmd-execute.c + +2017-11-03 21:31:36 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (56b46cd0) + + lib-sieve: util: edit-mail: Changed buffer implementation to use normal + stream buffer management. + + This makes the implementation easier to understand and amend once Dovecot + APIs changes. This implicitly makes the implementation suitable for the new + istream snapshot handling. + +M src/lib-sieve/util/edit-mail.c + +2017-11-04 00:42:47 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (c8a70d56) + + lib-sieve: util: edit-mail: Restructured merge_modified_headers() to remove + useless indent. + + +M src/lib-sieve/util/edit-mail.c + +2017-11-03 21:26:52 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (ce92b90b) + + lib-sieve: util: edit-mail: Properly remember the detection of EOF in the + edit mail stream. + + +M src/lib-sieve/util/edit-mail.c + +2017-11-02 11:43:08 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (87402574) + + lib-sieve: util: edit-mail: Fixed runtime integer arithmetic warnings + (CLang). + + Added assertions on subtractions. Restructured the code for clarity. Added + comments. + +M src/lib-sieve/util/edit-mail.c + +2017-11-03 21:33:06 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (48a29a0b) + + testsuite: editheader extension: Added a few more tests. + + +M tests/extensions/editheader/addheader.svtest + +2017-11-01 22:55:34 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (daeff904) + + lib-managesieve: managesieve-parser: Adjusted quoted string stream to + istream changes in Dovecot. + + Ported Dovecot's istream-jsonstr for ManageSieve syntax. + +M src/lib-managesieve/managesieve-parser.c + +2017-11-01 22:54:05 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (c582d151) + + managesieve: putscript command: Fixed parse error handling for save parser. + + +M src/managesieve/cmd-putscript.c + +2017-11-07 00:42:24 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (96fe42e7) + + managesieve-login: Removed ssl-proxy.h include forgotten in the previous + commit. + + +M src/managesieve-login/client.c + +2017-11-02 15:28:32 +0200 Timo Sirainen <timo.sirainen@dovecot.fi> (001d9f1f) + + managesieve-login: Core API change - rename ssl_initialized to + login_ssl_initialized + + +M src/managesieve-login/client.c + +2017-11-02 23:45:17 +0200 Timo Sirainen <timo.sirainen@dovecot.fi> (a5b04e7a) + + managesieve: Don't access login_set.*_socket_path after they're freed from + data stack + + Call master_login_init() before master_service_init_finish(), which frees + all the data stack done in initialization. + + This didn't normally cause any visible problems, because data stack wasn't + currently being used in a way that the strings were invalidated. However, it + was causing failures if --enable-devel-checks was used. + +M src/managesieve/main.c + +2017-11-02 09:54:39 +0200 Martti Rannanjärvi <martti.rannanjarvi@dovecot.fi> (4fd3b53a) + + lib-managesieve,lib-sieve: Add istream_create_flag parameter to + i_stream_create + + +M src/lib-managesieve/managesieve-parser.c +M src/lib-sieve/util/edit-mail.c + +2017-11-01 11:57:58 +0200 Aki Tuomi <aki.tuomi@dovecot.fi> (6558a20e) + + lib-sieve: Fix undefined define + + +M src/lib-sieve/storage/ldap/sieve-ldap-db.h + +2017-10-30 16:14:26 +0200 Timo Sirainen <timo.sirainen@dovecot.fi> (f4659224) + + global: Rename i_stream_is_eof() to i_stream_read_eof() + + +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c + +2017-10-28 03:16:35 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (40c54675) + + global: Replace o_stream_nfinish() with o_stream_finish + + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/sieve.c +M src/testsuite/testsuite-smtp.c + +2017-10-29 21:27:05 +0200 Aki Tuomi <aki.tuomi@dovecot.fi> (0f46b1d8) + + configure: Support EXTRA_CFLAGS/LDFLAGS + + +M configure.ac + +2017-10-23 15:11:18 +0300 Aki Tuomi <aki.tuomi@dovecot.fi> (97a87ac7) + + lib-sieve: Use uni_is_valid_ucs4 to check ucs4 validity + + +M src/lib-sieve/ext-encoded-character.c + +2017-10-23 01:34:09 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (454bbd47) + + managesieve: Fixed spelling mistake in source code. + + Patch by Andreas Schulze. + +M src/managesieve/managesieve-common.h + +2017-10-23 01:32:34 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (d0dab022) + + lib-sieve: Fixed spelling mistakes in source code. + + Patch by Andreas Schulze. + +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-storage.c + +2017-10-23 01:31:49 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (f85c4e8c) + + doc/man/sieve-test.1: Fixed spelling mistake. + + Patch by Andreas Schulze. + +M doc/man/sieve-test.1.in + +2017-10-21 12:45:29 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (1210d338) + + lib-sieve: enotify plugin: mailto method: Make sure from header is set to a + usable address and not (null). + + +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c + +2017-10-06 18:51:40 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (8b5be61d) + + managesieve: Remove fd-set-nonblock.h includes. + + It's replaced with fd-util.h which is automatically included now. + +M src/managesieve-login/managesieve-login-settings-plugin.c +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve/main.c + +2017-10-06 13:57:31 +0300 Aki Tuomi <aki.tuomi@dovecot.fi> (620b7808) + + lib-sieve-tool: Remove fd-set-nonblock.h + + It's replaced with fd-util.h which is automatically included now + +M src/lib-sieve-tool/mail-raw.c + +2017-10-05 23:29:25 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (37e8f71c) + + managesieve: Fix missing-command check + + Mirrors imap fix in Dovecot: 42149f48624b82fdf9631c256497580154c2e412 + + It's impossible for the command's pointer to be NULL at this point. + Previously, the command_find() would have returned NULL, but this check + presumably short-circuits that search in the trivial case, so has some real + use. + + Problem now found by GCC 7. + +M src/managesieve/managesieve-client.c + +2017-10-05 23:19:13 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (15f9fd11) + + imapsieve: Fixed check for the presence of causes in a mailbox rule. + + Problem found by GCC 7. + +M src/plugins/imapsieve/imap-sieve-storage.c + +2017-10-05 23:15:17 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (370b9739) + + lib-sieve: sieve-result: Added /* fall through */ comment to mark + intentional switch case fall through. + + Addresses GCC 7 warning. + +M src/lib-sieve/sieve-result.c + +2017-09-22 15:59:15 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (a0997e4f) + + Obtain postmaster_address and hostname from mail_storage_settings. + + +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-address-source.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite.c + +2017-09-14 04:11:42 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (1b42755f) + + plugins: Migrated from lib-lda/smtp-client.h to using lib-smtp/smtp-submit.h + for message submission. + + +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2017-09-16 14:48:52 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (8b7bf6b6) + + plugins/imapsieve: Initialize struct imap_sieve with full struct client, + rather than individual fields. + + +M src/plugins/imapsieve/imap-sieve-storage.c +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/imapsieve/imap-sieve.h + +2017-10-04 23:32:23 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (4d0db1ce) + + Adjusted to changes in Dovecot mail_duplicate API. + + +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2017-09-14 03:31:55 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (3ac2b15c) + + lib-sieve: Dropped lib-lda dependencies. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-result.c + +2017-09-30 21:19:11 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (418816cd) + + lib-sieve: redirect action: Always set X-Sieve-Redirected-From header to + sieve_user_email if configured. + + Set it to the final recipient only when there is an envelope and + sieve_user_email is unconfigured. + +M src/lib-sieve/cmd-redirect.c +M tests/execute/smtp.svtest + +2017-09-30 21:23:44 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (b38df93b) + + testsuite: Fixed redirect action tests to use the correct test message. + + +M tests/execute/smtp.svtest + +2017-09-22 16:30:26 +0300 Martti Rannanjärvi <martti.rannanjarvi@dovecot.fi> (c978393b) + + global: Add reasons to mailbox_transaction_begins + + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-storage-sync.c +M src/lib-sieve/util/edit-mail.c +M src/plugins/imapsieve/imap-sieve-storage.c +M src/sieve-tools/sieve-filter.c +M src/testsuite/testsuite-mailstore.c + +2017-08-24 02:03:21 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (8643cbde) + + lib-sieve: vacation extension: Allow ignoring the envelope sender while + composing the "To:" header for the reply. + + This adds a new setting "sieve_vacation_to_header_ignore_envelope". With + this setting enabled, the "To:" header is always composed from the first + "Sender", "Resent-From" or "From" header found in the message (in that + order). Normally, the "To:" header is composed from the address found in the + "Sender", "Resent-From" or "From" headers that is equal to the envelope + sender. If none is then found, the bare envelope sender is used. The new + setting allows ignoring the envelope, which is useful e.g. when SRS is used. + +M doc/extensions/vacation.txt +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M tests/extensions/vacation/message.svtest + +2017-09-05 21:29:06 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (2b3aca5a) + + LDA Sieve plugin: Fixed sequential exection of LDAP-based scripts. + + The sequence was broken when the LDAP script attribute does not exist; i.e., + when the script is not found. The NOT_FOUND error is returned at a later + instance than normal fs-based scripts, explaining why this problem does not + normally occur. + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2017-09-05 20:26:21 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (15bd3533) + + LDA Sieve plugin: Restructured execution of scripts by putting execution of + individual scripts in separate function. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2017-08-29 22:43:49 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (e5ea21fb) + + lib-sieve: imap4flags extension: Added API for runtime initialization of + derived extensions. + + This is needed to register the implicit side effect for the internal flag + variable. + +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/imap4flags/sieve-ext-imap4flags.h + +2017-08-30 21:27:42 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (736f94ea) + + imapsieve plugin: Fixed copyright messages. + + +M src/plugins/imapsieve/imap-sieve-plugin.c +M src/plugins/imapsieve/imap-sieve-storage.c + +2017-08-28 13:04:40 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (e37583a9) + + sieve-filter: Removed (now) duplicate utf8 to mutf7 mailbox name conversion. + + The Dovecot API was changed years ago, but apparently sieve-filter was never + updated. + +M src/sieve-tools/sieve-filter.c + +2017-08-22 13:15:34 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (dc20a45f) + + imapsieve plugin: Provide proper error details upon failure to access the + mailbox/server script METADATA attribute. + + This addresses an old FIXME. + +M src/plugins/imapsieve/imap-sieve-storage.c + +2017-08-18 16:20:22 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (e0e179b3) + + lib-sieve: vacation extension: Fixed invalid return value in function added + by previous change. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2017-08-17 18:59:33 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (d55d8773) + + lib-sieve: vacation extension: Compose the "To:" header from full sender + address found in the first "Sender:", "From:" or "Resent-From:" header. + + Before, it would create a "To:" header without a phrase part. The new + behavior is nicer, since the reply will be addressed to the sender by name + if possible. This addresses an old FIXME. + +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M tests/extensions/vacation/message.svtest + +2017-08-17 00:17:13 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (c7882e61) + + lib-sieve: vacation extension: Use mail_get_first_header*() rather than + mail_get_headers(*). + + Only the first header is ever of interest. + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2017-08-17 00:15:27 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (3a1ce369) + + testsuite: vacation extension: Test creation of subject header better. + + +M tests/extensions/vacation/message.svtest + +2017-07-08 10:51:27 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (d188419f) + + sieve-tools: sieve-filter: Forgot to clean up script binary at end of + execution. + + Normally, this would merely be an inconsequential memory leak. However, when + the script comes from an LDAP storage, the storage is not closed before + master_service_deinit() -> io_loop_destroy(). The LDAP connection's stale io + can cause problems while closing the main ioloop. + +M src/sieve-tools/sieve-filter.c + +2017-07-08 10:27:52 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (7aabfac4) + + sieve-tools: Terminate with a fatal error when script cannot be + compiled/opened. + + Rather than continuing with binary == NULL, causing a segfault. + +M src/lib-sieve-tool/sieve-tool.c + +2017-07-06 12:34:08 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (c80aa7c2) + + managesieve-login: managesieve_client_input_next_cmd(): Fix handling of + command continuation. + + Commands that continued after waiting for more input always failed. This + mainly applies to the AUTHENTICATE command, which mostly handles its own + arguments. This caused problems when a string literal was used as the + initial response for the AUTHENTICATE command. + + Caused by recent change: + + Author: Timo Sirainen <timo.sirainen@dovecot.fi> Date: Wed Jun 14 12:39:02 + 2017 +0300 + + managesieve-login: managesieve_client_input_next_cmd() - minor code cleanup + +M src/managesieve-login/client.c + +2017-07-06 12:28:44 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (f7b63d94) + + managesieve-login: authenticate command: Make sure + client->auth_mech_name_parsed is reset properly upon command error. + + This could cause problems for any subsequent AUTHENTICATE commmend. + +M src/managesieve-login/client-authenticate.c + +2017-06-28 18:41:33 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (dd34509a) + + LDA Sieve plugin: Fixed memory leak caused by not cleaning up the + sieve_discard script. + + Moved script cleanup to separate function as well. + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2017-06-22 21:12:21 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (c024dc7c) + + lib-sieve: include extension: Fixed segfault that (sometimes) occurred when + the global script location was left unconfigured. + + +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-common.c + +2017-06-20 23:36:10 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (f68f5637) + + sieve-tools: Make sure sieve command line tools properly show debug messages + if requested. + + +M src/lib-sieve-tool/sieve-tool.c +M src/sieve-tools/sieve-filter.c + +2017-06-13 19:36:57 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (de4248b9) + + lib-sieve: Made the retention period for redirect duplicate identifiers + configurable. + + For accounts that perform many redirects, the lda-dupes database could grow + to impractical sizes. Changed the default retention period from 24 to 12 + hours. + +M INSTALL +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-settings.c + +2017-06-20 20:46:28 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (82563e97) + + lib-sieve: Clear extension context upon unload. + + +M src/lib-sieve/sieve-extensions.c + +2017-06-16 14:42:39 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (072b0b49) + + managesieve-login: Adjust to new client_vfuncs.free() API change + + +M src/managesieve-login/client.c + +2017-06-14 12:39:46 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (303e561c) + + managesieve-login: managesieve_client_input_next_cmd() - Add assert to help + static analyzer + + +M src/managesieve-login/client.c + +2017-06-14 12:39:02 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (ea7e1789) + + managesieve-login: managesieve_client_input_next_cmd() - minor code cleanup + + +M src/managesieve-login/client.c + +2017-06-12 23:00:26 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (9d66c3e5) + + managesieve-login: Adjust to login-common API change + + +M src/managesieve-login/client.c + +2017-04-28 00:02:39 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (3e1a17a2) + + lib-sieve: Fixed bug in handling of deferred implicit keep with implicit + side-effects. + + Upon continuing the deferred implicit keep, the implicit side-effects (such + as imap flags) were not applied. + +M src/lib-sieve/sieve-result.c + +2017-04-24 18:58:07 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (11d5f197) + + imapsieve: Use client_add_capability() for adding the dynamic capability + + +M src/plugins/imapsieve/imap-sieve-plugin.c + +2017-04-21 13:37:40 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (649c7785) + + managesieve-login: Fill the new client_vfuncs.send_raw_data + + +M src/managesieve-login/client.c + +2017-04-12 13:17:53 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (6891f70d) + + imapsieve: Fixed flag assignment for the source message. + + Implicit keep was deferred for the source message, which discards all flags. + +M src/plugins/imapsieve/imap-sieve.c + +2017-04-05 16:02:51 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (b8af3b97) + + managesieve-login: Fill the new banner_sent field. + + +M src/managesieve-login/client.c + +2017-03-10 21:48:14 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (e69a6dec) + + imapsieve plugin: Implemented the copy_source_after rule action. + + When this is enabled for a mailbox rule, the specified Sieve script is + executed for the message in the source mailbox during a "COPY" event. This + happens only after the Sieve script that is executed for the corresponding + message in the destination mailbox finishes running successfully. + +M doc/plugins/imapsieve.txt +M src/plugins/imapsieve/imap-sieve-storage.c + +2017-03-10 21:53:19 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (71e773ca) + + imapsieve plugin: Prevent recording events for the COPY/MOVE source mailbox + transaction. + + This already has the imapsieve transaction context associated with it before + the sieve scripts are executed. This currently cannot occur, but it will + become relevant in subsequent commits. + +M src/plugins/imapsieve/imap-sieve-storage.c + +2017-03-10 21:44:36 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (b7ade8c3) + + imapsieve plugin: Added non-standard Sieve environment items for source and + destination mailbox. + + +M doc/plugins/imapsieve.txt +M src/plugins/imapsieve/ext-imapsieve-common.h +M src/plugins/imapsieve/ext-imapsieve-environment.c +M src/plugins/imapsieve/ext-imapsieve.c +M src/plugins/imapsieve/imap-sieve-storage.c +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/imapsieve/imap-sieve.h +M src/plugins/imapsieve/sieve-imapsieve-plugin.c + +2017-03-10 21:36:13 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (1748e01b) + + imapsieve plugin: Don't open the user's personal script storage if no + personal script is configured. + + +M src/plugins/imapsieve/imap-sieve.c + +2017-03-10 21:31:40 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (148ba040) + + imapsieve plugin: Forgot to cleanup imap_sieve_run object when + mailbox_sync() fails. + + +M src/plugins/imapsieve/imap-sieve-storage.c + +2017-03-16 20:56:46 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (e0283189) + + lib-sieve: multiscript: The execution of the discard script had an implicit + "keep", rather than an implicit "discard". + + +M src/lib-sieve/sieve.c + +2017-03-09 12:13:04 -0500 Timo Sirainen <timo.sirainen@dovecot.fi> (8053c068) + + managesieve-login: Log proxy state as human-readable string + + +M src/managesieve-login/client.c +M src/managesieve-login/client.h +M src/managesieve-login/managesieve-proxy.c +M src/managesieve-login/managesieve-proxy.h + +2017-03-09 12:10:30 -0500 Timo Sirainen <timo.sirainen@dovecot.fi> (9f9bc901) + + managesieve-login: Use enum managesieve_proxy_state for proxy_state + + +M src/managesieve-login/client.h +M src/managesieve-login/managesieve-proxy.c + +2017-02-26 19:23:34 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (bf2bd0ff) + + lib-sieve: store action: Made static analyzer happier about tr_context + argument for sieve_act_store_add_flags(). + + Added an assert ensuring it is not NULL. + +M src/lib-sieve/sieve-actions.c + +2017-02-26 18:25:53 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (7d06cde9) + + managesieve: Fix creation of critical error message timestamp. + + This used strftime() directly and allocated memory from the heap before + i_fatal(). It also used printf() to send the BYE message, which will only + work right when the service is running stand-alone. + +M src/managesieve/managesieve-client.c + +2017-02-22 13:36:26 +0200 Timo Sirainen <timo.sirainen@dovecot.fi> (92f3d323) + + global: Replace mail_storage_service_user_free() with _unref() + + +M src/lib-sieve-tool/sieve-tool.c +M src/managesieve/main.c +M src/managesieve/managesieve-client.c + +2017-02-16 17:00:53 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (c4df3317) + + lib-sieve: Made public function for adding a redirect action to the result. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h + +2017-02-07 18:10:48 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (25a5a493) + + lib-sieve: Implemented means to abort SMTP message submission after it is + started. + + This adds a new callback to the Sieve script execution environment. + +M src/lib-sieve/sieve-smtp.c +M src/lib-sieve/sieve-smtp.h +M src/lib-sieve/sieve-types.h +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite.c + +2017-02-19 00:55:12 +0200 Timo Sirainen <timo.sirainen@dovecot.fi> (051cf477) + + doveadm-sieve: Fix crash when setting Sieve script via attribute's string + value. + + +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c + +2017-02-09 18:48:20 +0200 Timo Sirainen <timo.sirainen@dovecot.fi> (a1dbf7a9) + + lib-sieve: Remove unnecessary mailbox_save_set_dest_mail() call + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h + +2017-02-09 17:26:29 +0200 Timo Sirainen <timo.sirainen@dovecot.fi> (85c9de00) + + imapsieve: Remove unnecessary mail_save_context.dest_mail==NULL checks + + It can never be NULL after the "lib-storage: Always create + mail_save_context.dest_mail" core change. + +M src/plugins/imapsieve/imap-sieve-storage.c + +2017-02-12 15:29:14 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (298b3410) + + lib-sieve: file storage: Amended the up-to-date timestamp comparison for + on-disk binaries to include nanoseconds. + + This will fix problems occurring when both binary and script are saved + within the same second. On older systems that have no support for + nanoseconds in the stat() time stamps, this has no effect. + +M src/lib-sieve/storage/file/sieve-file-script.c + +2017-02-12 15:28:44 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (602326ee) + + lib-sieve: binary: Added means to obtain stat() information from loaded + binary. + + +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h + +2017-02-12 14:01:41 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (014df56e) + + imapsieve plugin: Make sure "INBOX" is upper case in static mailbox rules. + + Otherwise, the mailbox name would never match, since matching is performed + case-sensitively and Dovecot only returns the upper-cased "INBOX". This + change prevents confusing administrators that for some reason choose to use + a different capitalization of that mailbox name. + +M src/plugins/imapsieve/imap-sieve-storage.c + +2017-02-12 11:46:31 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (34d44f7a) + + lib-sieve: file storage: Improve save permission error. + + Use eacces_error_get(), rather than just printing "Permission denied". + +M src/lib-sieve/storage/file/sieve-file-storage-save.c + +2017-02-08 02:08:17 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (51e4ff29) + + lib-sieve: file storage: Improve listing permission error. + + Use eacces_error_get(), rather than just printing "Permission denied". + +M src/lib-sieve/storage/file/sieve-file-storage-list.c + +2016-11-28 18:55:10 +0200 Martti Rannanjärvi <martti.rannanjarvi@dovecot.fi> (03434fa4) + + global: Replace realpath with path-util from core. + + path-util is a merge of realpath from Pigeonhole and abspath from core. + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve/storage/file/sieve-file-script.c +M src/lib-sieve/storage/file/sieve-file-storage-active.c +M src/lib-sieve/storage/file/sieve-file-storage.c +M src/lib-sieve/util/Makefile.am +D src/lib-sieve/util/realpath.c +D src/lib-sieve/util/realpath.h +M src/managesieve/main.c +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite.c + +2017-01-14 02:52:42 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (462a5352) + + lib-sieve: Fixed transaction context passed to finish() method of action + object in two cases. + + This is not currently used anywhere, so nothing actually broke. This bug was + exposed by the previous commit, causing a compiler error/warning on some + compilers. + +M src/lib-sieve/sieve-result.c + +2017-01-13 23:24:10 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (77248553) + + lib-sieve: Fixed handling of an early explicit keep during multiscript + execution. + + Applies to LDA/LMTP context in general, not only when + sieve_before/sieve_after are used. Action side-effects and the message + snapshot would be lost at the final stage where the implicit keep is + evaluated. This happened because the keep action itself is not actually + executed, but rather its presence is noted to determine whether more scripts + need to be executed. So, when finally execution of the actual keep action is + due, i.e. when there are no more scripts in the sequence, it overrides the + explicit keep from the last script. This didn't take the side-effects and + message snapshot into account. + +M src/lib-sieve/sieve-result.c + +2017-01-11 21:01:45 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (2583936f) + + Updated dovecot.m4. + + +M m4/dovecot.m4 + +2017-01-10 23:22:28 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (f9b37da1) + + lib-sieve: Fixed handling of mail_get_headers()/mail_get_headers_utf8() + result. + + The situation where no headers are found was not always handled correctly. + +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/sieve-message.c + +2017-01-11 01:13:45 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (22cbd7e7) + + lib-sieve: util: edit-mail: Fixed success return value for + mail_get_headers() to be 1. + + +M src/lib-sieve/util/edit-mail.c + +2017-01-01 13:32:21 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (57c05f4d) + + Updated copyright notices to include the year 2017. + + +M doc/man/doveadm-sieve.1.in +M doc/man/pigeonhole.7.in +M doc/man/sieve-dump.1.in +M doc/man/sieve-filter.1.in +M doc/man/sieve-test.1.in +M doc/man/sievec.1.in +M src/lib-managesieve/managesieve-arg.c +M src/lib-managesieve/managesieve-arg.h +M src/lib-managesieve/managesieve-parser.c +M src/lib-managesieve/managesieve-parser.h +M src/lib-managesieve/managesieve-quote.c +M src/lib-managesieve/managesieve-quote.h +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/mail-raw.h +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/cmp-i-ascii-casemap.c +M src/lib-sieve/cmp-i-octet.c +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/copy/sieve-ext-copy.h +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/ext-date-common.h +M src/lib-sieve/plugins/date/ext-date.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.c +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.h +M src/lib-sieve/plugins/duplicate/ext-duplicate.c +M src/lib-sieve/plugins/duplicate/tst-duplicate.c +M src/lib-sieve/plugins/editheader/cmd-addheader.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.h +M src/lib-sieve/plugins/editheader/ext-editheader-limits.h +M src/lib-sieve/plugins/editheader/ext-editheader.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify-limits.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.h +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/environment/ext-environment-common.h +M src/lib-sieve/plugins/environment/ext-environment.c +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/ihave/cmd-error.c +M src/lib-sieve/plugins/ihave/ext-ihave-binary.c +M src/lib-sieve/plugins/ihave/ext-ihave-binary.h +M src/lib-sieve/plugins/ihave/ext-ihave-common.c +M src/lib-sieve/plugins/ihave/ext-ihave-common.h +M src/lib-sieve/plugins/ihave/ext-ihave.c +M src/lib-sieve/plugins/ihave/tst-ihave.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/imap4flags/sieve-ext-imap4flags.h +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-limits.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/index/ext-index-common.c +M src/lib-sieve/plugins/index/ext-index-common.h +M src/lib-sieve/plugins/index/ext-index.c +M src/lib-sieve/plugins/index/tag-index.c +M src/lib-sieve/plugins/mailbox/ext-mailbox-common.h +M src/lib-sieve/plugins/mailbox/ext-mailbox.c +M src/lib-sieve/plugins/mailbox/sieve-ext-mailbox.h +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/metadata/ext-metadata-common.h +M src/lib-sieve/plugins/metadata/ext-metadata.c +M src/lib-sieve/plugins/metadata/tst-metadata.c +M src/lib-sieve/plugins/metadata/tst-metadataexists.c +M src/lib-sieve/plugins/mime/cmd-break.c +M src/lib-sieve/plugins/mime/cmd-extracttext.c +M src/lib-sieve/plugins/mime/cmd-foreverypart.c +M src/lib-sieve/plugins/mime/ext-extracttext.c +M src/lib-sieve/plugins/mime/ext-foreverypart.c +M src/lib-sieve/plugins/mime/ext-mime-common.c +M src/lib-sieve/plugins/mime/ext-mime-common.h +M src/lib-sieve/plugins/mime/ext-mime.c +M src/lib-sieve/plugins/mime/tag-mime.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.h +M src/lib-sieve/plugins/notify/ext-notify-limits.h +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/plugins/regex/ext-regex-common.c +M src/lib-sieve/plugins/regex/ext-regex-common.h +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/lib-sieve/plugins/vacation/ext-vacation-seconds.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.h +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables-dump.h +M src/lib-sieve/plugins/variables/ext-variables-limits.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-name.c +M src/lib-sieve/plugins/variables/ext-variables-name.h +M src/lib-sieve/plugins/variables/ext-variables-namespaces.c +M src/lib-sieve/plugins/variables/ext-variables-namespaces.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug-common.h +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-common.h +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-items.c +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-variables.c +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment.c +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.c +M src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address-source.c +M src/lib-sieve/sieve-address-source.h +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary-code.c +M src/lib-sieve/sieve-binary-debug.c +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-objects.c +M src/lib-sieve/sieve-objects.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-plugins.c +M src/lib-sieve/sieve-plugins.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-runtime-trace.c +M src/lib-sieve/sieve-runtime-trace.h +M src/lib-sieve/sieve-runtime.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve-smtp.c +M src/lib-sieve/sieve-smtp.h +M src/lib-sieve/sieve-storage-private.h +M src/lib-sieve/sieve-storage-sync.c +M src/lib-sieve/sieve-storage.c +M src/lib-sieve/sieve-storage.h +M src/lib-sieve/sieve-stringlist.c +M src/lib-sieve/sieve-stringlist.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/storage/dict/sieve-dict-script.c +M src/lib-sieve/storage/dict/sieve-dict-storage.c +M src/lib-sieve/storage/dict/sieve-dict-storage.h +M src/lib-sieve/storage/file/sieve-file-script-sequence.c +M src/lib-sieve/storage/file/sieve-file-script.c +M src/lib-sieve/storage/file/sieve-file-storage-active.c +M src/lib-sieve/storage/file/sieve-file-storage-list.c +M src/lib-sieve/storage/file/sieve-file-storage-quota.c +M src/lib-sieve/storage/file/sieve-file-storage-save.c +M src/lib-sieve/storage/file/sieve-file-storage.c +M src/lib-sieve/storage/file/sieve-file-storage.h +M src/lib-sieve/storage/ldap/sieve-ldap-db.c +M src/lib-sieve/storage/ldap/sieve-ldap-script.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage-settings.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c +M src/lib-sieve/tst-truefalse.c +M src/lib-sieve/util/edit-mail.c +M src/lib-sieve/util/edit-mail.h +M src/lib-sieve/util/rfc2822.c +M src/lib-sieve/util/rfc2822.h +M src/managesieve-login/client-authenticate.c +M src/managesieve-login/client-authenticate.h +M src/managesieve-login/client.c +M src/managesieve-login/client.h +M src/managesieve-login/managesieve-login-settings-plugin.c +M src/managesieve-login/managesieve-login-settings-plugin.h +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve-login/managesieve-login-settings.h +M src/managesieve-login/managesieve-proxy.c +M src/managesieve-login/managesieve-proxy.h +M src/managesieve/cmd-capability.c +M src/managesieve/cmd-deletescript.c +M src/managesieve/cmd-getscript.c +M src/managesieve/cmd-havespace.c +M src/managesieve/cmd-listscripts.c +M src/managesieve/cmd-logout.c +M src/managesieve/cmd-noop.c +M src/managesieve/cmd-putscript.c +M src/managesieve/cmd-renamescript.c +M src/managesieve/cmd-setactive.c +M src/managesieve/main.c +M src/managesieve/managesieve-capabilities.c +M src/managesieve/managesieve-capabilities.h +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h +M src/managesieve/managesieve-commands.c +M src/managesieve/managesieve-commands.h +M src/managesieve/managesieve-common.h +M src/managesieve/managesieve-quota.c +M src/managesieve/managesieve-quota.h +M src/managesieve/managesieve-settings.c +M src/managesieve/managesieve-settings.h +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-activate.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-delete.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-get.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-list.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-put.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-rename.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd.h +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.h +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c +M src/plugins/imapsieve/ext-imapsieve-common.h +M src/plugins/imapsieve/ext-imapsieve-environment.c +M src/plugins/imapsieve/ext-imapsieve.c +M src/plugins/imapsieve/imap-sieve-plugin.h +M src/plugins/imapsieve/imap-sieve-storage.h +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/imapsieve/imap-sieve.h +M src/plugins/imapsieve/sieve-imapsieve-plugin.c +M src/plugins/imapsieve/sieve-imapsieve-plugin.h +M src/plugins/lda-sieve/lda-sieve-log.c +M src/plugins/lda-sieve/lda-sieve-log.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/plugins/lda-sieve/lda-sieve-plugin.h +M src/plugins/settings/pigeonhole-settings.c +M src/plugins/sieve-extprograms/cmd-execute.c +M src/plugins/sieve-extprograms/cmd-filter.c +M src/plugins/sieve-extprograms/cmd-pipe.c +M src/plugins/sieve-extprograms/ext-execute.c +M src/plugins/sieve-extprograms/ext-filter.c +M src/plugins/sieve-extprograms/ext-pipe.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.h +M src/plugins/sieve-extprograms/sieve-extprograms-plugin.c +M src/plugins/sieve-extprograms/sieve-extprograms-plugin.h +M src/sieve-tools/sieve-dump.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-imap-metadata.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-result.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-arguments.c +M src/testsuite/testsuite-arguments.h +M src/testsuite/testsuite-binary.c +M src/testsuite/testsuite-binary.h +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-log.h +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-result.h +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-script.h +M src/testsuite/testsuite-settings.c +M src/testsuite/testsuite-settings.h +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite-substitutions.c +M src/testsuite/testsuite-substitutions.h +M src/testsuite/testsuite-variables.c +M src/testsuite/testsuite-variables.h +M src/testsuite/testsuite.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-action.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c + +2016-12-24 02:56:01 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (131ea974) + + global: Replaced all instances of memset(p, 0, sizeof(*p)) with the new + i_zero() macro. + + Used the following script: + + C_FILES=`git ls-files *.c` H_FILES=`git ls-files *.h` for F in "$C_FILES + $H_FILES"; do + echo "$F" + perl -p -i -e + 's/safe_memset\(&\(?([^,]*)\)?,\s*0,\s*sizeof\(\g1\)\)/i_zero_safe(&$1)/g' + $F + perl -p -i -e + 's/safe_memset\(([^,]*),\s*0,\s*sizeof\(\*\g1\)\)/i_zero_safe($1)/g' $F + perl -p -i -e + 's/memset\(&\(?([^,]*)\)?,\s*0,\s*sizeof\(\g1\)\)/i_zero(&$1)/g' $F + perl -p -i -e 's/memset\(([^,]*),\s*0,\s*sizeof\(\*\g1\)\)/i_zero($1)/g' $F + done + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/metadata/tst-metadataexists.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-address-source.c +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-plugins.c +M src/lib-sieve/sieve.c +M src/lib-sieve/storage/dict/sieve-dict-storage.c +M src/lib-sieve/storage/ldap/sieve-ldap-db.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/managesieve-login/managesieve-proxy.c +M src/managesieve/main.c +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-commands.c +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c +M src/plugins/imapsieve/imap-sieve-storage.c +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite.c + +2016-11-19 01:14:18 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (13fbc935) + + lib-sieve: sieve-message: Fixed trimming of empty header. + + +M src/lib-sieve/sieve-message.c + +2016-11-19 00:27:59 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (6709993b) + + lib-sieve: matches match type: Improved string pointer manipulation. + + +M src/lib-sieve/mcht-matches.c + +2016-12-26 19:56:47 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (5fe323d1) + + managesieve-login: proxy: Adjusted to changes in Dovecot lib-sasl API. + + +M src/managesieve-login/managesieve-proxy.c + +2016-11-13 15:13:48 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (c90b7fdc) + + managesieve: Fixed indent in client_output(). + + Apparently, this causes GCC warnings. + +M src/managesieve/managesieve-client.c + +2016-11-13 15:11:59 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (d5afd719) + + lib-sieve: file storage: Fixed indent in + sieve_storage_get_relative_link_path(). + + Apparently, this causes GCC warnings. + +M src/lib-sieve/storage/file/sieve-file-storage.c + +2016-11-08 01:45:16 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (c8b91de8) + + imapsieve plugin: Removed spurious debug message. + + +M src/plugins/imapsieve/imap-sieve-storage.c + +2016-11-08 01:03:00 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (00651e60) + + imapsieve plugin: Fixed assert failure occurring when used with virtual + mailboxes. + + In that case a transaction (delayed sync) is perfromed outside of the + context of an IMAP command. + +M src/plugins/imapsieve/imap-sieve-storage.c + +2016-11-07 09:55:28 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (be11698e) + + doc: Forgot to add several files to the distribution. + + +M doc/example-config/Makefile.am +M doc/extensions/Makefile.am +M doc/plugins/Makefile.am +M doc/rfc/Makefile.am + +2016-11-03 20:52:07 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (3deda06e) + + managesieve: Try to initialize var_expand_tab[] directly. + + This avoids accidents with the array numbering being wrong. + +M src/managesieve/managesieve-client.c + +2016-11-03 20:26:49 +0100 Stephan Bosch <stephan.bosch@dovecot.fi> (849790c5) + + lib-sieve: ldap storage: Adjust to var_expand*() API changes. + + +M src/lib-sieve/storage/ldap/sieve-ldap-db.c + +2016-11-01 01:09:42 +0200 Timo Sirainen <timo.sirainen@dovecot.fi> (1e5d2c6a) + + Adjust to var_expand*() API changes. + + +M src/lib-sieve/sieve-error.c +M src/managesieve/main.c +M src/managesieve/managesieve-client.c +M src/plugins/lda-sieve/lda-sieve-log.c + +2016-10-29 14:28:07 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (10e70749) + + lib-sieve: edit-mail: Adjusted to changes in Dovecot lib-storage/index. + + +M src/lib-sieve/util/edit-mail.c + +2016-10-21 18:02:57 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (c5ed66bc) + + testsuite: Cleanup spurious test output. + + +M src/testsuite/Makefile.am + +2016-10-21 15:35:51 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (74ab3713) + + managesieve: Added rawlog_dir setting to store ManageSieve traffic logs. + + This at least partially replaces the "rawlog" post-login binary. For now the + "rawlog" binary supports some parameters, which aren't configurable for + rawlog_dir. + +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-settings.c +M src/managesieve/managesieve-settings.h + +2016-10-21 17:29:17 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (036d5191) + + lib-sieve: vacation extension: Use Microsoft X-Auto-Response-Suppress header + to prevent unwanted responses. + + We've seen a few situations where Pigeonhole and Microsoft products start a + useless machine conversation. At least older versions of Outlook ignore the + standards on multiple points to make this happen. We prevent this now by + recognizing and generating the X-Auto-Response-Suppress header. + +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M tests/extensions/vacation/reply.svtest + +2016-10-21 17:36:44 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (32e7781d) + + lib-sieve: util: Removed Pigeonhole's own version of t_str_trim(), since it + is now available in Dovecot. + + +M src/lib-sieve/sieve-address-source.c +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/util/Makefile.am +D src/lib-sieve/util/strtrim.c +D src/lib-sieve/util/strtrim.h +M src/plugins/imapsieve/imap-sieve-storage.c + +2016-10-21 01:01:16 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (663f8cc5) + + lib-sieve: code dumper: Fixed T_BEGIN { ... } T_END block violation. + + +M src/lib-sieve/sieve-code-dumper.c + +2016-10-20 02:38:07 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (ca0cd69e) + + lib-sieve: vnd.dovecot.report extension: Added Dovecot-Reporting-User field, + which contains the e-mail address of the user sending the report. + + +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M tests/extensions/vnd.dovecot/report/execute.svtest + +2016-10-19 18:38:00 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (4d5a9448) + + Updated dovecot.m4. + + +M m4/dovecot.m4 + +2016-10-19 16:04:49 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (905db120) + + Sieve extprograms plugin: Adjusted to more changes in Dovecot program-client + API. + + +M src/plugins/sieve-extprograms/sieve-extprograms-common.c + +2016-10-17 23:59:58 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (85680b40) + + lib-sieve: result object: Fixed bug in detection of the execution of + delivery action. + + Sequential exections would override a previously flagged delivery, which is + wrong. This caused the sieve_discard feature to trigger for messages that + were actually delivered somewhere by an earlier script in the sequence. + +M src/lib-sieve/sieve-result.c + +2016-10-15 12:24:33 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (bcad6334) + + LDA Sieve plugin: Fixed assert failure caused by earlier sieve_discard + changes. + + The simplest case in which all normal scripts maintain the (implicit) keep + action triggered an assert failure. Fixed by restructuring the script + execution loop to make it easy to understand. Now handles each case + explicitly. + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2016-10-13 15:30:25 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (d18e9b53) + + Sieve exprograms plugin: Adjusted to changes in Dovecot program-client API. + + +M src/plugins/sieve-extprograms/sieve-extprograms-common.c + +2016-10-11 16:40:47 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (a195bd82) + + lib-sieve: vnd.dovecot.report extension: Added support for configuring the + "From:" address used in the report. + + +A doc/extensions/vnd.dovecot.report.txt +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.c +M src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.h +M src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report.c +M tests/extensions/vnd.dovecot/report/execute.svtest + +2016-10-10 19:20:57 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (2a6ff60b) + + Sieve extprograms plugin: Adjusted to program-client API change in Dovecot. + + program_client_remote_create() is now called program_client_unix_create(). + +M src/plugins/sieve-extprograms/sieve-extprograms-common.c + +2016-10-07 12:42:09 +0300 Martti Rannanjärvi <martti.rannanjarvi@dovecot.fi> (a8fb5314) + + lib-sieve: restore realpath.h in Makefile.am + + +M src/lib-sieve/util/Makefile.am + +2016-10-06 12:11:57 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (055537a3) + + doveadm sieve plugin: sync: Fixed saving synchronized Sieve script. + + Assert failure could occur if the input buffer was full. Also, a small + chance existed that not all data would be saved. + +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c + +2016-10-05 22:28:03 +0300 Aki Tuomi <aki.tuomi@dovecot.fi> (22f05f11) + + lib-sieve: program-client was moved to dovecot core + + +M src/lib-sieve/util/Makefile.am +D src/lib-sieve/util/program-client-local.c +D src/lib-sieve/util/program-client-private.h +D src/lib-sieve/util/program-client-remote.c +D src/lib-sieve/util/program-client.c +D src/lib-sieve/util/program-client.h + +2016-09-30 23:57:05 +0200 Stephan Bosch <stephan@dovecot.fi> (2ae18e51) + + LDA Sieve plugin: Implemented support for a "discard script" that is run + when the message is going to be discarded. + + This adds a new "sieve_discard" setting that points to the location of the + "discard script". Once the normal scripts finish executing and the result is + that the message will be discarded without being delivered anywhere, the + "discard script" is executed. The discard script can prevent dropping the + message, by executing alternative actions. If the discard script does + nothing, the message is still discarded. + +M INSTALL +M doc/example-config/conf.d/90-sieve.conf +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2016-09-30 23:55:25 +0200 Stephan Bosch <stephan@dovecot.fi> (bc99d792) + + lib-sieve: Implemented support for running a "discard script" in the + multiscript execution API. + + The "discard script" is run when the normal script sequence ends and the + message is going to be discarded. + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h + +2016-09-30 21:44:33 +0200 Stephan Bosch <stephan@dovecot.fi> (df19597c) + + lib-sieve: Added means to evaluate whether the result object executed a + delivery action. + + +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2016-09-30 19:37:25 +0200 Stephan Bosch <stephan@dovecot.fi> (8f959e8f) + + LDA Sieve plugin: Always use multiscript API for script execution. + + Removed special code path for single script. This is a remnant from times + when the multiscript feature was still experimental. + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2016-09-29 21:23:51 +0200 Stephan Bosch <stephan@dovecot.fi> (67c93ffd) + + lib-sieve: vnd.dovecot.environment extension: Added vnd.dovecot.config.* + environment items. + + A "vnd.dovecot.config.<identifier>" environment item maps to the content of + the matching sieve_env_<identifier> plugin setting. + +M INSTALL +A doc/extensions/vnd.dovecot.environment.txt +M doc/rfc/spec-bosch-sieve-dovecot-environment.txt +M doc/rfc/xml/spec-bosch-sieve-dovecot-environment.xml +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-items.c +M tests/extensions/vnd.dovecot/environment/basic.svtest + +2016-10-04 19:59:03 +0200 Stephan Bosch <stephan.bosch@dovecot.fi> (c9324ac9) + + lib-sieve: environment extension: Improved runtime trace for a nonexistent + environment item. + + +M src/lib-sieve/plugins/environment/tst-environment.c + +2016-09-29 21:21:50 +0200 Stephan Bosch <stephan@dovecot.fi> (2865e415) + + lib-sieve: environment extension: Added support for wildcard environment + items that are identified by a name prefix. + + +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-items.c +M src/plugins/imapsieve/ext-imapsieve-environment.c + +2016-09-29 23:39:42 +0200 Stephan Bosch <stephan@dovecot.fi> (1bca1af3) + + lib-sieve: variables extension: Substitution of an invalid namespace + canceled the substitution, rather than substituting the empty string. + + +M src/lib-sieve/plugins/variables/ext-variables-arguments.c + +2016-09-29 23:37:50 +0200 Stephan Bosch <stephan@dovecot.fi> (da1ed8d9) + + lib-sieve: variables extension: Increased the maximum number of namespace + elements in a variable name. + + +M src/lib-sieve/plugins/variables/ext-variables-limits.h + +2016-09-21 21:41:25 +0200 Stephan Bosch <stephan@dovecot.fi> (47635d88) + + lib-sieve: file storage: Fixed handling of non-blocking input in + save_continue(). + + Bug was exposed by previous change. Normally, this would not surface. + +M src/lib-sieve/storage/file/sieve-file-storage-save.c + +2016-09-21 21:33:58 +0200 Stephan Bosch <stephan@dovecot.fi> (2ce32c4c) + + managesieve: The PUTSCRIPT command now allows uploading empty Sieve scripts. + + There is no reason to forbid an empty Sieve script. + +M src/managesieve/cmd-putscript.c + +2016-09-20 09:35:38 -0400 Josef 'Jeff' Sipek <jeff.sipek@dovecot.fi> (a4348748) + + doveadm-sieve: Update attribute API usage + + +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c + +2016-08-28 23:40:30 +0200 Stephan Bosch <stephan@dovecot.fi> (4a5c2ce4) + + Adjusted client_read_string_args() prototype to handle CLang warning. + + Clang -Wvargargs complained about passing a bool argument to va_start(). + +M src/managesieve/cmd-deletescript.c +M src/managesieve/cmd-getscript.c +M src/managesieve/cmd-putscript.c +M src/managesieve/cmd-renamescript.c +M src/managesieve/cmd-setactive.c +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h + +2016-08-26 01:44:23 +0200 Stephan Bosch <stephan@dovecot.fi> (8a2ef99d) + + lib-sieve: ldap storage: Fixed bool vs. int mixup in function call. + + Found with clang -Wstrict-bool. + +M src/lib-sieve/storage/ldap/sieve-ldap-storage-settings.c + +2016-08-21 12:07:34 +0200 Stephan Bosch <stephan@rename-it.nl> (930ec524) + + lib-sieve: Fixed various bool vs. int/pointer mixups. + + Found with clang -Wstrict-bool. + +M src/lib-sieve/mcht-is.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-storage.c +M src/lib-sieve/sieve-stringlist.c +M src/lib-sieve/sieve.c +M src/lib-sieve/tst-exists.c + +2016-08-21 12:05:55 +0200 Stephan Bosch <stephan@rename-it.nl> (cab5eff7) + + doveadm sieve plugin: Removed unused 'subscriptions' field from command + context. + + Addresses a FIXME. Caused a warning with clang -Wstrict-bool. + +M src/plugins/doveadm-sieve/doveadm-sieve-cmd.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd.h + +2016-08-21 12:05:05 +0200 Stephan Bosch <stephan@rename-it.nl> (0929a400) + + extprograms plugin: Fixed various bool vs. int mixups. + + Found with clang -Wstrict-bool. + +M src/plugins/sieve-extprograms/cmd-execute.c +M src/plugins/sieve-extprograms/cmd-filter.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.c + +2016-08-21 12:02:20 +0200 Stephan Bosch <stephan@rename-it.nl> (ec02e3b5) + + managesieve: Fixed various bool vs. int mixups. + + Found with clang -Wstrict-bool. + +M src/managesieve/managesieve-client.c + +2016-08-21 12:01:29 +0200 Stephan Bosch <stephan@rename-it.nl> (ee3a6554) + + lib-sieve: util: program-client: Fixed a bool vs. int/pointer mixup. + + Found with clang -Wstrict-bool. + +M src/lib-sieve/util/program-client.c + +2016-08-21 11:58:41 +0200 Stephan Bosch <stephan@rename-it.nl> (8e0367b0) + + lib-sieve: file storage: The try_hardlink parameter of file_copy() is of + type bool, rather than int. + + Found with clang -Wstrict-bool. + +M src/lib-sieve/storage/file/sieve-file-storage-active.c + +2016-08-21 11:57:16 +0200 Stephan Bosch <stephan@rename-it.nl> (a010c390) + + lib-sieve: The return type of duplicate_check() is supposed to be bool + rather than int. + + Found with clang -Wstrict-bool. + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-types.h +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-test.c + +2016-08-21 11:52:55 +0200 Stephan Bosch <stephan@rename-it.nl> (b0b9e0a5) + + lib-sieve: script: The return type of binary_dump_metadata() is supposed to + be bool rather than int. + + Found with clang -Wstrict-bool. + +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/storage/dict/sieve-dict-script.c +M src/lib-sieve/storage/ldap/sieve-ldap-script.c + +2016-08-21 11:46:15 +0200 Stephan Bosch <stephan@rename-it.nl> (6a6f7309) + + sieve-filter: Fixed a bool vs. int mixup. + + Found with clang -Wstrict-bool. + +M src/sieve-tools/sieve-filter.c + +2016-08-21 11:44:50 +0200 Stephan Bosch <stephan@rename-it.nl> (86eb7c95) + + testsuite: Fixed various bool vs. int mixups. + + Found with clang -Wstrict-bool. + +M src/testsuite/cmd-test-message.c +M src/testsuite/testsuite-binary.c +M src/testsuite/testsuite-script.c + +2016-08-21 11:37:12 +0200 Stephan Bosch <stephan@rename-it.nl> (ae255494) + + lib-sieve: reject extension: Fixed varius bool vs. int mixups. + + Found with clang -Wstrict-bool. + +M src/lib-sieve/ext-reject.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h + +2016-08-21 11:28:32 +0200 Stephan Bosch <stephan@rename-it.nl> (d8331c81) + + lib-sieve: vacation extension: Fixed invalid evaluation of the + mail_get_headers() return value. + + Found with clang -Wstrict-bool. + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2016-08-21 11:27:37 +0200 Stephan Bosch <stephan@rename-it.nl> (d2fa7208) + + lib-sieve: regex extension: Fixed invalid use of sieve_ast_stringlist_map(). + + Mixed up bool and int return types. Found with clang -Wstrict-bool. + +M src/lib-sieve/plugins/regex/mcht-regex.c + +2016-08-21 11:25:57 +0200 Stephan Bosch <stephan@rename-it.nl> (dabacd9a) + + lib-sieve: deprecated notify extension: Fixed various bool vs. int/pointer + mixups. + + Found with clang -Wstrict-bool. + +M src/lib-sieve/plugins/notify/cmd-notify.c + +2016-08-21 11:24:35 +0200 Stephan Bosch <stephan@rename-it.nl> (f95c6c0c) + + lib-sieve: metadata extension: Fixed invalid use of + sieve_ast_stringlist_map(). + + Mixed up bool and int return types. Found with clang -Wstrict-bool. + +M src/lib-sieve/plugins/metadata/tst-metadataexists.c + +2016-08-21 11:23:03 +0200 Stephan Bosch <stephan@rename-it.nl> (01f7d9f3) + + lib-sieve: mailbox extension: Fixed invalid use of + sieve_ast_stringlist_map(). + + Mixed up bool and int return types. Found with clang -Wstrict-bool. + +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c + +2016-08-21 11:21:39 +0200 Stephan Bosch <stephan@rename-it.nl> (e180373f) + + lib-sieve: index extension: Fixed a bool vs. int mixup. + + Found with clang -Wstrict-bool. + +M src/lib-sieve/plugins/index/tag-index.c + +2016-08-21 11:20:54 +0200 Stephan Bosch <stephan@rename-it.nl> (13485c33) + + lib-sieve: include extension: Fixed various bool vs. int mixups. + + Found with clang -Wstrict-bool. + +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-common.c + +2016-08-21 11:19:30 +0200 Stephan Bosch <stephan@rename-it.nl> (dc60b279) + + lib-sieve: enotify extension: Fixed various bool vs. int/pointer mixups. + + Found with clang -Wstrict-bool. + +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c + +2016-08-21 11:16:27 +0200 Stephan Bosch <stephan@rename-it.nl> (5ef69ddc) + + lib-sieve: match types: Fixed match function return values to be int rather + than bool. + + Found with clang -Wstrict-bool. + +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c + +2016-08-21 11:13:43 +0200 Stephan Bosch <stephan@rename-it.nl> (02d0b7ff) + + lib-sieve: encoded-character extension: Fixed function return types to be + bool rather than int. + + Found with clang -Wstrict-bool. + +M src/lib-sieve/ext-encoded-character.c + +2016-08-21 11:11:45 +0200 Stephan Bosch <stephan@rename-it.nl> (b800fc1c) + + lib-managesieve: managesieve-parser: Fixed function return types to be bool + rather than int. + + Found with clang -Wstrict-bool. + +M src/lib-managesieve/managesieve-parser.c + +2016-08-24 02:47:37 +0200 Stephan Bosch <stephan@dovecot.fi> (af91dd3f) + + doveadm sieve plugin: sync: Fixed handling of unknown attribute timestamps. + + +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c + +2016-08-24 01:22:12 +0200 Stephan Bosch <stephan@dovecot.fi> (ef268fec) + + lib-sieve: util: program-client-remote: Fixed assert failure caused by + previous change. + + Erroneously assumed the number of reserved bytes (for the return code) could + not decrease. + +M src/lib-sieve/util/program-client-remote.c + +2016-08-23 17:07:34 +0300 Aki Tuomi <aki.tuomi@dovecot.fi> (0dcee109) + + tests/deprecated: Fix typo + + +M tests/deprecated/imapflags/errors.svtest +M tests/deprecated/notify/errors.svtest + +2016-08-16 14:29:53 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (d582f0db) + + Adjust to unlink_directory() API changes. + + +M src/testsuite/testsuite-binary.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-smtp.c + +2016-08-20 03:32:58 +0200 Stephan Bosch <stephan@rename-it.nl> (6b02395c) + + global: unsigned int:1 -> bool:1 + + perl -i -pe 's/unsigned int ([^,:;]+):1;/bool $1:1;/' **/*.[ch] + +M src/lib-managesieve/managesieve-parser.c +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.c +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/index/tag-index.c +M src/lib-sieve/plugins/mime/tag-mime.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-smtp.c +M src/lib-sieve/sieve-storage-private.h +M src/lib-sieve/sieve-stringlist.c +M src/lib-sieve/sieve-stringlist.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/storage/dict/sieve-dict-script.c +M src/lib-sieve/storage/file/sieve-file-script-sequence.c +M src/lib-sieve/storage/file/sieve-file-storage-save.c +M src/lib-sieve/storage/ldap/sieve-ldap-script.c +M src/lib-sieve/util/edit-mail.c +M src/lib-sieve/util/program-client-private.h +M src/lib-sieve/util/program-client-remote.c +M src/lib-sieve/util/program-client.h +M src/managesieve-login/client.h +M src/managesieve/cmd-getscript.c +M src/managesieve/managesieve-client.h +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-delete.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-put.c +M src/plugins/imapsieve/imap-sieve-storage.c +M src/plugins/imapsieve/imap-sieve.c +M src/sieve-tools/sieve-filter.c + +2016-08-19 23:05:27 +0200 Stephan Bosch <stephan@dovecot.fi> (0adb7400) + + lib-sieve: util: program-client-remote: Made the program_client_istream + implementation cleaner and more logical. + + It was too hard to understand. + +M src/lib-sieve/util/program-client-remote.c + +2016-08-19 23:02:32 +0200 Stephan Bosch <stephan@dovecot.fi> (351bb053) + + lib-sieve: util: program-client: Fixed position of the seekable stream for + the output of remote programs. + + It would now make the output of the script service seekable, rather than the + output of the program. This adds a '+' at the end of the data. This showed + up for the extprograms filter command. + +M src/lib-sieve/util/program-client.c + +2016-08-19 01:24:21 +0200 Stephan Bosch <stephan@dovecot.fi> (36614104) + + sieve-test: Forgot to disable error handling for dummy SMTP output stream. + + +M src/sieve-tools/sieve-test.c + +2016-08-14 19:13:13 +0300 Martti Rannanjärvi <martti.rannanjarvi@dovecot.fi> (a920da2a) + + lib-sieve: remove set_cache_corrupted_reason from mail_vfuncs + + set_cache_corrupted_reason was removed in core. + +M src/lib-sieve/util/edit-mail.c + +2016-08-13 18:43:04 +0200 Stephan Bosch <stephan@dovecot.fi> (97dcfb2f) + + lib-sieve: relational extension: Replaced return statement with + i_unreached() in mcht_value_match_key(). + + Coverity still complained. + +M src/lib-sieve/plugins/relational/mcht-value.c + +2016-08-13 18:10:08 +0200 Stephan Bosch <stephan@dovecot.fi> (0edfe0c1) + + lib-sieve: ldap storage: Removed useless NULL checks. + + Caused minor complaints by Coverity. + +M src/lib-sieve/storage/ldap/sieve-ldap-db.c + +2016-08-13 17:42:03 +0200 Stephan Bosch <stephan@dovecot.fi> (a6aa9d44) + + lib-sieve: relational extension: Removed dead default in switch statement. + + Minor complaint by Coverity. + +M src/lib-sieve/plugins/relational/mcht-value.c + +2016-08-13 17:26:56 +0200 Stephan Bosch <stephan@dovecot.fi> (53eee4d9) + + imapsieve plugin: Fixed potential segfault bug caused by shadowing a + parameter with a local variable. + + Renamed the local variable. Found by Coverity. + +M src/plugins/imapsieve/imap-sieve-storage.c + +2016-08-13 14:42:31 +0300 Martti Rannanjärvi <martti.rannanjarvi@dovecot.fi> (54eb6fb7) + + lib-sieve: MAIL_FETCH_UIDL_FILE_NAME to MAIL_FETCH_STORAGE_ID: + + MAIL_FETCH_UIDL_FILE_NAME was removed from core. + +M src/lib-sieve/util/edit-mail.c + +2016-08-11 03:17:36 +0200 Stephan Bosch <stephan@dovecot.fi> (886199dd) + + Fixed copyright notices. + + +M src/lib-sieve/plugins/mime/cmd-extracttext.c +M src/lib-sieve/plugins/mime/ext-extracttext.c + +2016-08-10 20:38:05 +0300 Aki Tuomi <aki.tuomi@dovecot.fi> (e246fe9d) + + imapsieve: Update mailbox_attribute API usage + + +M src/plugins/imapsieve/imap-sieve-storage.c + +2016-08-10 20:20:57 +0300 Aki Tuomi <aki.tuomi@dovecot.fi> (0b8386aa) + + doveadm-sieve: Update attribute API + + +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c + +2016-08-10 11:32:04 +0200 Stephan Bosch <stephan@dovecot.fi> (2987a3c2) + + imapsieve plugin: Fixed crash occurring when a mailbox is opened for a user + before the imap client object is created. + + +M src/plugins/imapsieve/imap-sieve-storage.c + +2016-08-10 11:27:40 +0200 Stephan Bosch <stephan@dovecot.fi> (0e8abe2c) + + imapsieve plugin: Removed spurious pool field from imap_sieve_user struct. + + +M src/plugins/imapsieve/imap-sieve-storage.c + +2016-08-02 23:41:11 +0200 Stephan Bosch <stephan@dovecot.fi> (670e029a) + + lib-sieve: program client: Changed I/O to use o_stream_send_istream() where + possible. + + This simplifies the code significantly. This also removes calls to + i_stream_get_data(), which caused problems after its semantics were changed + in Dovecot. + +M src/lib-sieve/util/program-client.c + +2016-08-02 19:39:15 +0200 Stephan Bosch <stephan@dovecot.fi> (18338b4b) + + lib-sieve: lexer: Adjusted to Dovecot change: i_stream_get_data() no longer + returns NULL when returned size = 0. + + +M src/lib-sieve/sieve-lexer.c + +2016-05-20 15:38:31 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (d6cacfef) + + Use i_unlink() to improve unexpected unlink() error messages. + + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve/storage/file/sieve-file-storage-active.c +M src/lib-sieve/storage/file/sieve-file-storage-save.c +M src/lib-sieve/util/program-client.c +M src/sieve-tools/sieve-test.c + +2016-07-15 01:32:01 +0200 Stephan Bosch <stephan@rename-it.nl> (1521447e) + + Removed the test suite's valgrind handling in favor of the generic + implementation Dovecot provides. + + +M .gitignore +M Makefile.am +M configure.ac +M dovecot-pigeonhole.m4 + +2016-07-14 21:50:34 +0200 Stephan Bosch <stephan@rename-it.nl> (814ef928) + + Add flags in DOVECOT_BINARY_CFLAGS and DOVECOT_BINARY_LDFLAGS to all + binaries. + + In effect, this adds PIE and RELRO to binaries. + +M configure.ac +M src/managesieve-login/Makefile.am +M src/managesieve/Makefile.am +M src/sieve-tools/Makefile.am + +2016-07-14 23:09:34 +0200 Stephan Bosch <stephan@rename-it.nl> (1f157d0f) + + lib-managesieve: Use libtool. + + +M src/lib-managesieve/Makefile.am +M src/managesieve-login/Makefile.am +M src/managesieve/Makefile.am + +2016-07-14 21:50:20 +0200 Stephan Bosch <stephan@rename-it.nl> (91368343) + + Updated dovecot.m4. + + +M m4/dovecot.m4 + +2016-07-07 21:52:05 +0200 Stephan Bosch <stephan@rename-it.nl> (66b7c14c) + + extprograms plugin: Clarified the language specification regarding handling + of filter and execute errors. + + +M doc/rfc/spec-bosch-sieve-extprograms.txt +M doc/rfc/xml/spec-bosch-sieve-extprograms.xml + +2016-07-07 18:25:29 +0200 Stephan Bosch <stephan@dovecot.fi> (3fa08e71) + + extprograms plugin: Added tests for invocation of unknown programs. + + +M tests/plugins/extprograms/execute/errors.svtest +A tests/plugins/extprograms/execute/errors/unknown-program.sieve +M tests/plugins/extprograms/filter/errors.svtest +A tests/plugins/extprograms/filter/errors/unknown-program.sieve +M tests/plugins/extprograms/pipe/errors.svtest +A tests/plugins/extprograms/pipe/errors/unknown-program.sieve + +2016-07-07 18:24:16 +0200 Stephan Bosch <stephan@dovecot.fi> (60f4960a) + + extprograms plugin: For directly forked programs, the "program not found" + was reported twice. + + +M src/plugins/sieve-extprograms/sieve-extprograms-common.c + +2016-07-07 18:18:35 +0200 Stephan Bosch <stephan@dovecot.fi> (efef641a) + + extprograms plugin: Execution errors in filter and execute commands did not + lead to script termination. + + +M src/plugins/sieve-extprograms/cmd-execute.c +M src/plugins/sieve-extprograms/cmd-filter.c + +2016-07-07 10:15:15 +0200 Stephan Bosch <stephan@dovecot.fi> (70c27283) + + lib-sieve: program client: Fixed bug in handling of result code from remote + program (script service). + + It was sometimes passed through as data, meaning that the result code was + missed. This transiently resulted in programs seemingly returning invalid + result codes, causing an error. + +M src/lib-sieve/util/program-client-remote.c + +2016-07-07 01:23:27 +0200 Stephan Bosch <stephan@dovecot.fi> (aabde88b) + + lib-sieve: program client: Connection to remote program service was not + retried. + + +M src/lib-sieve/util/program-client-remote.c + +2016-07-06 21:15:19 +0200 Stephan Bosch <stephan@dovecot.fi> (807c61c2) + + lib-sieve: vacation extension: The sieve_user_email setting is now used in + check for implicit delivery. + + This means that vacation responses are now also sent for messages that + include the sieve_user_email address in one of the relevant headers. + +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M tests/extensions/vacation/reply.svtest + +2016-07-06 20:31:35 +0200 Stephan Bosch <stephan@dovecot.fi> (cefa449a) + + testsuite: Removed spurious test_message_print statements. + + +M tests/execute/address-normalize.svtest + +2016-07-06 20:26:50 +0200 Stephan Bosch <stephan@dovecot.fi> (467080db) + + lib-sieve: Fixed handling of quoted string localparts in email addresses. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve.c +M src/testsuite/testsuite-message.c +M tests/extensions/envelope.svtest + +2016-06-28 23:44:12 +0200 Stephan Bosch <stephan@rename-it.nl> (f9eda178) + + lib-sieve: if command: Made static analyzer happier. + + Added assertion to validation function. + +M src/lib-sieve/cmd-if.c + +2016-06-28 23:17:50 +0200 Stephan Bosch <stephan@rename-it.nl> (5673ee51) + + lib-sieve: Make static analyzer happier about argument validation. + + Added assertions. + +M src/lib-sieve/plugins/mime/tag-mime.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/sieve-validator.c + +2016-06-28 22:35:34 +0200 Stephan Bosch <stephan@rename-it.nl> (82592618) + + lib-sieve: Make static analyzer happier about use of + sieve_ast_stringlist_map(). + + Added assertions. + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/tst-address.c + +2016-06-27 21:39:18 +0200 Stephan Bosch <stephan@rename-it.nl> (e2aa3166) + + dovecot-pigeonhole.m4: Make testsuite available when linked against + Pigeonhole source tree, even when it is not yet compiled. + + +M dovecot-pigeonhole.m4 + +2016-06-23 13:30:49 +0200 Stephan Bosch <stephan@dovecot.fi> (9e6e5ee0) + + imapsieve plugin: During transaction run the synchronized version of the + target mailbox was opened too early. + + This meant opening a mailbox a second time even if it did not match any + mailbox rules. + +M src/plugins/imapsieve/imap-sieve-storage.c + +2016-06-21 02:54:36 +0200 Stephan Bosch <stephan@rename-it.nl> (f3944c69) + + lib-sieve: edit-mail: Passed FALSE for normalizer argument of + message_header_decode_utf8() rather than NULL. + + +M src/lib-sieve/util/edit-mail.c + +2016-06-21 02:54:00 +0200 Stephan Bosch <stephan@rename-it.nl> (7860911b) + + lib-sieve: variables extesnion: Fixed instances where FALSE was returned + rather than NULL. + + +M src/lib-sieve/plugins/variables/ext-variables-common.c + +2016-06-21 02:50:29 +0200 Stephan Bosch <stephan@rename-it.nl> (f6b6815a) + + lib-sieve: enotify extension: Fixed instances where FALSE was returned + rather than NULL. + + +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c + +2016-06-20 23:39:09 +0200 Stephan Bosch <stephan@rename-it.nl> (69296a11) + + imapsieve plugin: Restructured imap_sieve_run_scripts() function such that + the compile error code is never used uninitialized. + + +M src/plugins/imapsieve/imap-sieve.c + +2016-06-20 23:08:09 +0200 Stephan Bosch <stephan@rename-it.nl> (561d0adc) + + lib-sieve: address test: Mixed up bool and int for + sieve_ast_stringlist_map() return type. + + +M src/lib-sieve/tst-address.c + +2016-06-20 22:48:06 +0200 Stephan Bosch <stephan@rename-it.nl> (358e40db) + + imapsieve plugin: Prevent possible NULL pointer dereference at transaction + commit. + + +M src/plugins/imapsieve/imap-sieve-storage.c + +2016-06-20 22:40:50 +0200 Stephan Bosch <stephan@rename-it.nl> (44316d49) + + lib-sieve: envelope extension: Mixed up bool and int for + sieve_ast_stringlist_map() return type. + + +M src/lib-sieve/ext-envelope.c + +2016-06-20 22:32:32 +0200 Stephan Bosch <stephan@rename-it.nl> (f3e53764) + + imapsieve plugin: Removed dead assignment reported by scan-build. + + +M src/plugins/imapsieve/imap-sieve.c + +2016-06-20 22:20:32 +0200 Stephan Bosch <stephan@rename-it.nl> (a16a9b8b) + + lib-sieve: variables extension: Changed declaration of new variables to + avoid useless memory allocation. + + Also prevents assert failures with new hash_table_insert() assertion against + existing entries. This changes the API for the variables extension. + +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2016-06-20 21:52:17 +0200 Stephan Bosch <stephan@rename-it.nl> (45d4fa9d) + + lib-sieve: Require blocking message stream for sieve_message_substitute(). + + This prevents trouble with o_stream_nsend_istream() later. + +M src/lib-sieve/sieve-message.c +M src/plugins/sieve-extprograms/cmd-filter.c + +2016-06-20 21:14:11 +0200 Stephan Bosch <stephan@rename-it.nl> (8091baf4) + + lib-sieve: Changed sieve_extension_override() to use hash_table_update() + rather than hash_table_insert(). + + Due to a Dovecot change this would now cause an assertion failure. + +M src/lib-sieve/sieve-extensions.c + +2016-06-20 20:53:47 +0200 Stephan Bosch <stephan@rename-it.nl> (5931b69e) + + managesieve-login: proxy: Did not handle zero return value from + managesieve_parser_read_args() correctly. + + +M src/managesieve-login/managesieve-proxy.c + +2016-06-13 22:06:55 +0200 Stephan Bosch <stephan@dovecot.fi> (167ca91b) + + lib-sieve: Handle duplicate registrations of capabilities better. + + This would uselessly allocate a new entry with the same content. + +M src/lib-sieve/sieve-extensions.c + +2016-06-13 21:59:45 +0200 Stephan Bosch <stephan@dovecot.fi> (9cdc454e) + + lib-sieve: variables extensions: Fixed handling of importing a variable into + a scope that is already imported earlier. + + This allocated a new variable entry every time. + +M src/lib-sieve/plugins/variables/ext-variables-common.c + +2016-06-13 21:41:49 +0200 Stephan Bosch <stephan@dovecot.fi> (74f60b97) + + sieve-tools: Disable automatic data stack frame initialization. + + +M src/lib-sieve-tool/sieve-tool.c + +2016-05-20 15:32:51 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (1ddbb32e) + + Adjusted to changes in o_stream_send_istream() API + + +M src/lib-sieve/storage/file/sieve-file-storage-save.c +M src/managesieve/cmd-getscript.c + +2016-06-09 19:21:53 +0300 Aki Tuomi <aki.tuomi@dovecot.fi> (5e492476) + + pigeonhole: Remove autoclose parameter + + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve.c +M src/lib-sieve/storage/file/sieve-file-storage-save.c +M src/lib-sieve/util/program-client.c +M src/managesieve/managesieve-client.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-result.c + +2016-05-31 02:56:26 +0200 Stephan Bosch <stephan@rename-it.nl> (67dfb5a2) + + Previous change omitted one occurrence of t_malloc(). + + +M src/lib-sieve/storage/ldap/sieve-ldap-db.c + +2016-05-11 10:19:00 +0300 Martti Rannanjärvi <martti.rannanjarvi@dovecot.fi> (3d1226b5) + + Replace t_malloc with t_malloc0 or t_malloc_no0 + + Plain t_malloc was deprecated in dovecot. + +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/util/program-client-local.c +M src/managesieve/managesieve-client.c + +2016-05-16 21:02:09 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (e2d6a03d) + + Use o_stream_nsend*() to make sure write errors are caught. + + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve.c +M src/managesieve-login/managesieve-proxy.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-smtp.c + +2016-05-16 16:08:41 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (69cce444) + + managesieve: Adjust to new o_stream_send_istream() API + + +M src/managesieve/cmd-getscript.c + +2016-05-18 15:23:18 +0200 Stephan Bosch <stephan@dovecot.fi> (b3f5d771) + + Adjusted to changes in Dovecot buffer API. + + +M src/lib-sieve/sieve-binary.c + +2016-05-18 00:31:27 +0200 Stephan Bosch <stephan@rename-it.nl> (634b16b3) + + lib-sieve: ldap storage: Fixed compiler warning occurring under specific + configuration conditions. + + +M src/lib-sieve/storage/ldap/sieve-ldap-db.c + +2016-05-18 00:25:24 +0200 Stephan Bosch <stephan@rename-it.nl> (5f4db18f) + + doveadm-sieve: Fixed copy-paste stupidity in previous change. + + +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-delete.c + +2016-05-18 00:09:28 +0300 Aki Tuomi <aki.tuomi@dovecot.fi> (b47c3a06) + + doveadm-sieve: Update to ver2 structures + + +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-activate.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-delete.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-get.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-list.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-put.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-rename.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd.h + +2016-05-16 22:04:13 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (2c0aa0f0) + + Replaced i_stream_read_data() calls with _read_bytes and _read_more() + + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/util/program-client-remote.c +M src/lib-sieve/util/program-client.c +M src/managesieve-login/client-authenticate.c +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c +M src/testsuite/cmd-test-message.c + +2016-05-15 14:42:49 +0200 Stephan Bosch <stephan@dovecot.fi> (8ab4f24c) + + managesieve: Avoid crashing at deinit if mail_user_unref() triggers + mail_storage_callbacks + + This could have happened with Maildir/mbox and autoexpunging. Mimics + Dovecot/IMAP change ddffbb277e212adb9d594b3d7d1e1d39fa78f7c6. + +M src/managesieve/managesieve-client.c + +2016-05-15 14:38:05 +0200 Stephan Bosch <stephan@dovecot.fi> (cafb21eb) + + managesieve: Free mail_user only after client is disconnected. + + Mimics Dovecot/IMAP change 1001bda65e9f592d852a26ddd6a993f7973050bf. + +M src/managesieve/managesieve-client.c + +2016-03-22 10:13:19 -0400 Aaron Lindsay <aaron@aclindsay.com> (dd0f8d1a) + + subaddress: Support multiple recipient_delimiters + + The recipient_delimiter is treated as multiple one-character delimiters + rather than one multi-character delimiter if more than one character is + supplied. + + Based on a patch by: Lennart Weller <lhw@ring0.de> + +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M tests/extensions/subaddress/config.svtest + +2016-05-09 23:12:43 +0200 Stephan Bosch <stephan@rename-it.nl> (daf1c25c) + + lib-sieve: program client: Significantly improved error handling. + + Stream errors were never logged properly. Streams now have a name that makes + sense. Timeout errors were handled in a rather stupid fashion. + +M src/lib-sieve/util/program-client-local.c +M src/lib-sieve/util/program-client-private.h +M src/lib-sieve/util/program-client-remote.c +M src/lib-sieve/util/program-client.c + +2016-05-09 22:27:45 +0200 Stephan Bosch <stephan@rename-it.nl> (64ac8433) + + lib-sieve: Fixed error handling for mail streams. + + The previous change prompted some futher code review and similar + improvements/fixes were applied at various places in the code. + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +M src/lib-sieve/sieve-message.c + +2016-05-09 16:05:37 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (a66812ae) + + lib-sieve: edit mail wasn't didn't handle truncated header correctly. + + If header was truncated, it was treated as an istream error. Also the + istream read errors weren't logged. + +M src/lib-sieve/util/edit-mail.c + +2016-05-06 17:40:25 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (495393c5) + + Adjusted to changes in Dovecot lib-dict API. + + +M src/lib-sieve/storage/dict/sieve-dict-script.c +M src/lib-sieve/storage/dict/sieve-dict-storage.c + +2016-05-04 02:20:17 +0200 Stephan Bosch <stephan@rename-it.nl> (f7f206d5) + + configure: Changed version number to v0.5.devel. + + +M configure.ac + +2016-05-02 17:09:12 +0300 Timo Sirainen <timo.sirainen@dovecot.fi> (641fa414) + + testsuite: Adjusted to changes in Dovecot lib-storage API. + + +M src/testsuite/testsuite-mailstore.c + +2016-05-02 18:08:59 +0200 Stephan Bosch <stephan@rename-it.nl> (6b436b4f) + + Changed Makefile.am to make sure test suite is executed at `make check'. + + +M Makefile.am + +2016-05-02 17:49:05 +0200 Stephan Bosch <stephan@rename-it.nl> (2dc13c59) + + Merged concurrent changes. + + +2016-04-28 23:02:38 +0200 Stephan Bosch <stephan@dovecot.fi> (b9e567b5) + + lib-sieve: Handle extension overriding itself properly. + + +M src/lib-sieve/sieve-extensions.c + +2016-04-26 22:36:43 +0200 Stephan Bosch <stephan@rename-it.nl> (850d80b2) + + Updated README with availability of vnd.dovecot.report extension. + + +M README + +2016-04-26 21:51:46 +0200 Stephan Bosch <stephan@rename-it.nl> (7c79cdc8) + + Added v0.4.13 to NEWS. + + +M NEWS + +2016-04-26 21:34:15 +0200 Stephan Bosch <stephan@rename-it.nl> (c984322f) + + lib-sieve: edit-mail: Removed useless NULL check in + edit_mail_istream_seek(). + + This caused a Coverity defect report. + +M src/lib-sieve/util/edit-mail.c + +2016-04-26 21:27:08 +0200 Stephan Bosch <stephan@rename-it.nl> (0b04d67d) + + lib-sieve: vnd.dovecot.report extension: Removed logically dead code. + + This caused Coverity defect reports. + +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c + +2016-04-26 21:19:06 +0200 Stephan Bosch <stephan@rename-it.nl> (dfe0d52c) + + lib-sieve: validator: Fixed potential NULL dereference in + sieve_validator_extensions_check_conficts(). + + Would only happen with dummy/internal `extensions' that have no valid ID. + This caused a Coverity defect report. + +M src/lib-sieve/sieve-validator.c + +2016-04-26 21:13:04 +0200 Stephan Bosch <stephan@rename-it.nl> (e25f31a3) + + lib-sieve: validator: Fixed potential NULL dereference in + sieve_validator_extension_load(). + + Would only happen with dummy/internal `extensions' that have no valid ID. + This caused a Coverity defect report. + +M src/lib-sieve/sieve-validator.c + +2016-04-26 21:09:12 +0200 Stephan Bosch <stephan@rename-it.nl> (504a08ae) + + lib-sieve: redirect command: Removed useless NULL check in loop detection. + + This caused a coverity defect report. + +M src/lib-sieve/cmd-redirect.c + +2016-04-19 00:27:09 +0200 Stephan Bosch <stephan@rename-it.nl> (ef25ce69) + + imapsieve plugin: Do not initialize mailbox rules until they are needed. + + Otherwise, these would be re-parsed every time a new mail_user is created + (e.g. when opening a mail as raw). + +M src/plugins/imapsieve/imap-sieve-storage.c + +2016-04-18 22:46:03 +0200 Stephan Bosch <stephan@rename-it.nl> (6af702e3) + + lib-sieve: redirect action: Sender address was not always correctly + assigned. + + This should have provoked a compiler warning. + +M src/lib-sieve/cmd-redirect.c + +2016-04-18 22:40:47 +0200 Stephan Bosch <stephan@rename-it.nl> (c8d1f17a) + + lib-sieve: Messed up indentation in earlier change. + + +M src/lib-sieve/sieve.c + +2016-04-18 21:27:31 +0200 Stephan Bosch <stephan@rename-it.nl> (931adc13) + + lib-sieve: The redirect action still partly depended on having an envelope + available. + + +M src/lib-sieve/cmd-redirect.c + +2016-04-18 19:54:55 +0200 Stephan Bosch <stephan@rename-it.nl> (7949cc28) + + lib-sieve: Implemented utility function that determines the primary email + address of the user. + + +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve.c +M src/plugins/imapsieve/ext-imapsieve-environment.c + +2016-04-14 20:52:04 +0200 Stephan Bosch <stephan@dovecot.fi> (1b6fb01a) + + lib-sieve: Don't add overridden built-in extensions to the capability list. + + These are not available under that name anymore and when the replacing + extension has the same bare name, this would have led to duplicate + capabilities. + +M src/lib-sieve/sieve-extensions.c + +2016-04-14 20:51:04 +0200 Stephan Bosch <stephan@dovecot.fi> (cfb5ee27) + + lib-sieve: When overriding a built-in extension, the wrong extension was + marked as overridden. + + +M src/lib-sieve/sieve-extensions.c + +2016-04-10 03:41:48 +0200 Stephan Bosch <stephan@dovecot.fi> (215349a4) + + lib-sieve: deprecated notify: Removed dependencies on availability of + message envelope. + + +M src/lib-sieve/plugins/notify/cmd-notify.c + +2016-04-09 23:16:06 +0200 Stephan Bosch <stephan@dovecot.fi> (04d86b2f) + + lib-sieve: vnd.dovecot.report extension: Made the report action behave + correctly when there is no envelope. + + +M src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c + +2016-04-09 22:32:00 +0200 Stephan Bosch <stephan@dovecot.fi> (6015613a) + + lib-sieve: enotify: mailto: Sending a notification still partly depended on + having an envelope available. + + +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c + +2016-04-09 22:11:35 +0200 Stephan Bosch <stephan@dovecot.fi> (0bcd59d7) + + lib-sieve: Added a "sieve_user_email" setting that configures the user's + primary email address. + + This is used mainly when no other means of obtaining the user's email is + available, such as when there is no envelope (in IMAP). Before, the + postmaster address or the null "<>" address was used as a fallback for + sending messages. The redirect and enotify commands can be explicitly + configured to use what is configured with sieve_user_email. + +M INSTALL +M doc/example-config/conf.d/90-sieve.conf +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/sieve-address-source.c +M src/lib-sieve/sieve-address-source.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-settings.c +M tests/execute/smtp.svtest +M tests/extensions/enotify/mailto.svtest + +2016-04-09 21:35:05 +0200 Stephan Bosch <stephan@dovecot.fi> (2e67f041) + + lib-sieve: sieve-address-source: Fixed result initialization. + + Used wrong type in sizeof(). + +M src/lib-sieve/sieve-address-source.c + +2016-04-09 20:45:33 +0200 Stephan Bosch <stephan@dovecot.fi> (39713774) + + lib-sieve: Made redirect and enotify/mailto handle the absence of an + envelope properly. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/sieve-address-source.c +M src/lib-sieve/sieve-address-source.h + +2016-04-09 18:48:47 +0200 Stephan Bosch <stephan@dovecot.fi> (a3e2ad32) + + lib-sieve: Moved resolution of sender address source to common location. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/sieve-address-source.c +M src/lib-sieve/sieve-address-source.h +M src/lib-sieve/sieve-common.h + +2016-04-09 18:09:32 +0200 Stephan Bosch <stephan@dovecot.fi> (674376cd) + + lib-sieve: Created sieve_address_source for common handling of address + configuration. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/sieve-actions.c +A src/lib-sieve/sieve-address-source.c +A src/lib-sieve/sieve-address-source.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h + +2016-04-09 16:19:09 +0200 Stephan Bosch <stephan@dovecot.fi> (35f31bfc) + + Updated README file regarding implementation status of IMAPSIEVE. + + +M README + +2016-04-09 16:03:35 +0200 Stephan Bosch <stephan@dovecot.fi> (2e3f99c4) + + lib-sieve: Made sure local part of a mail address is encoded properly using + quoted string when it is not a dot-atom. + + +M Makefile.am +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +A tests/execute/address-normalize.svtest + +2016-04-09 13:53:10 +0200 Stephan Bosch <stephan@dovecot.fi> (dba245c0) + + lib-sieve: Made parsing of explicit address for mail sender setting check + the address syntax. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-settings.c + +2016-04-07 21:31:55 +0200 Stephan Bosch <stephan@rename-it.nl> (7627b9f2) + + Merge pull request #1 from sebix/x-original-to + + lib-sieve: Allow X-Original-To header for the address test. +2016-04-07 16:54:13 +0200 Stephan Bosch <stephan@rename-it.nl> (4e27a127) + + Fix segfault bug caused by earlier trace log changes. + + Trace_log variable was not initialized. + +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2016-04-07 04:31:30 +0200 Stephan Bosch <stephan@rename-it.nl> (cd05a404) + + Documented new trace debugging features. + + +M INSTALL +M doc/example-config/conf.d/90-sieve.conf + +2016-04-07 04:02:26 +0200 Stephan Bosch <stephan@rename-it.nl> (bb4b299e) + + imapsieve plugin: Added trace logging support. + + +M src/plugins/imapsieve/imap-sieve.c + +2016-04-07 04:01:07 +0200 Stephan Bosch <stephan@rename-it.nl> (c934cc42) + + lda-sieve plugin: Added trace logging support. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2016-04-07 03:57:14 +0200 Stephan Bosch <stephan@rename-it.nl> (8b51e7c1) + + lib-sieve: trace logging: Added optional file name label. + + This way, imapsieve can show to which user.mailbox.uid the trace applies. + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h + +2016-04-07 03:55:07 +0200 Stephan Bosch <stephan@rename-it.nl> (6a8f7bdf) + + lib-sieve: Implemented utility functions for configuring runtime trace + logging. + + +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h + +2016-04-06 23:23:42 +0200 Stephan Bosch <stephan@dovecot.fi> (905f66a3) + + lib-sieve: Fixed crashes in extension conflict checking. + + Registering conflicting commands before conflicts are checked is a bad idea. + Make sure conflicting extensions are not part of remaining validation + process. + +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/sieve-validator.c +M tests/deprecated/notify/errors.svtest +M tests/deprecated/notify/errors/conflict-ihave.sieve + +2016-04-06 23:18:23 +0200 Stephan Bosch <stephan@dovecot.fi> (228855fc) + + lib-sieve: Made command and argument error macros accept NULL for commands + and arguments. + + +M src/lib-sieve/sieve-commands.h + +2016-04-06 00:56:07 +0200 Stephan Bosch <stephan@rename-it.nl> (ee860f97) + + lib-sieve: Moved the algorithm for determining the user log file path to + lib-sieve. + + This was duplicated between the lda-sieve and imapsieve plugins. + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/imapsieve/imap-sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2016-04-06 00:28:29 +0200 Stephan Bosch <stephan@rename-it.nl> (f95bab5c) + + lib-sieve: Implemented support for writing runtime trace output to a + directory if it exists, much like Dovecot rawlog. + + +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-runtime-trace.c +M src/lib-sieve/sieve-runtime-trace.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite.c + +2016-04-05 21:35:22 +0200 Stephan Bosch <stephan@rename-it.nl> (684aa242) + + doc/example-config: Added description for a few generic settings that were + only mentioned in the INSTALL file. + + +M doc/example-config/conf.d/90-sieve.conf + +2016-04-05 21:21:12 +0200 Stephan Bosch <stephan@rename-it.nl> (2591cd15) + + doc/man: The -u and -o options were undocumented for the sieve* tools. + + +M doc/man/sieve-dump.1.in +M doc/man/sieve-filter.1.in +M doc/man/sieve-test.1.in +M doc/man/sievec.1.in + +2016-04-05 11:43:36 +0200 Stephan Bosch <stephan@rename-it.nl> (0a191d4b) + + lib-sieve: Make sure that an absent envelope does not cause segfaults. + + Futher changes are needed to prevent accessing the envelope in the first + place. + +M src/lib-sieve/sieve-message.c + +2016-04-05 11:17:31 +0200 Stephan Bosch <stephan@rename-it.nl> (ebc95b51) + + imapsieve plugin: storage: Forgot to free mailbox when there are no Sieve + scripts. + + +M src/plugins/imapsieve/imap-sieve-storage.c + +2016-03-28 19:31:39 +0200 Stephan Bosch <stephan@rename-it.nl> (136c5b18) + + test suite: Added some more ihave-related extension conflict tests. + + +M tests/deprecated/imapflags/errors.svtest +A tests/deprecated/imapflags/errors/conflict-ihave.sieve +R100 tests/deprecated/imapflags/errors/imapflags.sieve tests/deprecated/imapflags/errors/conflict.sieve +M tests/deprecated/notify/errors.svtest +A tests/deprecated/notify/errors/conflict-ihave.sieve +A tests/deprecated/notify/errors/conflict.sieve + +2016-03-27 23:48:44 +0200 Stephan Bosch <stephan@rename-it.nl> (cb2f60e3) + + lib-sieve: Implemented the dovecot-specific "vnd.dovecot.report". + + It allows sending feedback report (RFC 5965) messages. + +M Makefile.am +M configure.ac +A doc/rfc/spec-bosch-sieve-report.txt +A doc/rfc/xml/reference.IMAPSIEVE.xml +A doc/rfc/xml/reference.MARF.xml +A doc/rfc/xml/reference.RFC.2045.xml +A doc/rfc/xml/reference.RFC.3834.xml +A doc/rfc/xml/spec-bosch-sieve-report.xml +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/vnd.dovecot/Makefile.am +A src/lib-sieve/plugins/vnd.dovecot/report/Makefile.am +A src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c +A src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.c +A src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.h +A src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report.c +M src/lib-sieve/sieve-extensions.c +A tests/extensions/vnd.dovecot/report/errors.svtest +A tests/extensions/vnd.dovecot/report/errors/syntax.sieve +A tests/extensions/vnd.dovecot/report/execute.svtest + +2016-03-27 23:47:44 +0200 Stephan Bosch <stephan@rename-it.nl> (b1e2bbd7) + + imapsieve plugins: Fixed compiler warning. + + +M src/plugins/imapsieve/imap-sieve-storage.c + +2016-03-27 23:41:10 +0200 Stephan Bosch <stephan@rename-it.nl> (08c6a402) + + Documented the new IMAPSIEVE plugins. + + +M INSTALL +A doc/plugins/imapsieve.txt +A doc/rfc/imapsieve.rfc6785.txt +M src/plugins/imapsieve/ext-imapsieve.c + +2016-03-27 16:44:20 +0200 Stephan Bosch <stephan@rename-it.nl> (dbe03ae2) + + Implemented the imapsieve extension for Sieve and IMAP as a plugin. + + +M TODO +M configure.ac +M src/plugins/Makefile.am +A src/plugins/imapsieve/Makefile.am +A src/plugins/imapsieve/ext-imapsieve-common.h +A src/plugins/imapsieve/ext-imapsieve-environment.c +A src/plugins/imapsieve/ext-imapsieve.c +A src/plugins/imapsieve/imap-sieve-plugin.c +A src/plugins/imapsieve/imap-sieve-plugin.h +A src/plugins/imapsieve/imap-sieve-storage.c +A src/plugins/imapsieve/imap-sieve-storage.h +A src/plugins/imapsieve/imap-sieve.c +A src/plugins/imapsieve/imap-sieve.h +A src/plugins/imapsieve/sieve-imapsieve-plugin.c +A src/plugins/imapsieve/sieve-imapsieve-plugin.h + +2016-03-27 16:41:20 +0200 Stephan Bosch <stephan@rename-it.nl> (b190d77b) + + lib-sieve: Added support for running the Sieve interpreter without an + envelope. + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-types.h + +2016-03-27 16:40:20 +0200 Stephan Bosch <stephan@rename-it.nl> (4dce44be) + + lib-sieve: Added support for evaluating extension availability (ihave test) + at runtime. + + +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/ihave/cmd-error.c +M src/lib-sieve/plugins/ihave/ext-ihave-common.h +M src/lib-sieve/plugins/ihave/ext-ihave.c +M src/lib-sieve/plugins/ihave/tst-ihave.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-validator.c +M src/testsuite/testsuite-common.c + +2016-03-25 02:48:06 +0100 Stephan Bosch <stephan@rename-it.nl> (222c5af0) + + lib-sieve: Notify extensions about whether they are loaded in the validator + optionally (ihave extension). + + +M src/lib-sieve/plugins/duplicate/ext-duplicate.c +M src/lib-sieve/plugins/ihave/tst-ihave.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/mime/ext-extracttext.c +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/plugins/sieve-extprograms/ext-pipe.c + +2016-03-25 01:47:49 +0100 Stephan Bosch <stephan@rename-it.nl> (ac77b22b) + + lib-sieve: Improved handling of extension conflicts. + + Conflicts are now always tested from both sides. This is mainly important + for the "ihave" test. + +M src/lib-sieve/plugins/duplicate/ext-duplicate.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/mime/ext-extracttext.c +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/plugins/sieve-extprograms/ext-pipe.c + +2016-03-23 02:41:46 +0100 Stephan Bosch <stephan@rename-it.nl> (a95b0579) + + lib-sieve: program client: local: Destroy the output stream before the fd is + closed. + + An earlier change exposed this bug. Before, it was always a socket, and + closing the output early meant using shutdown() rather than close(). This + bug caused an assert failure. + +M src/lib-sieve/util/program-client.c + +2016-03-21 20:57:29 +0100 Sebastian <sebix@sebix.at> (dee854ed) + + Allow X-Original-To for address test + + +M src/lib-sieve/tst-address.c + +2016-03-19 17:05:28 +0100 Stephan Bosch <stephan@rename-it.nl> (75e241fa) + + lib-sieve: Added support for bluntly replacing extensions. + + +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h + +2016-03-19 17:04:28 +0100 Stephan Bosch <stephan@rename-it.nl> (aa5a9a93) + + lib-sieve: Added execution flag that defers handling of keep to the caller. + + +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-types.h + +2016-03-19 17:03:28 +0100 Stephan Bosch <stephan@rename-it.nl> (fb69bc52) + + lib-sieve: Renamed sieve_runtime_flags to sieve_execute_flags and made these + available to result execution. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-runtime.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-script.c + +2016-03-18 02:58:25 +0100 Stephan Bosch <stephan@rename-it.nl> (8d1b0810) + + lib-sieve: util: Fixed message header composition functions to turn newlines + into proper header line continuations. + + +M src/lib-sieve/util/rfc2822.c + +2016-03-09 22:11:21 +0100 Stephan Bosch <stephan@rename-it.nl> (1d36af65) + + Documented the new sieve_implicit_extensions setting. + + +M INSTALL + +2016-03-09 21:35:37 +0100 Stephan Bosch <stephan@rename-it.nl> (355dfd82) + + Added v0.4.12 to NEWS. + + +M NEWS + +2016-03-09 19:23:26 +0100 Stephan Bosch <stephan@rename-it.nl> (c2bca55b) + + lib-sieve: redirect action: Made mail loop detection more robust by forcibly + adding a Message-ID header if it is missing. + + +M src/lib-sieve/cmd-redirect.c + +2016-03-08 17:48:43 +0100 Stephan Bosch <stephan@rename-it.nl> (b188844f) + + Merge branch 'master' of git.dovecot.net:pigeonhole/core + + +2016-03-02 13:01:13 +0100 Stephan Bosch <stephan@rename-it.nl> (0cfa05d0) + + Adjusted to changes in Dovecot lib-storage API/ABI. + + Struct mail_vfuncs has an additional method now. + +M src/lib-sieve/util/edit-mail.c + +2016-02-29 18:05:37 +0100 Stephan Bosch <stephan@rename-it.nl> (75498e45) + + doc/man: doveadm sieve: Clarified that the script name has no ".sieve" + extension. + + +M doc/man/doveadm-sieve.1.in + +2016-02-29 13:26:29 +0100 Stephan Bosch <stephan@dovecot.fi> (5181c14c) + + lib-sieve: validator: Prevent duplicate registration of persistent command + tags. + + +M src/lib-sieve/sieve-validator.c + +2016-02-29 13:08:59 +0100 Stephan Bosch <stephan@dovecot.fi> (61780582) + + lib-sieve: imap4flags: Created API for registering the implicit flags + side-effect with commands. + + This is needed for other extensions that manipulate flags while the + imap4flags extension is not used directly. + +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/imap4flags/sieve-ext-imap4flags.h + +2016-02-29 01:51:04 +0100 Stephan Bosch <stephan@rename-it.nl> (da266d81) + + lib-sieve: redirect action: Added list-id header to the duplicate ID for + mail loop prevention. + + This prevents a conflict between the message coming through a mailing list + and a copy of that message recieved directly. If both of these have the same + message ID, one of these messages would be discarded (or worse: delivered + locally) when redirected. + +M src/lib-sieve/cmd-redirect.c + +2016-02-27 13:28:37 +0100 Stephan Bosch <stephan@rename-it.nl> (93e501fe) + + lib-sieve: Omit logging message for "script not found" during normal script + compile. + + The caller will normally handle this and it will handle it better with more + context information. This also produced a spurious "script not found" error + message when an entry but no attribute existed for an LDAP-based Sieve + script. + +M src/lib-sieve/sieve.c + +2016-02-27 13:28:22 +0100 Stephan Bosch <stephan@rename-it.nl> (2be3992e) + + lib-sieve: ldap storage: Clarified "script not found" errors a bit so that + it is clear at which stage it occurrs. + + +M src/lib-sieve/storage/ldap/sieve-ldap-script.c + +2016-02-22 20:53:46 +0100 Stephan Bosch <stephan@rename-it.nl> (d28957f5) + + lib-sieve: util: program-client-local: Changed link between parent and child + process from a socketpair to a double pipe. + + Turns out /dev/stdin, /dev/stdout, and /dev/fd/XX don't work on Linux if the + underlying FD is a socket. Since some programs may rely on those symbolic + links to work, the local client is amended to use two pipes instead. This + will not help for programs invoked in the remote script service, since a + socket is required for the connection. + +M src/lib-sieve/util/program-client-local.c +A tests/plugins/extprograms/bin/cat-stdin +M tests/plugins/extprograms/execute/execute.svtest + +2016-02-22 20:48:58 +0100 Stephan Bosch <stephan@rename-it.nl> (b83db1dc) + + lib-sieve: util: program-client: Made shutting down output towards program + more efficient. + + Shutdown is now called only once. If there is no used input side to the FD, + it is now closed entirely. + +M src/lib-sieve/util/program-client-local.c +M src/lib-sieve/util/program-client-remote.c + +2016-02-22 20:30:36 +0100 Stephan Bosch <stephan@rename-it.nl> (63080455) + + lib-sieve: util: program-client-local: Made FD handling in child process a + little more robust. + + Prevent mishaps with dup2(); e.g., when source and destination are + identicial, which could happen. + +M src/lib-sieve/util/program-client-local.c + +2016-02-14 23:27:12 +0100 Stephan Bosch <stephan@rename-it.nl> (7ba41a7c) + + Removed some remaining real addresses/domains from the test suite. + + +M src/testsuite/testsuite-message.c +M tests/compile/trivial.sieve +M tests/plugins/extprograms/bin/stderr + +2016-02-13 00:40:48 +0100 Stephan Bosch <stephan@rename-it.nl> (0de2a195) + + lib-sieve: Implemented sieve_implicit_extensions setting. + + The extensions listed in this setting do not need to be enabled explicitly + using the Sieve require command. This behavior voilates the standard, but is + necessary for compatibility with some existing implementations of Sieve. Do + not use this setting unless you really need to! + +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c + +2016-02-12 22:19:46 +0100 Stephan Bosch <stephan@rename-it.nl> (f37f0165) + + lib-sieve: Changed Sieve number type to uint64. + + Fixed a few printf format problems in the process. Updated test suite to + account for the new number width. + +M src/lib-sieve/plugins/duplicate/tst-duplicate.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/tst-size.c +M src/testsuite/cmd-test-message.c +M tests/compile/errors.svtest +M tests/compile/errors/lexer.sieve + +2016-02-12 21:38:09 +0100 Stephan Bosch <stephan@rename-it.nl> (b899aa34) + + lib-sieve: code: Made jump offset code generation a bit more robust against + integer overflow mishaps. + + +M src/lib-sieve/sieve-binary-code.c + +2016-02-12 21:19:52 +0100 Stephan Bosch <stephan@rename-it.nl> (60ad07ad) + + lib-sieve: lexer: Updated number parsing to use Dovecot strnum.h. + + +M src/lib-sieve/sieve-lexer.c + +2016-01-27 01:25:42 +0100 Stephan Bosch <stephan@rename-it.nl> (77e7e81f) + + configure: Changed version number to v0.4.devel. + + The actual version numbers live only on the release-branches from now on. + +M configure.ac + +2016-01-27 01:21:07 +0100 Stephan Bosch <stephan@rename-it.nl> (4fd43c3c) + + configure: Matched first few lines with Dovecot's configure.ac. + + +M configure.ac + +2016-01-26 23:21:50 +0100 Stephan Bosch <stephan@rename-it.nl> (3d48d756) + + Makefile: Added run-test.sh to be cleaned by distclean. + + +M Makefile.am + +2016-01-26 21:48:05 +0100 Stephan Bosch <stephan@rename-it.nl> (311a2090) + + Increased ABI version. + + +M configure.ac + +2016-01-26 21:29:54 +0100 Stephan Bosch <stephan@rename-it.nl> (fd9f5795) + + ChangeLog: Generate Mercurial-style changelogs + + Mimics similar change in Dovecot. + +M Makefile.am +M autogen.sh + +2016-01-19 22:33:02 +0100 Stephan Bosch <stephan@rename-it.nl> (71e908a1) + + managesieve-login: Fixed proxy to allow SASL mechanisms other than PLAIN. + Also made sure that any capability-derived state information is reset + properly before a new capability reply is to be parsed. + + +M src/managesieve-login/client.h +M src/managesieve-login/managesieve-proxy.c + +2016-01-19 22:03:17 +0100 Stephan Bosch <stephan@rename-it.nl> (2bb0c624) + + Fixed recurring language mistake. + + +M NEWS +M doc/extensions/spamtest-virustest.txt +M doc/man/sieve-test.1.in +M src/lib-sieve/plugins/variables/ext-variables-name.h +M src/managesieve-login/managesieve-proxy.c +M tests/compile/errors/if.sieve + +2016-01-17 20:08:32 +0100 Stephan Bosch <stephan@rename-it.nl> (9e93a502) + + Fixed the document name of the vnd.dovecot.environment specification. + + +M doc/rfc/spec-bosch-sieve-dovecot-environment.txt +M doc/rfc/xml/spec-bosch-sieve-dovecot-environment.xml + +2016-01-16 00:09:25 +0100 Stephan Bosch <stephan@rename-it.nl> (3a29a267) + + Merge branch 'master' of git.dovecot.net:pigeonhole/core + + +2016-01-16 00:07:05 +0100 Stephan Bosch <stephan@rename-it.nl> (16362ac8) + + lib-sieve: multiscript: Fixed bug in handling of (implicit) keep; final keep + action was executed as though there was a failure. Among other things, this + caused the keep action to revert back to the initial message, causing + editheader actions to be ignored. + + +M Makefile.am +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve.c +A tests/extensions/editheader/execute.svtest +A tests/extensions/editheader/execute/multiscript-after.sieve +A tests/extensions/editheader/execute/multiscript-before.sieve +A tests/extensions/editheader/execute/multiscript-personal.sieve + +2016-01-14 02:28:46 +0100 Stephan Bosch <stephan@rename-it.nl> (cf873f14) + + LDA Sieve plugin: Removed useless assignment. Addresses LLVM scan-build + report. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2016-01-14 02:16:53 +0100 Stephan Bosch <stephan@rename-it.nl> (62279853) + + lib-sieve: ldap storage: Prevent segfault occurring when assigning global + configuration options. + + +M src/lib-sieve/storage/ldap/sieve-ldap-db.c + +2016-01-14 01:30:20 +0100 Stephan Bosch <stephan@rename-it.nl> (a66a4af8) + + lib-sieve: storage: Local variable in + sieve_storage_active_script_is_default() wasn't always properly initialized. + This was a LLVM scan-build report. + + +M src/lib-sieve/sieve-storage.c + +2016-01-10 02:11:04 +0100 Stephan Bosch <stephan@rename-it.nl> (3f32cd00) + + Updated description of user log in the README file. + + +M README + +2016-01-09 22:54:06 +0100 Stephan Bosch <stephan@rename-it.nl> (3446fef1) + + Forgot to remove is-tagged.py from Makefile.am. + + +M Makefile.am + +2016-01-09 20:58:56 +0100 Stephan Bosch <stephan@rename-it.nl> (45bc3d90) + + lib-sieve: imap4flags extension: Similar problem as previous commit, but + relating to retrieval rather than manipulation. + + +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/sieve-ext-imap4flags.h +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c + +2016-01-09 20:26:06 +0100 Stephan Bosch <stephan@rename-it.nl> (61127ef9) + + lib-sieve: imap4flags extension: Fixed problem in public flag manipulation + API. Flags weren't always assigned properly, because the internal variable + was not retrieved correctly. + + +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/sieve-ext-imap4flags.h + +2016-01-09 16:00:04 +0100 Stephan Bosch <stephan@rename-it.nl> (0a593901) + + Updated TODO. + + +M TODO + +2016-01-09 15:59:03 +0100 Stephan Bosch <stephan@rename-it.nl> (1596c777) + + Updated Sieve extension support information in README. + + +M README + +2016-01-09 15:10:49 +0100 Stephan Bosch <stephan@rename-it.nl> (060c7bd4) + + Updated dovecot.m4 to the latest version. + + +M m4/dovecot.m4 + +2016-01-09 12:54:47 +0100 Stephan Bosch <stephan@rename-it.nl> (2d92fd87) + + Switched from hg to git. + + +A .gitignore +D .hgignore +D .hgsigs +M Makefile.am +D is-tagged.py +M update-version.sh + +2016-01-08 22:27:34 +0100 Stephan Bosch <stephan@rename-it.nl> (f3817d68) + + lib-sieve: imap4flags extension: Forgot to check for empty flag/keyword in + new flag checking function. + + +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c + +2016-01-08 22:05:03 +0100 Stephan Bosch <stephan@rename-it.nl> (a68816ee) + + lib-sieve: imap4flags extension: Made flag syntax checking available to + other extensions. + + +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/sieve-ext-imap4flags.h + +2016-01-08 20:49:39 +0100 Stephan Bosch <stephan@rename-it.nl> (9d7a19d9) + + Implemented Sieve extracttext extension. + + +M Makefile.am +M src/lib-sieve/plugins/mime/Makefile.am +A src/lib-sieve/plugins/mime/cmd-extracttext.c +A src/lib-sieve/plugins/mime/ext-extracttext.c +M src/lib-sieve/plugins/mime/ext-mime-common.h +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/sieve-extensions.c +M tests/extensions/mime/errors.svtest +A tests/extensions/mime/errors/extracttext-nofep.sieve +A tests/extensions/mime/errors/extracttext-novar.sieve +A tests/extensions/mime/errors/extracttext.sieve +A tests/extensions/mime/extracttext.svtest + +2016-01-08 20:49:39 +0100 Stephan Bosch <stephan@rename-it.nl> (b8b6f750) + + lib-sieve: message body: Amended messaage part API with some more access + functions. Added support for getting message part information and content. + + +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h + +2016-01-08 20:49:39 +0100 Stephan Bosch <stephan@rename-it.nl> (b2444c8d) + + lib-sieve: foreverypart extension: Improved byte code generated around break + command. Prevents useless jumps after break operation. + + +M src/lib-sieve/plugins/mime/cmd-break.c + +2016-01-08 20:49:39 +0100 Stephan Bosch <stephan@rename-it.nl> (0caef4ef) + + lib-sieve: Added support for having multiple instances of a single tag + (type) within a single command. + + +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-validator.c + +2016-01-08 20:49:39 +0100 Stephan Bosch <stephan@rename-it.nl> (823d2903) + + lib-sieve: Cleaned up object definitions using newer C99 syntax. + + +M src/lib-sieve/cmp-i-ascii-casemap.c +M src/lib-sieve/cmp-i-octet.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-variables.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-objects.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-substitutions.c + +2016-01-08 20:49:39 +0100 Stephan Bosch <stephan@rename-it.nl> (877f8247) + + lib-sieve: Cleaned up byte code operand and operation definitions using + newer C99 syntax. + + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/duplicate/tst-duplicate.c +M src/lib-sieve/plugins/editheader/cmd-addheader.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/ihave/cmd-error.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/index/tag-index.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/metadata/tst-metadata.c +M src/lib-sieve/plugins/metadata/tst-metadataexists.c +M src/lib-sieve/plugins/mime/cmd-break.c +M src/lib-sieve/plugins/mime/cmd-foreverypart.c +M src/lib-sieve/plugins/mime/tag-mime.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/regex/ext-regex-common.c +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-namespaces.c +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-variables.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c +M src/plugins/sieve-extprograms/cmd-execute.c +M src/plugins/sieve-extprograms/cmd-filter.c +M src/plugins/sieve-extprograms/cmd-pipe.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-imap-metadata.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-result.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-substitutions.c +M src/testsuite/testsuite-variables.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-action.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c + +2016-01-08 20:49:39 +0100 Stephan Bosch <stephan@rename-it.nl> (3d33283d) + + lib-sieve: Cleaned up command definitions using newer C99 syntax. + + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/duplicate/tst-duplicate.c +M src/lib-sieve/plugins/editheader/cmd-addheader.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/ihave/cmd-error.c +M src/lib-sieve/plugins/ihave/tst-ihave.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/metadata/tst-metadata.c +M src/lib-sieve/plugins/metadata/tst-metadataexists.c +M src/lib-sieve/plugins/mime/cmd-break.c +M src/lib-sieve/plugins/mime/cmd-foreverypart.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c +M src/lib-sieve/tst-truefalse.c +M src/plugins/sieve-extprograms/cmd-execute.c +M src/plugins/sieve-extprograms/cmd-filter.c +M src/plugins/sieve-extprograms/cmd-pipe.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-imap-metadata.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-result.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-action.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c + +2016-01-08 20:49:39 +0100 Stephan Bosch <stephan@rename-it.nl> (2677f978) + + lib-sieve: Cleaned up command argument definitions using newer C99 syntax. + + +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/duplicate/tst-duplicate.c +M src/lib-sieve/plugins/editheader/cmd-addheader.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/index/tag-index.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mime/cmd-break.c +M src/lib-sieve/plugins/mime/cmd-foreverypart.c +M src/lib-sieve/plugins/mime/tag-mime.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-namespaces.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/tst-size.c +M src/plugins/sieve-extprograms/cmd-execute.c +M src/plugins/sieve-extprograms/cmd-pipe.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-imap-metadata.c +M src/testsuite/cmd-test-message.c +M src/testsuite/testsuite-arguments.c +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-substitutions.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-result-action.c +M src/testsuite/tst-test-script-run.c + +2016-01-08 20:07:51 +0100 Stephan Bosch <stephan@rename-it.nl> (45f46f03) + + Added signature for changeset 80146e7670e9 + + +M .hgsigs + +2016-01-08 19:15:44 +0100 Stephan Bosch <stephan@rename-it.nl> (7da5ae6e) + + Added tag 0.4.11 for changeset 80146e7670e9 + + +2016-01-08 19:15:33 +0100 Stephan Bosch <stephan@rename-it.nl> (9d7b1725) + + Released v0.4.11 for Dovecot v2.2.21. + + +M NEWS +M configure.ac + +2016-01-07 22:20:21 +0100 Stephan Bosch <stephan@rename-it.nl> (dd66c5f3) + + lib-sieve: util: realpath: Make Coverity happier. + + +M src/lib-sieve/util/realpath.c + +2016-01-07 22:09:50 +0100 Stephan Bosch <stephan@rename-it.nl> (d576f532) + + lib-sieve: util: Fixed source code indentation in realpath.c. + + +M src/lib-sieve/util/realpath.c + +2016-01-04 01:19:02 +0100 Stephan Bosch <stephan@rename-it.nl> (c405da95) + + Added signature for changeset ce96bdac1f74 + + +M .hgsigs + +2016-01-04 01:14:24 +0100 Stephan Bosch <stephan@rename-it.nl> (3ef7f9d7) + + Added tag 0.4.11.rc1 for changeset ce96bdac1f74 + + +2016-01-04 01:14:15 +0100 Stephan Bosch <stephan@rename-it.nl> (439ad92d) + + Released v0.4.11.rc1 for Dovecot v2.2.21. + + +M NEWS +M configure.ac + +2016-01-04 00:19:02 +0100 Stephan Bosch <stephan@rename-it.nl> (51b2276f) + + Updated copyright notices to include the year 2016. + + +M doc/man/doveadm-sieve.1.in +M doc/man/pigeonhole.7.in +M doc/man/sieve-dump.1.in +M doc/man/sieve-filter.1.in +M doc/man/sieve-test.1.in +M doc/man/sievec.1.in +M src/lib-managesieve/managesieve-arg.c +M src/lib-managesieve/managesieve-arg.h +M src/lib-managesieve/managesieve-parser.c +M src/lib-managesieve/managesieve-parser.h +M src/lib-managesieve/managesieve-quote.c +M src/lib-managesieve/managesieve-quote.h +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/mail-raw.h +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/cmp-i-ascii-casemap.c +M src/lib-sieve/cmp-i-octet.c +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/copy/sieve-ext-copy.h +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/ext-date-common.h +M src/lib-sieve/plugins/date/ext-date.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.c +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.h +M src/lib-sieve/plugins/duplicate/ext-duplicate.c +M src/lib-sieve/plugins/duplicate/tst-duplicate.c +M src/lib-sieve/plugins/editheader/cmd-addheader.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.h +M src/lib-sieve/plugins/editheader/ext-editheader-limits.h +M src/lib-sieve/plugins/editheader/ext-editheader.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify-limits.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.h +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/environment/ext-environment-common.h +M src/lib-sieve/plugins/environment/ext-environment.c +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/ihave/cmd-error.c +M src/lib-sieve/plugins/ihave/ext-ihave-binary.c +M src/lib-sieve/plugins/ihave/ext-ihave-binary.h +M src/lib-sieve/plugins/ihave/ext-ihave-common.c +M src/lib-sieve/plugins/ihave/ext-ihave-common.h +M src/lib-sieve/plugins/ihave/ext-ihave.c +M src/lib-sieve/plugins/ihave/tst-ihave.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/imap4flags/sieve-ext-imap4flags.h +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-limits.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/index/ext-index-common.c +M src/lib-sieve/plugins/index/ext-index-common.h +M src/lib-sieve/plugins/index/ext-index.c +M src/lib-sieve/plugins/index/tag-index.c +M src/lib-sieve/plugins/mailbox/ext-mailbox-common.h +M src/lib-sieve/plugins/mailbox/ext-mailbox.c +M src/lib-sieve/plugins/mailbox/sieve-ext-mailbox.h +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/metadata/ext-metadata-common.h +M src/lib-sieve/plugins/metadata/ext-metadata.c +M src/lib-sieve/plugins/metadata/tst-metadata.c +M src/lib-sieve/plugins/metadata/tst-metadataexists.c +M src/lib-sieve/plugins/mime/cmd-break.c +M src/lib-sieve/plugins/mime/cmd-foreverypart.c +M src/lib-sieve/plugins/mime/ext-foreverypart.c +M src/lib-sieve/plugins/mime/ext-mime-common.c +M src/lib-sieve/plugins/mime/ext-mime-common.h +M src/lib-sieve/plugins/mime/ext-mime.c +M src/lib-sieve/plugins/mime/tag-mime.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.h +M src/lib-sieve/plugins/notify/ext-notify-limits.h +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/plugins/regex/ext-regex-common.c +M src/lib-sieve/plugins/regex/ext-regex-common.h +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/lib-sieve/plugins/vacation/ext-vacation-seconds.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.h +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables-dump.h +M src/lib-sieve/plugins/variables/ext-variables-limits.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-name.c +M src/lib-sieve/plugins/variables/ext-variables-name.h +M src/lib-sieve/plugins/variables/ext-variables-namespaces.c +M src/lib-sieve/plugins/variables/ext-variables-namespaces.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug-common.h +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-common.h +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-items.c +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-variables.c +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary-code.c +M src/lib-sieve/sieve-binary-debug.c +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-objects.c +M src/lib-sieve/sieve-objects.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-plugins.c +M src/lib-sieve/sieve-plugins.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-runtime-trace.c +M src/lib-sieve/sieve-runtime-trace.h +M src/lib-sieve/sieve-runtime.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve-smtp.c +M src/lib-sieve/sieve-smtp.h +M src/lib-sieve/sieve-storage-private.h +M src/lib-sieve/sieve-storage-sync.c +M src/lib-sieve/sieve-storage.c +M src/lib-sieve/sieve-storage.h +M src/lib-sieve/sieve-stringlist.c +M src/lib-sieve/sieve-stringlist.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/storage/dict/sieve-dict-script.c +M src/lib-sieve/storage/dict/sieve-dict-storage.c +M src/lib-sieve/storage/dict/sieve-dict-storage.h +M src/lib-sieve/storage/file/sieve-file-script-sequence.c +M src/lib-sieve/storage/file/sieve-file-script.c +M src/lib-sieve/storage/file/sieve-file-storage-active.c +M src/lib-sieve/storage/file/sieve-file-storage-list.c +M src/lib-sieve/storage/file/sieve-file-storage-quota.c +M src/lib-sieve/storage/file/sieve-file-storage-save.c +M src/lib-sieve/storage/file/sieve-file-storage.c +M src/lib-sieve/storage/file/sieve-file-storage.h +M src/lib-sieve/storage/ldap/sieve-ldap-db.c +M src/lib-sieve/storage/ldap/sieve-ldap-script.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage-settings.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c +M src/lib-sieve/tst-truefalse.c +M src/lib-sieve/util/edit-mail.c +M src/lib-sieve/util/edit-mail.h +M src/lib-sieve/util/program-client-local.c +M src/lib-sieve/util/program-client-private.h +M src/lib-sieve/util/program-client-remote.c +M src/lib-sieve/util/program-client.c +M src/lib-sieve/util/program-client.h +M src/lib-sieve/util/realpath.c +M src/lib-sieve/util/rfc2822.c +M src/lib-sieve/util/rfc2822.h +M src/lib-sieve/util/strtrim.c +M src/managesieve-login/client-authenticate.c +M src/managesieve-login/client-authenticate.h +M src/managesieve-login/client.c +M src/managesieve-login/client.h +M src/managesieve-login/managesieve-login-settings-plugin.c +M src/managesieve-login/managesieve-login-settings-plugin.h +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve-login/managesieve-login-settings.h +M src/managesieve-login/managesieve-proxy.c +M src/managesieve-login/managesieve-proxy.h +M src/managesieve/cmd-capability.c +M src/managesieve/cmd-deletescript.c +M src/managesieve/cmd-getscript.c +M src/managesieve/cmd-havespace.c +M src/managesieve/cmd-listscripts.c +M src/managesieve/cmd-logout.c +M src/managesieve/cmd-noop.c +M src/managesieve/cmd-putscript.c +M src/managesieve/cmd-renamescript.c +M src/managesieve/cmd-setactive.c +M src/managesieve/main.c +M src/managesieve/managesieve-capabilities.c +M src/managesieve/managesieve-capabilities.h +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h +M src/managesieve/managesieve-commands.c +M src/managesieve/managesieve-commands.h +M src/managesieve/managesieve-common.h +M src/managesieve/managesieve-quota.c +M src/managesieve/managesieve-quota.h +M src/managesieve/managesieve-settings.c +M src/managesieve/managesieve-settings.h +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-activate.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-delete.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-get.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-list.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-put.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-rename.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd.h +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.h +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c +M src/plugins/lda-sieve/lda-sieve-log.c +M src/plugins/lda-sieve/lda-sieve-log.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/plugins/lda-sieve/lda-sieve-plugin.h +M src/plugins/settings/pigeonhole-settings.c +M src/plugins/sieve-extprograms/cmd-execute.c +M src/plugins/sieve-extprograms/cmd-filter.c +M src/plugins/sieve-extprograms/cmd-pipe.c +M src/plugins/sieve-extprograms/ext-execute.c +M src/plugins/sieve-extprograms/ext-filter.c +M src/plugins/sieve-extprograms/ext-pipe.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.h +M src/plugins/sieve-extprograms/sieve-extprograms-plugin.c +M src/plugins/sieve-extprograms/sieve-extprograms-plugin.h +M src/sieve-tools/sieve-dump.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-imap-metadata.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-result.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-arguments.c +M src/testsuite/testsuite-arguments.h +M src/testsuite/testsuite-binary.c +M src/testsuite/testsuite-binary.h +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-log.h +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-result.h +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-script.h +M src/testsuite/testsuite-settings.c +M src/testsuite/testsuite-settings.h +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite-substitutions.c +M src/testsuite/testsuite-substitutions.h +M src/testsuite/testsuite-variables.c +M src/testsuite/testsuite-variables.h +M src/testsuite/testsuite.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-action.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c + +2016-01-03 22:06:50 +0100 Stephan Bosch <stephan@rename-it.nl> (645bd122) + + test suite: mime extension: Added more test for exists and address tests + with :mime tag. + + +M Makefile.am +A tests/extensions/mime/address.svtest +A tests/extensions/mime/exists.svtest + +2016-01-03 19:39:32 +0100 Stephan Bosch <stephan@rename-it.nl> (c9a2056a) + + lib-sieve: mime extensions: Updated status from development to experimental. + + +M src/lib-sieve/plugins/mime/ext-foreverypart.c +M src/lib-sieve/plugins/mime/ext-mime.c + +2016-01-03 18:37:39 +0100 Stephan Bosch <stephan@rename-it.nl> (edb268d9) + + lib-sieve: message body: Fixed parsing of content-disposition header. + + +M src/lib-sieve/sieve-message.c + +2016-01-03 18:20:51 +0100 Stephan Bosch <stephan@rename-it.nl> (e46b5a2d) + + lib-sieve: Fixed segfault occurring when default match type of a test is not + :is. Would not occur in Pigeonhole itself. + + +M src/lib-sieve/sieve-match-types.c + +2016-01-03 16:33:39 +0100 Stephan Bosch <stephan@rename-it.nl> (017989a3) + + lib-sieve: mime extension: Fixed the header :mime :anychild test to work + properly outside a foreverypart loop. + + +M src/lib-sieve/plugins/mime/tag-mime.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M tests/extensions/mime/foreverypart.svtest +M tests/extensions/mime/header.svtest + +2016-01-03 16:32:27 +0100 Stephan Bosch <stephan@rename-it.nl> (6a117056) + + lib-sieve: message body: Fixed erroneous changes to the message part tree + structure performed when re-parsing the message. + + +M src/lib-sieve/sieve-message.c + +2016-01-03 16:29:30 +0100 Stephan Bosch <stephan@rename-it.nl> (414251d6) + + lib-sieve: Fixed duplication of discard actions in result. No duplicate + check function was implemented, so that the discard action would be + duplicated each time it is invoked. This only affects the action limits + (each discard invocation is counted as another new action). The result of + the script execution would be identical. + + +M src/lib-sieve/cmd-discard.c + +2016-01-02 19:36:01 +0100 Stephan Bosch <stephan@rename-it.nl> (eed8e51d) + + test suite: mime extension: Improved header test cases to catch header + trimming and folding problems. + + +M tests/extensions/mime/header.svtest + +2016-01-02 19:35:24 +0100 Stephan Bosch <stephan@rename-it.nl> (aecb32fe) + + lib-sieve: message body: Forgot to trim header values. + + +M src/lib-sieve/sieve-message.c + +2016-01-02 19:34:58 +0100 Stephan Bosch <stephan@rename-it.nl> (75f9c5a0) + + lib-sieve: Fixed an off-by-one error in the previously committed string + trimming functions. + + +M src/lib-sieve/util/strtrim.c + +2016-01-02 18:27:14 +0100 Stephan Bosch <stephan@rename-it.nl> (c0679f08) + + lib-sieve: Added our own string trimming functions for until equivalents get + added in Dovecot. + + +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/util/Makefile.am +A src/lib-sieve/util/strtrim.c +A src/lib-sieve/util/strtrim.h + +2016-01-02 17:13:00 +0100 Stephan Bosch <stephan@rename-it.nl> (fb29773f) + + lib-sieve: Forgot to enable header unfolding for (mime) headers parsed from + the whole message. + + +M src/lib-sieve/sieve-message.c + +2016-01-02 16:14:27 +0100 Stephan Bosch <stephan@rename-it.nl> (93024df1) + + test suite: Repeated normal header tests for the mime extension. + + +M Makefile.am +A tests/extensions/mime/header.svtest + +2015-12-30 21:38:16 +0100 Stephan Bosch <stephan@rename-it.nl> (57a7d70e) + + lib-sieve: message body: Fixed assert failure occurring when text extraction + is attempted on a empty or broken text part. + + +M src/lib-sieve/sieve-message.c +M tests/extensions/body/text.svtest + +2015-12-30 21:36:29 +0100 Stephan Bosch <stephan@rename-it.nl> (62c8bcaf) + + lib-sieve: message body: Erroneously omitted break statement in switch + block. + + +M src/lib-sieve/sieve-message.c + +2015-12-30 21:34:33 +0100 Stephan Bosch <stephan@rename-it.nl> (766ae2a2) + + lib-sieve: message body: Explicitly prevent attempting text extraction from + header and multipart body parts. + + +M src/lib-sieve/sieve-message.c + +2015-12-30 17:21:35 +0100 Stephan Bosch <stephan@rename-it.nl> (3debc34c) + + lib-sieve: util: program-client: Ignored ENOTCONN error in shutdown(fd, + SHUT_WR) call. This error can apparently occur if the program terminates + earlier than the program client issues shutdown(). + + +M src/lib-sieve/util/program-client-local.c +M src/lib-sieve/util/program-client-remote.c + +2015-12-29 20:20:29 +0100 Stephan Bosch <stephan@rename-it.nl> (65c4ec04) + + lib-sieve: message body: Fixed assert failure in handling of body parts that + are converted to text. No final '\0' character was added to those body + parts. This occurs for the body test with the (default) `:text' body + transform. + + +M src/lib-sieve/sieve-message.c + +2015-12-28 20:46:14 +0100 Stephan Bosch <stephan@rename-it.nl> (75c53950) + + lib-sieve: message body: Prevent cached raw body from growing by one '\0' + each time it is accessed. + + +M src/lib-sieve/sieve-message.c + +2015-12-28 20:33:01 +0100 Stephan Bosch <stephan@rename-it.nl> (71be8cc6) + + lib-sieve: code: Added assert to prevent emitting invalid byte code when + extension definitions are wrong. + + +M src/lib-sieve/sieve-code.c + +2015-12-25 20:50:50 +0100 Stephan Bosch <stephan@rename-it.nl> (1a8c0016) + + Added ./compile to .hgignore. + + +M .hgignore + +2015-12-22 21:30:12 +0100 Stephan Bosch <stephan@rename-it.nl> (587d90d8) + + lib-sieve: Made sure that quota errors never get logged as errors in syslog. + Also improved handling of permission errors caused by ACL plugin. + + +M src/lib-sieve/sieve-actions.c + +2015-12-22 21:29:14 +0100 Stephan Bosch <stephan@rename-it.nl> (be199519) + + lib-sieve: Fixed handling of global errors. If master and user error handler + were identical, in some cases the log message could be lost. + + +M src/lib-sieve/sieve-error.c + +2015-12-22 21:28:17 +0100 Stephan Bosch <stephan@rename-it.nl> (5357208d) + + lib-sieve: result: Fixed handling of implicit keep for a partially executed + transaction that yield a temporary failure. It would probably result in + message duplication. + + +M src/lib-sieve/sieve-result.c + +2015-12-21 23:51:55 +0100 Stephan Bosch <stephan@rename-it.nl> (8411f0fa) + + LDA Sieve plugin: Made sure there is always a proper error handler for the + implicit keep action during multiscript execution. Should fix reported bug + on missing message-ID in log. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2015-12-21 23:32:49 +0100 Stephan Bosch <stephan@rename-it.nl> (3e2e5545) + + LDA Sieve plugin: Removed stray error handler dereference. This would + probably cause a segfault at multiscript errors. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2015-12-14 18:56:25 +0100 Stephan Bosch <stephan@rename-it.nl> (6c9580e8) + + lib-sieve: Fixed AIX compile issue in message body parser. Should not + dereference array_idx() result on the spot. + + +M src/lib-sieve/sieve-message.c + +2015-12-14 18:54:33 +0100 Stephan Bosch <stephan@rename-it.nl> (d9d8fdb6) + + LDA Sieve plugin: Fixed bug in error handling of Sieve storage constructor. + Error code was not passed back to caller, so that it operates on an + uninitialized value. Bug found by CLang warning. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2015-12-14 01:10:44 +0100 Stephan Bosch <stephan@rename-it.nl> (3c4c2bb8) + + Added signature for changeset 7e19bcfc0c16 + + +M .hgsigs + +2015-12-14 01:01:56 +0100 Stephan Bosch <stephan@rename-it.nl> (1adf0132) + + Added tag 0.4.10 for changeset 7e19bcfc0c16 + + +2015-12-14 01:01:38 +0100 Stephan Bosch <stephan@rename-it.nl> (fa008c0f) + + Released v0.4.10 for Dovecot v2.2.21. + + +M NEWS +M configure.ac + +2015-12-08 20:33:19 +0100 Stephan Bosch <stephan@rename-it.nl> (4177ae29) + + Renamed pigeonhole.m4 to dovecot-pigeonhole.m4. + + +M Makefile.am +R100 pigeonhole.m4 dovecot-pigeonhole.m4 + +2015-12-08 00:37:34 +0100 Stephan Bosch <stephan@rename-it.nl> (c1fe7b28) + + Added signature for changeset 9b7f6f14a350 + + +M .hgsigs + +2015-12-08 00:32:20 +0100 Stephan Bosch <stephan@rename-it.nl> (1daceb9b) + + Added tag 0.4.10.rc2 for changeset 9b7f6f14a350 + + +2015-12-08 00:32:10 +0100 Stephan Bosch <stephan@rename-it.nl> (543848bd) + + Released v0.4.10.rc2 for Dovecot v2.2.20. + + +M configure.ac + +2015-12-08 00:31:05 +0100 Stephan Bosch <stephan@rename-it.nl> (d6e95607) + + Fixed indentation in README file. + + +M README + +2015-12-05 01:15:11 +0100 Stephan Bosch <stephan@rename-it.nl> (2f56a91f) + + lib-sieve: Added back t_str_trim() for the time being, since it was removed + from Dovecot. It is now named pg_t_str_trim() to prevent a new conflict at + the next attempt. + + +M src/lib-sieve/sieve-settings.c + +2015-12-05 00:49:33 +0100 Stephan Bosch <stephan@rename-it.nl> (a8bec513) + + Added signature for changeset a795304eb433 + + +M .hgsigs + +2015-12-05 00:44:09 +0100 Stephan Bosch <stephan@rename-it.nl> (c6766eb4) + + Added tag 0.4.10.rc1 for changeset a795304eb433 + + +2015-12-05 00:43:45 +0100 Stephan Bosch <stephan@rename-it.nl> (c3af27f4) + + Released v0.4.10.rc1 for Dovecot v2.2.20.rc1. + + +M NEWS +M configure.ac + +2015-12-04 23:21:58 +0100 Stephan Bosch <stephan@rename-it.nl> (ae3ef56d) + + Updated TODO. + + +M TODO + +2015-12-04 23:20:05 +0100 Stephan Bosch <stephan@rename-it.nl> (42582832) + + lib-sieve: mime/foreverypart: Properly implemented interaction with include + extension. Included scripts now execute in the context of the inner parent + foreverypart loop. + + +M src/lib-sieve/plugins/mime/ext-mime-common.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M tests/extensions/mime/errors.svtest +M tests/extensions/mime/foreverypart.svtest +A tests/extensions/mime/included/include-foreverypart.sieve + +2015-12-04 22:58:35 +0100 Stephan Bosch <stephan@rename-it.nl> (c8643b66) + + lib-sieve: mime: Improved foreverypart runtime trace. + + +M src/lib-sieve/plugins/mime/cmd-foreverypart.c + +2015-12-01 14:24:33 +0100 Stephan Bosch <stephan@rename-it.nl> (714988c4) + + Forced distribution of pigeonhole.m4 file. For some inapparent reason it was + not included in the output tarball. + + +M Makefile.am + +2015-11-29 21:47:14 +0100 Stephan Bosch <stephan@rename-it.nl> (fec57037) + + lib-sieve: variables extension: Fixed handling of empty string by the + `:length' set modifier. An empty string yielded an empty string rather than + "0". + + +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M tests/extensions/variables/modifiers.svtest + +2015-11-29 21:33:33 +0100 Stephan Bosch <stephan@rename-it.nl> (c751d077) + + lib-sieve: Fixed memory leak in code dumper. The free handler of code dumper + extensions was never executed. + + +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h + +2015-11-29 20:01:09 +0100 Stephan Bosch <stephan@rename-it.nl> (55154015) + + testsuite: mime extension: Added iCalendar example test case. + + +M Makefile.am +A tests/extensions/mime/calendar-example.svtest + +2015-11-29 20:00:37 +0100 Stephan Bosch <stephan@rename-it.nl> (9bdc93c9) + + lib-sieve: mime extension: Improved trace output. + + +M src/lib-sieve/plugins/mime/cmd-foreverypart.c +M src/lib-sieve/plugins/mime/tag-mime.c +M src/lib-sieve/sieve-message.c + +2015-11-29 18:33:40 +0100 Stephan Bosch <stephan@rename-it.nl> (58fee67d) + + testsuite: mime: Created tests for some basic foreverypart loops. + + +M Makefile.am +A tests/extensions/mime/foreverypart.svtest + +2015-11-29 16:17:41 +0100 Stephan Bosch <stephan@rename-it.nl> (62af47b8) + + testsuite: Fixed the test_fail command to also work from within a + foreverypart loop. + + +M src/testsuite/cmd-test-fail.c + +2015-11-29 16:17:15 +0100 Stephan Bosch <stephan@rename-it.nl> (0a130f99) + + lib-sieve: interpreter; Added support for program jumps that explicitly + cross loop boundaries. Needed for test suite. + + +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h + +2015-11-29 15:33:25 +0100 Stephan Bosch <stephan@rename-it.nl> (856c89c6) + + lib-sieve: Fixed memory leak occurring in interpreter loop handling. + + +M src/lib-sieve/sieve-interpreter.c + +2015-11-29 15:28:18 +0100 Stephan Bosch <stephan@rename-it.nl> (07ad6819) + + testsuite: Accidentally committed disabled tests. + + +M tests/extensions/mime/errors.svtest + +2015-11-29 14:58:20 +0100 Stephan Bosch <stephan@rename-it.nl> (4d2c27cc) + + lib-sieve: interpreter: Improved robustness of code loop handling against + binary corruption. When the program crosses the boundary of the current jump + somehow, the program is terminated and a corruption error is returned. + + +M src/lib-sieve/plugins/mime/cmd-foreverypart.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h + +2015-11-29 13:46:03 +0100 Stephan Bosch <stephan@rename-it.nl> (028d6fef) + + lib-sieve: mime/foreverypart: Enforced loop nesting limit across includes. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve.c +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite.c +M tests/extensions/mime/errors.svtest +A tests/extensions/mime/errors/limits-include.sieve +A tests/extensions/mime/included/include-loop-2.sieve +A tests/extensions/mime/included/include-loop-3.sieve +A tests/extensions/mime/included/include-loop-4.sieve +A tests/extensions/mime/included/include-loop-5.sieve + +2015-11-29 13:00:38 +0100 Stephan Bosch <stephan@rename-it.nl> (2f4cdcdd) + + lib-sieve: mime/foreverypart: Implemented loop nesting limit. + + +M src/lib-sieve/plugins/mime/cmd-foreverypart.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-limits.h +M tests/extensions/mime/errors.svtest +A tests/extensions/mime/errors/limits.sieve + +2015-11-29 12:17:32 +0100 Stephan Bosch <stephan@rename-it.nl> (4ee04548) + + lib-sieve: mime/foreverypart: Fixed code dumping of `:param' argument. It + erroneously reported a code corruption. + + +M src/lib-sieve/plugins/mime/tag-mime.c + +2015-11-29 12:16:25 +0100 Stephan Bosch <stephan@rename-it.nl> (53bab871) + + lib-sieve: mime/foreverypart: Implemented basic execution tests. + + +M Makefile.am +M tests/extensions/mime/execute.svtest +M tests/extensions/mime/execute/foreverypart.sieve +A tests/extensions/mime/execute/mime.sieve + +2015-11-29 11:53:24 +0100 Stephan Bosch <stephan@rename-it.nl> (07318673) + + Merged concurrent changes. + + +2015-11-29 11:50:59 +0100 Stephan Bosch <stephan@rename-it.nl> (725a6c66) + + lib-sieve: Implemented the foreverypart and mime extensions (RFC 5703). + + +M Makefile.am +M README +M TODO +M configure.ac +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/mime/Makefile.am +A src/lib-sieve/plugins/mime/cmd-break.c +A src/lib-sieve/plugins/mime/cmd-foreverypart.c +A src/lib-sieve/plugins/mime/ext-foreverypart.c +A src/lib-sieve/plugins/mime/ext-mime-common.c +A src/lib-sieve/plugins/mime/ext-mime-common.h +A src/lib-sieve/plugins/mime/ext-mime.c +A src/lib-sieve/plugins/mime/tag-mime.c +M src/lib-sieve/sieve-extensions.c +A tests/extensions/mime/content-header.svtest +A tests/extensions/mime/errors.svtest +A tests/extensions/mime/errors/address-mime-tag.sieve +A tests/extensions/mime/errors/break.sieve +A tests/extensions/mime/errors/exists-mime-tag.sieve +A tests/extensions/mime/errors/foreverypart.sieve +A tests/extensions/mime/errors/header-mime-tag.sieve +A tests/extensions/mime/execute.svtest +A tests/extensions/mime/execute/foreverypart.sieve + +2015-11-29 11:50:44 +0100 Stephan Bosch <stephan@rename-it.nl> (7050cd8d) + + lib-sieve: Implemented running code loops in the interpreter. + + +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h + +2015-11-29 11:49:47 +0100 Stephan Bosch <stephan@rename-it.nl> (e5dc35fc) + + lib-sieve: Created message body part iterator and mime header list. + + +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h + +2015-11-29 11:48:29 +0100 Stephan Bosch <stephan@rename-it.nl> (1679708b) + + lib-sieve: Created special stringlist class for message headers, so that + header names can also be returned by the iterator. + + +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h + +2015-11-29 11:48:21 +0100 Stephan Bosch <stephan@rename-it.nl> (b9339d5b) + + lib-sieve: Reworked message body parsing to store the message parts in a + tree structure. + + +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M tests/extensions/body/content.svtest + +2015-11-29 11:47:47 +0100 Stephan Bosch <stephan@rename-it.nl> (d8eb07db) + + lib-sieve: The t_str_trim() function has moved to Dovecot. + + +M src/lib-sieve/sieve-settings.c + +2015-11-28 23:53:27 +0100 Stephan Bosch <stephan@rename-it.nl> (b947e601) + + Added new TODO item. + + +M TODO + +2015-11-18 22:11:31 +0100 Stephan Bosch <stephan@rename-it.nl> (fb2fed99) + + lib-sieve: Moved handling of implicit keep during multiscript execution + outside the script sequence itself. Before, implicit keep was executed as + part of the final script execution. This caused the implicit keep to be + executed as part of that script, including global context. This caused + insignificant errors during delivery to be logged as errors in the + administrator log when the last script is global. + + +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-script.c + +2015-11-15 22:46:01 +0100 Stephan Bosch <stephan@rename-it.nl> (c8f4930b) + + lib-sieve: Made message part content type and disposition available to + extensions. + + +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h + +2015-11-14 00:36:19 +0100 Stephan Bosch <stephan@rename-it.nl> (b378f922) + + lib-sieve: Make message the time the message processing started available to + any extension. + + +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h + +2015-11-14 00:30:30 +0100 Stephan Bosch <stephan@rename-it.nl> (67366e88) + + lib-sieve: Moved message body parsing code from body extension to Sieve + core. This makes this available for other extensions. + + +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h + +2015-11-02 18:56:39 +0100 Stephan Bosch <stephan@rename-it.nl> (07defb0a) + + lib-sieve: imap4flags extension: Made flag manipulation API available to + other extensions. + + +M src/lib-sieve/plugins/imap4flags/Makefile.am +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +A src/lib-sieve/plugins/imap4flags/sieve-ext-imap4flags.h +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c + +2015-11-02 18:56:39 +0100 Stephan Bosch <stephan@rename-it.nl> (5aebc1c8) + + testsuite: Allow setting configuration options from command line. These will + influence some of the performed tests. + + +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-settings.c + +2015-11-02 18:56:39 +0100 Stephan Bosch <stephan@rename-it.nl> (6ff4199c) + + lib-sieve: Implemented means to override existing (standard) extensions. + + +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h + +2015-11-02 18:56:39 +0100 Stephan Bosch <stephan@rename-it.nl> (ab12e844) + + Added pigeonhole.m4 to installation. + + +M Makefile.am +A pigeonhole.m4 + +2015-11-02 18:55:14 +0100 Stephan Bosch <stephan@rename-it.nl> (98226d2f) + + doveadm sieve plugin: Added proper handling of Sieve storage initialization + failure occurring when sieve_enabled=no + + +M src/plugins/doveadm-sieve/doveadm-sieve-cmd.c + +2015-10-29 22:14:32 +0100 Stephan Bosch <stephan@rename-it.nl> (d2a75724) + + lib-sieve: Added sieve_enabled setting that defaults to "yes". This allows + completely disabling Sieve processing for a particular user. + + +M src/lib-sieve/sieve-storage.c +M src/managesieve/managesieve-client.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2015-10-29 22:14:24 +0100 Stephan Bosch <stephan@rename-it.nl> (28b1d41f) + + doveadm sieve plugin: Fixed stray debug code committed in earlier patch. + + +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-get.c + +2015-10-27 23:42:52 +0100 Stephan Bosch <stephan@rename-it.nl> (a88ff161) + + lib-sieve: body extension: Properly implemented the :text body transform. It + now extracts bare text from HTML/XHMTL parts. Other text/* parts are still + returned as is. Any other unrecognized content types are skipped. + + +M Makefile.am +M README +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/ext-body.c +A tests/extensions/body/text.svtest + +2015-10-21 23:31:06 +0200 Stephan Bosch <stephan@rename-it.nl> (9bc63675) + + lib-sieve: enotify extension: mailto method: Implemented + sieve_notify_mailto_envelope_from setting. This allows setting the MAIL FROM + of the SMTP envelope for the notification e-mails. The syntax is identical + to the sieve_redirect_envelope_from setting. + + +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M tests/extensions/enotify/mailto.svtest + +2015-10-21 23:27:36 +0200 Stephan Bosch <stephan@rename-it.nl> (e66eddcd) + + lib-sieve: Created generic implementation for parsing an envelope_from + setting, such as sieve_redirect_envelope_from. Also adds a new source for + the envelope_from address called "postmaster". This means that the value is + obtained from the postmaster_address LDA setting. + + +M INSTALL +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h + +2015-10-20 21:54:49 +0200 Stephan Bosch <stephan@rename-it.nl> (c0d68bce) + + lib-sieve: script storage: Sieve mailbox attributes use an external storage, + so they don't need to be synced explicitly with any mail storage backend. + Patch by Timo Sirainen. + + +M src/lib-sieve/sieve-storage-sync.c + +2015-10-20 13:57:48 +0200 Stephan Bosch <stephan@rename-it.nl> (37e7b654) + + doveadm sieve plugin: Fixed crashes caused by incorrect context allocation + in the command implementations. The base context struct was allocated, + rather than the (larger) command-specific context. Patch by Timo Sirainen. + + +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-activate.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-get.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-put.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-rename.c + +2015-10-04 23:18:29 +0200 Stephan Bosch <stephan@rename-it.nl> (d3c8a4c1) + + Added signature for changeset 8cdb8b90e7a3 + + +M .hgsigs + +2015-10-04 23:14:08 +0200 Stephan Bosch <stephan@rename-it.nl> (d5710094) + + Added tag 0.4.9 for changeset 8cdb8b90e7a3 + + +2015-10-04 23:13:50 +0200 Stephan Bosch <stephan@rename-it.nl> (cef21760) + + Released v0.4.9 for Dovecot v2.2.19. + + +M NEWS +M configure.ac + +2015-10-02 21:37:28 +0200 Stephan Bosch <stephan@rename-it.nl> (0a7c0238) + + lib-sieve: file storage: Added assert to make Coverity happier. + + +M src/lib-sieve/storage/file/sieve-file-storage.c + +2015-10-02 17:43:37 +0200 Stephan Bosch <stephan@rename-it.nl> (52ed9371) + + lib-sieve: Use mailbox_save_using_mail() instead of mailbox_copy() for + delivering messages. This makes sure that the resulting mail storage events + are of the correct type for logging/notification. + + +M src/lib-sieve/sieve-actions.c + +2015-10-01 00:11:04 +0200 Stephan Bosch <stephan@rename-it.nl> (a4078e88) + + sieve-test: Fixed couple of Coverity warnings. + + +M src/sieve-tools/sieve-test.c + +2015-10-01 00:10:31 +0200 Stephan Bosch <stephan@rename-it.nl> (ab7ae1bc) + + Sieve extprograms plugin: Fixed Coverity warning. + + +M src/plugins/sieve-extprograms/cmd-pipe.c + +2015-10-01 00:09:51 +0200 Stephan Bosch <stephan@rename-it.nl> (193d2f88) + + doveadm sieve plugin: Addressed spurious Coverity warning. + + +M src/plugins/doveadm-sieve/doveadm-sieve-cmd.c + +2015-10-01 00:04:37 +0200 Stephan Bosch <stephan@rename-it.nl> (31b96ae3) + + Sieve file storage: Fixed couple of Coverity warnings. + + +M src/lib-sieve/storage/file/sieve-file-script.c +M src/lib-sieve/storage/file/sieve-file-storage.c + +2015-10-01 00:02:44 +0200 Stephan Bosch <stephan@rename-it.nl> (e331c727) + + Sieve metadata extension: Fixed couple of Coverity warnings. + + +M src/lib-sieve/plugins/metadata/tst-metadata.c +M src/lib-sieve/plugins/metadata/tst-metadataexists.c + +2015-09-30 00:54:40 +0200 Stephan Bosch <stephan@rename-it.nl> (b746e31d) + + Sieve vnd.dovecot.environment extension: Forgot 'extern' in extension + declaration. This causes link failures for certain platforms. + + +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-common.h + +2015-09-25 00:01:42 +0200 Stephan Bosch <stephan@rename-it.nl> (3b739e61) + + Added signature for changeset b2d5b1a5fa25 + + +M .hgsigs + +2015-09-24 23:35:00 +0200 Stephan Bosch <stephan@rename-it.nl> (5d5d4979) + + Added tag 0.4.9.rc1 for changeset b2d5b1a5fa25 + + +2015-09-24 23:33:17 +0200 Stephan Bosch <stephan@rename-it.nl> (df7e58f9) + + Released v0.4.9.rc1 for Dovecot v2.2.19.rc1. + + +M NEWS +M configure.ac + +2015-09-23 22:54:11 +0200 Stephan Bosch <stephan@rename-it.nl> (593dde9f) + + Remove now-unnecessary direct stdlib.h #includes. + + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve.c +M src/lib-sieve/storage/file/sieve-file-script-sequence.c +M src/lib-sieve/storage/file/sieve-file-script.c +M src/lib-sieve/storage/file/sieve-file-storage-list.c +M src/lib-sieve/storage/file/sieve-file-storage-quota.c +M src/lib-sieve/storage/file/sieve-file-storage-save.c +M src/lib-sieve/storage/file/sieve-file-storage.c +M src/lib-sieve/storage/ldap/sieve-ldap-db.c +M src/lib-sieve/util/realpath.c +M src/managesieve-login/client-authenticate.c +M src/managesieve-login/client.c +M src/managesieve-login/managesieve-login-settings-plugin.c +M src/managesieve/cmd-noop.c +M src/managesieve/main.c +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-commands.c +M src/managesieve/managesieve-settings.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.c +M src/sieve-tools/sieve-dump.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite.c + +2015-09-23 21:57:31 +0200 Stephan Bosch <stephan@rename-it.nl> (ab51bf47) + + Sieve vnd.dovecot.environment extension: Referenced specification from + extension source. + + +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment.c + +2015-09-23 21:54:39 +0200 Stephan Bosch <stephan@rename-it.nl> (8027c3ad) + + doc: Removed obsolete vnd.dovecot.duplicate specification sources. + + +D doc/rfc/xml/reference.IMAP4FLAGS.xml +D doc/rfc/xml/reference.MAILBOX.xml +D doc/rfc/xml/reference.VACATION.xml +D doc/rfc/xml/spec-bosch-sieve-duplicate.xml + +2015-09-23 21:50:10 +0200 Stephan Bosch <stephan@rename-it.nl> (a0f7efd0) + + Created specification for the vnd.dovecot.environment extension. + + +A doc/rfc/spec-bosch-sieve-dovecot-environment.txt +A doc/rfc/xml/reference.ENVIRONMENT.xml +A doc/rfc/xml/spec-bosch-sieve-dovecot-environment.xml + +2015-09-23 21:49:25 +0200 Stephan Bosch <stephan@rename-it.nl> (a8b8d1cb) + + Sieve vnd.dovecot.environment extension: Made activation of the environment + extension implicit. + + +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment.c +M tests/extensions/vnd.dovecot/environment/basic.svtest +M tests/extensions/vnd.dovecot/environment/variables.svtest + +2015-09-23 20:06:15 +0200 Stephan Bosch <stephan@rename-it.nl> (1ce4c883) + + Sieve extprograms plugin: Made line endings configurable for the input + passed to the external program. + + +M doc/plugins/sieve_extprograms.txt +M src/plugins/sieve-extprograms/sieve-extprograms-common.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.h +A tests/plugins/extprograms/bin/crlf +M tests/plugins/extprograms/execute/execute.svtest + +2015-09-21 23:34:41 +0200 Stephan Bosch <stephan@rename-it.nl> (66a4bf01) + + vnd.dovecot.environment extension: Forgot a \ in Makefile.am. + + +M src/lib-sieve/plugins/vnd.dovecot/environment/Makefile.am + +2015-09-08 01:08:34 +0200 Stephan Bosch <stephan@rename-it.nl> (b185215e) + + managesieve: Fixed assert failure occuring when client disconnects during + GETSCRIPT command. Passed NULL as reason to client_disconnect(), which is + not allowed. + + +M src/managesieve/cmd-getscript.c + +2015-09-08 01:07:43 +0200 Stephan Bosch <stephan@rename-it.nl> (d6079cf4) + + managesieve: Started using io_stream_get_disconnect_reason() for default + client_destroy() reason. + + +M src/managesieve/managesieve-client.c + +2015-08-29 13:12:58 +0200 Stephan Bosch <stephan@rename-it.nl> (e0c53ce7) + + Removed all invocations of strtoll() and friends. + + +M src/lib-sieve/sieve-settings.c + +2015-08-29 13:12:58 +0200 Stephan Bosch <stephan@rename-it.nl> (786522e4) + + Removed all invocations of atoi(). + + +M src/lib-sieve/storage/ldap/sieve-ldap-db.c + +2015-08-29 13:12:58 +0200 Stephan Bosch <stephan@rename-it.nl> (3e2d24fc) + + Changed type of internet port values to in_port_t everywhere. + + +M src/managesieve-login/client.c + +2015-08-29 12:53:29 +0200 Stephan Bosch <stephan@rename-it.nl> (b25371ee) + + Merged concurrent changes. + + +2015-08-17 23:56:21 +0200 Stephan Bosch <stephan@rename-it.nl> (0615ed9c) + + lib-sieve: Improved efficiency of reading a string-list operand that is + actually a single string. + + +M src/lib-sieve/sieve-code.c + +2015-08-17 23:51:35 +0200 Stephan Bosch <stephan@rename-it.nl> (5f6735d9) + + lib-sieve: variables extension: Added asserts to extension API to make sure + variables extension instance gets passed as argument. + + +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables-namespaces.c +M src/lib-sieve/plugins/variables/ext-variables-operands.c + +2015-08-17 23:41:05 +0200 Stephan Bosch <stephan@rename-it.nl> (f985536f) + + lib-sieve: vnd.dovecot.environment extension: Forgot to add several files in + previous commit. + + +A src/lib-sieve/plugins/vnd.dovecot/environment/Makefile.am +A src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-common.h +A src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-items.c +A src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-variables.c +A src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment.c +A tests/extensions/vnd.dovecot/environment/basic.svtest +A tests/extensions/vnd.dovecot/environment/variables.svtest + +2015-08-17 23:34:21 +0200 Stephan Bosch <stephan@rename-it.nl> (2c1540a5) + + lib-sieve: Implemented the vnd.dovecot.environment extension. This adds the + vnd.dovecot.default-mailbox and vnd.dovecot.username environment items. It + creates the 'env' variables namespace through which all environment items + can be accessed directly. This extension is yet to be documented properly. + More environment items are under consideration. + + +M Makefile.am +M configure.ac +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/environment/ext-environment-common.h +M src/lib-sieve/plugins/environment/ext-environment.c +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/vnd.dovecot/Makefile.am +M src/lib-sieve/sieve-extensions.c + +2015-08-16 19:00:29 +0200 Stephan Bosch <stephan@rename-it.nl> (30509319) + + sieve-filter: Fixed handling of failure-related implicit keep when there is + an explicit default destination folder. The message was left in the source + mailbox, even though it was stored in the destination folder. + + +M src/sieve-tools/sieve-filter.c + +2015-08-06 22:23:29 +0200 Stephan Bosch <stephan@rename-it.nl> (d35a452c) + + doveadm sieve plugin: Fixed incorrect initialization of mail user. + + +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c + +2015-08-06 22:23:03 +0200 Stephan Bosch <stephan@rename-it.nl> (74e03520) + + lib-sieve: Properly implemented checking of ABI version for plugins. + + +M configure.ac +M pigeonhole-config.h.in +M src/lib-sieve/sieve-plugins.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.c +M src/plugins/sieve-extprograms/sieve-extprograms-plugin.c + +2015-07-25 00:53:51 +0200 Stephan Bosch <stephan@rename-it.nl> (ccf6ae59) + + lib-sieve: Substituted inappropriate use of str_append_n() with normal + str_append(). + + +M src/lib-sieve/util/rfc2822.c + +2015-07-24 23:54:25 +0200 Stephan Bosch <stephan@rename-it.nl> (1cbc493c) + + testsuite: Fixed default envelope extraction fron test message. + + +M src/testsuite/testsuite-message.c + +2015-07-24 23:24:33 +0200 Stephan Bosch <stephan@rename-it.nl> (d1b6d77c) + + lib-sieve: util: Fixed RFC5322 header folding. + + +M src/lib-sieve/util/rfc2822.c +M tests/extensions/vacation/message.svtest + +2015-07-06 23:47:05 +0200 Stephan Bosch <stephan@rename-it.nl> (cf089193) + + doveadm-sieve: Fixed one memory leak. + + +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c + +2015-05-22 23:38:58 +0200 Stephan Bosch <stephan@rename-it.nl> (710b5ca5) + + sieve-test: Fixed Clang variable initialization warning. + + +M src/sieve-tools/sieve-test.c + +2015-05-22 23:36:03 +0200 Stephan Bosch <stephan@rename-it.nl> (18b089f6) + + Fixed duplicate const specifier warning from Clang. + + +M src/lib-sieve/plugins/relational/ext-relational-common.c + +2015-05-22 21:14:21 +0200 Stephan Bosch <stephan@rename-it.nl> (7c96426f) + + managesieve-login: proxy: Fixed use of SASL mechanisms with multiple + challenge-response cycles. Previous change had several problems. + + +M src/managesieve-login/managesieve-proxy.c + +2015-05-22 02:11:03 +0200 Stephan Bosch <stephan@rename-it.nl> (5da0edb0) + + managesieve-login: Changed proxy to better match imap equivalent. It now + uses dsasl-client, so it should now be possible to use SASL mechanisms other + than PLAIN. Cleaned up the code a bit. + + +M src/managesieve-login/managesieve-proxy.c + +2015-05-22 02:02:38 +0200 Stephan Bosch <stephan@rename-it.nl> (6dfca60c) + + managesieve-login: Copied too much in previous change. + + +M src/managesieve-login/managesieve-proxy.c + +2015-05-21 21:45:40 +0200 Stephan Bosch <stephan@rename-it.nl> (79e19b50) + + managesieve-login: Implemented proxy XCLIENT support. + + +M src/managesieve-login/client.c +M src/managesieve-login/client.h +M src/managesieve-login/managesieve-proxy.c + +2015-05-19 21:23:52 +0200 Stephan Bosch <stephan@rename-it.nl> (186911f0) + + managesieve-login: settings: Changed default listener initialization to + include field names. + + +M src/managesieve-login/managesieve-login-settings.c + +2015-05-15 20:54:00 +0200 Stephan Bosch <stephan@rename-it.nl> (898dd129) + + Added signature for changeset baa15dd77f9e + + +M .hgsigs + +2015-05-15 20:22:32 +0200 Stephan Bosch <stephan@rename-it.nl> (641126d2) + + Added tag 0.4.8 for changeset baa15dd77f9e + + +2015-05-15 20:22:20 +0200 Stephan Bosch <stephan@rename-it.nl> (f95a87c8) + + Released v0.4.8 for Dovecot v2.2.18. + + +M NEWS +M configure.ac + +2015-05-14 13:13:39 +0200 Stephan Bosch <stephan@rename-it.nl> (2ee12500) + + configure: Use consistent quotation for AC_DEFINEs as per autoconf + recommendations. + + +M configure.ac + +2015-05-13 23:13:42 +0200 Stephan Bosch <stephan@rename-it.nl> (e4405c33) + + Small adjustment to NEWS file. + + +M NEWS + +2015-05-13 22:54:18 +0200 Stephan Bosch <stephan@rename-it.nl> (406b2b87) + + Added signature for changeset 7b154d69394f + + +M .hgsigs + +2015-05-13 22:50:58 +0200 Stephan Bosch <stephan@rename-it.nl> (5443d289) + + Added tag 0.4.8.rc3 for changeset 7b154d69394f + + +2015-05-13 22:50:46 +0200 Stephan Bosch <stephan@rename-it.nl> (6f5be001) + + Released v0.4.8.rc3 for Dovecot v2.2.17. + + +M NEWS +M configure.ac + +2015-05-13 19:52:51 +0200 Stephan Bosch <stephan@rename-it.nl> (25d59c10) + + managesieve: Implemented support for reporting command statistics at + disconnect. + + +M src/managesieve/cmd-deletescript.c +M src/managesieve/cmd-getscript.c +M src/managesieve/cmd-putscript.c +M src/managesieve/cmd-renamescript.c +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h + +2015-05-13 19:52:51 +0200 Stephan Bosch <stephan@rename-it.nl> (eaf64db1) + + managesieve: Managesieve used "managesieve" rather than "sieve" as login + service name, which means that all managesieve-specific settings where + ignored. + + +M src/managesieve/main.c + +2015-05-13 19:52:51 +0200 Stephan Bosch <stephan@rename-it.nl> (d1cf3325) + + managesieve: Storage quota was not always enforced properly for scripts + uploaded as quoted string. Nobody does that, but we support it. + + +M src/managesieve/cmd-putscript.c + +2015-05-13 19:52:43 +0200 Stephan Bosch <stephan@rename-it.nl> (b3b0e003) + + lib-sieve: script: Forgot to assign storage error when determining script + size from stream. + + +M src/lib-sieve/sieve-script.c + +2015-05-12 22:51:12 +0200 Stephan Bosch <stephan@rename-it.nl> (4c587465) + + lib-smtp: storage: Fixed small problem in handling of default script. When + the default was first overriden, then deactivated and finally overriden + again, it would erroneously implicitly re-activate. + + +M src/lib-sieve/sieve-storage.c + +2015-05-12 20:53:46 +0200 Stephan Bosch <stephan@rename-it.nl> (daa9088f) + + lib-sieve: storage: Added parameter to sieve_script_delete() to allow + ignoring the active status of the script. Normally, the active script cannot + be deleted. This change is necessary to handle doveadm sieve delete -a + correctly when the provided script is the default. + + +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-storage.c +M src/managesieve/cmd-deletescript.c +M src/plugins/doveadm-sieve/doveadm-sieve-cmd-delete.c +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c + +2015-05-11 23:05:24 +0200 Stephan Bosch <stephan@rename-it.nl> (b171cb09) + + lib-sieve: storage: Fixed handling of defaul script in + sieve_storage_active_script_open(). It only worked when sieve_default_name + was set. + + +M src/lib-sieve/sieve-storage.c + +2015-05-11 21:04:39 +0200 Stephan Bosch <stephan@rename-it.nl> (f24b2920) + + Added signature for changeset 44d41235776d + + +M .hgsigs + +2015-05-11 21:02:10 +0200 Stephan Bosch <stephan@rename-it.nl> (3236a53c) + + Added tag 0.4.8.rc2 for changeset 44d41235776d + + +2015-05-11 21:02:00 +0200 Stephan Bosch <stephan@rename-it.nl> (42fe82af) + + Released v0.4.8.rc2 for Dovecot v2.2.17.rc1. + + +M configure.ac + +2015-05-11 10:03:02 +0200 Stephan Bosch <stephan@rename-it.nl> (f4f8d873) + + lib-sieve: storage: Fixed segfault problem in main storage initialization. + Caused by earlier sieve_default_name-related changes. + + +M src/lib-sieve/sieve-storage.c + +2015-05-11 00:23:22 +0200 Stephan Bosch <stephan@rename-it.nl> (00ef451c) + + Added signature for changeset fcc97e953584 + + +M .hgsigs + +2015-05-11 00:19:16 +0200 Stephan Bosch <stephan@rename-it.nl> (84528ce8) + + Added tag 0.4.8.rc1 for changeset fcc97e953584 + + +2015-05-11 00:19:00 +0200 Stephan Bosch <stephan@rename-it.nl> (c6c93204) + + Released v0.4.8.rc1 for Dovecot v2.2.17.rc1. + + +M NEWS +M configure.ac + +2015-05-10 22:52:09 +0200 Stephan Bosch <stephan@rename-it.nl> (a7867b24) + + Updated example configuration. + + +M doc/example-config/conf.d/90-sieve.conf + +2015-05-07 22:05:23 +0200 Stephan Bosch <stephan@rename-it.nl> (4ca65a78) + + lib-sieve: storage: Forgot to check whether sieve_default_name setting + exists. This caused a segfault in the test suite. + + +M src/lib-sieve/sieve-storage.c + +2015-05-07 21:46:57 +0200 Stephan Bosch <stephan@rename-it.nl> (91baa5c1) + + LDA Sieve plugin: Fixed spurious error caused by earlier changes. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2015-05-07 21:41:24 +0200 Stephan Bosch <stephan@rename-it.nl> (49a1885f) + + lib-sieve: storage: Check Sieve script name validity in configuration. + + +M src/lib-sieve/sieve-storage.c + +2015-05-07 21:17:40 +0200 Stephan Bosch <stephan@rename-it.nl> (74684fcb) + + lib-sieve: file storage: The sieve_script_is_active() function returns int + rather than bool. + + +M src/lib-sieve/storage/file/sieve-file-script.c + +2015-05-07 21:10:37 +0200 Stephan Bosch <stephan@rename-it.nl> (ccd08367) + + lib-sieve: storage: Changed configuration of default script visibility + feature. Using a location option for the default name makes no sense if its + only used for the main personal script. + + +M INSTALL +M src/lib-sieve/sieve-storage.c + +2015-05-06 23:58:57 +0200 Stephan Bosch <stephan@rename-it.nl> (f5775b67) + + lib-sieve: storage: Implemented magic to make sieve_default script visible + in main storage (e.g. from ManageSieve). + + +M INSTALL +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-storage-private.h +M src/lib-sieve/sieve-storage.c +M src/lib-sieve/sieve-storage.h +M src/lib-sieve/storage/file/sieve-file-storage-save.c +M src/lib-sieve/storage/file/sieve-file-storage.c +M src/lib-sieve/storage/file/sieve-file-storage.h +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2015-05-05 13:42:38 +0200 Stephan Bosch <stephan@rename-it.nl> (d1c868ae) + + lib-sieve: Erroneously decoded mime-encoded words in address headers. + + +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/index/tag-index.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M tests/test-address.svtest + +2015-05-05 10:41:45 +0200 Stephan Bosch <stephan@rename-it.nl> (1e563215) + + lib-sieve: util: program client: Fixed handing of situation when no input is + provided to external program used as a command. Previous fixes still omitted + a few important aspects: Connect return result wasn't actually passed up to + program_client_run(). Default exit code was wrong. + + +M src/lib-sieve/util/program-client-remote.c +M src/lib-sieve/util/program-client.c +M tests/plugins/extprograms/execute/execute.svtest + +2015-05-04 00:26:58 +0200 Stephan Bosch <stephan@rename-it.nl> (db218f64) + + lib-sieve: util: program client: Fixed omission in previous change. + + +M src/lib-sieve/util/program-client.c + +2015-05-04 00:22:09 +0200 Stephan Bosch <stephan@rename-it.nl> (8ba2d883) + + lib-sieve: util: program client: Fixed handling of connecting + asynchronously. + + +M src/lib-sieve/util/program-client-remote.c +M src/lib-sieve/util/program-client.c + +2015-04-23 02:04:38 +0200 Stephan Bosch <stephan@rename-it.nl> (45a84bda) + + lib-sieve: util: Fixed bug in t_realpath() normalization occuring with + relative symlinks below root. Also contains a few small code cleanups. + + +M src/lib-sieve/util/realpath.c + +2015-04-22 21:43:33 +0200 Stephan Bosch <stephan@rename-it.nl> (c7a2dc1a) + + Merged concurrent changes. + + +2015-04-22 21:36:29 +0200 Stephan Bosch <stephan@rename-it.nl> (6fcc0ca9) + + LDA Sieve plugin: Changed error handling so that each action log message can + have up-to-date time stamps. This change matches a change in LDA that is + aimed at logging timing statistics. + + +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/Makefile.am +A src/plugins/lda-sieve/lda-sieve-log.c +A src/plugins/lda-sieve/lda-sieve-log.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-script.c + +2015-04-08 23:48:30 +0200 Stephan Bosch <stephan@rename-it.nl> (3a83dab5) + + lib-sieve: editheader extension: The ADDHEADER operation mnemonic was in + lower case. + + +M src/lib-sieve/plugins/editheader/cmd-addheader.c + +2015-04-06 17:04:13 +0200 Stephan Bosch <stephan@rename-it.nl> (b1bc4da8) + + Fixed some inconsistencies in the INSTALL documentation. Forgot to adjust a + few things when the location types were introduced and documented. + + +M INSTALL +M doc/example-config/conf.d/90-sieve.conf + +2015-03-28 10:49:23 +0100 Stephan Bosch <stephan@rename-it.nl> (57aec8ab) + + Updated TODO. + + +M TODO + +2015-03-27 23:20:44 +0100 Stephan Bosch <stephan@rename-it.nl> (6aea1b8e) + + More small fixes in file script location documentation. + + +M doc/locations/file.txt + +2015-03-27 23:00:11 +0100 Stephan Bosch <stephan@rename-it.nl> (7b3a70cd) + + Small fixes in file script location documentation. + + +M doc/locations/file.txt + +2015-03-27 22:36:09 +0100 Stephan Bosch <stephan@rename-it.nl> (029e7a28) + + Revised documentation for the duplicate Sieve extension. + + +M doc/extensions/duplicate.txt + +2015-03-27 22:20:09 +0100 Stephan Bosch <stephan@rename-it.nl> (6de83f18) + + Revised documentation for the editheader Sieve extension. + + +M doc/extensions/editheader.txt + +2015-03-27 21:58:08 +0100 Stephan Bosch <stephan@rename-it.nl> (0ec8e14a) + + Updated RFCs in documentation. + + +M doc/rfc/Makefile.am +A doc/rfc/date-index.rfc5260.txt +D doc/rfc/draft-ietf-appsawg-sieve-duplicate-03.txt +A doc/rfc/duplicate.rfc7352.txt +A doc/rfc/mailbox-metadata.rfc5490.txt +D doc/rfc/spec-bosch-sieve-duplicate.txt + +2015-03-27 21:40:00 +0100 Stephan Bosch <stephan@rename-it.nl> (b55d8611) + + Fixed installation of documentation. This was quite fundamentally broken, + not only due to previous change. + + +M configure.ac +M doc/Makefile.am +A doc/extensions/Makefile.am +A doc/locations/Makefile.am +A doc/plugins/Makefile.am +M doc/rfc/Makefile.am + +2015-03-26 23:32:21 +0100 Stephan Bosch <stephan@rename-it.nl> (cfae5b21) + + Updated configuration-related documentation. + + +M INSTALL +M doc/extensions/duplicate.txt +R098 doc/script-location-dict.txt doc/locations/dict.txt +A doc/locations/file.txt +R100 doc/script-location-ldap.txt doc/locations/ldap.txt + +2015-03-19 23:27:48 +0100 Stephan Bosch <stephan@rename-it.nl> (eedd48c9) + + Added signature for changeset f2323a90c202 + + +M .hgsigs + +2015-03-19 23:18:35 +0100 Stephan Bosch <stephan@rename-it.nl> (993984f5) + + Added tag 0.4.7 for changeset f2323a90c202 + + +2015-03-19 23:18:17 +0100 Stephan Bosch <stephan@rename-it.nl> (1052e9e9) + + Released v0.4.7 for Dovecot v2.2.16. + + +M NEWS +M configure.ac + +2015-03-17 02:31:57 +0100 Stephan Bosch <stephan@rename-it.nl> (8ab23992) + + Added signature for changeset 87b2d3e43a44 + + +M .hgsigs + +2015-03-17 02:29:33 +0100 Stephan Bosch <stephan@rename-it.nl> (0b5e52db) + + Added tag 0.4.7.rc3 for changeset 87b2d3e43a44 + + +2015-03-17 02:29:22 +0100 Stephan Bosch <stephan@rename-it.nl> (3103de66) + + Released v0.4.7.rc3 for Dovecot v2.2.16. + + +M NEWS +M configure.ac + +2015-03-16 22:27:17 +0100 Stephan Bosch <stephan@rename-it.nl> (23006f38) + + lib-sieve: file storage: Fixed bug that caused missing active symlink to + cause a temporary error in some cases. + + +M src/lib-sieve/storage/file/sieve-file-storage.c + +2015-03-16 22:09:55 +0100 Stephan Bosch <stephan@rename-it.nl> (7491fe59) + + lib-sieve: file storage: Fixed bug in storage path normalization. A + conditional expression was inverted, causing the path to remain + unnormalized. + + +M src/lib-sieve/storage/file/sieve-file-storage.c + +2015-03-15 00:15:54 +0100 Stephan Bosch <stephan@rename-it.nl> (54f75842) + + Added signature for changeset fd050f466314 Messed up the previous attempt. + + +M .hgsigs + +2015-03-15 00:07:20 +0100 Stephan Bosch <stephan@rename-it.nl> (606e4778) + + Added signature for changeset b3439a979c2e + + +M .hgsigs + +2015-03-15 00:05:39 +0100 Stephan Bosch <stephan@rename-it.nl> (d07e65ab) + + Added tag 0.4.7.rc2 for changeset fd050f466314 + + +2015-03-15 00:05:14 +0100 Stephan Bosch <stephan@rename-it.nl> (5acb35f2) + + Released v0.4.7.rc2 for Dovecot v2.2.16. + + +M NEWS +M configure.ac + +2015-03-14 23:21:06 +0100 Stephan Bosch <stephan@rename-it.nl> (85854f75) + + lib-sieve: file storage: Fixed handling of invalid active script link. The + error status code wasn't set, so this was handled as an error rather than a + warning in the LDA plugin. + + +M src/lib-sieve/storage/file/sieve-file-storage-active.c + +2015-03-14 23:06:37 +0100 Stephan Bosch <stephan@rename-it.nl> (df8c776b) + + lib-sieve: file storage: Improved backwards compatibility with respect to + the active script being a regular file. + + +M src/lib-sieve/storage/file/sieve-file-storage.c + +2015-03-14 18:20:22 +0100 Stephan Bosch <stephan@rename-it.nl> (42387a43) + + lib-sieve: Added script metadata to binary dump output. + + +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/storage/dict/sieve-dict-script.c +M src/lib-sieve/storage/ldap/sieve-ldap-script.c + +2015-03-14 15:52:15 +0100 Stephan Bosch <stephan@rename-it.nl> (dc0bc425) + + lib-sieve: Improved debug messages about up-to-date status of a loaded + binary. + + +M src/lib-sieve/sieve-script.c +M src/lib-sieve/storage/dict/sieve-dict-script.c +M src/lib-sieve/storage/file/sieve-file-script.c +M src/lib-sieve/storage/ldap/sieve-ldap-script.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.h + +2015-03-14 15:31:53 +0100 Stephan Bosch <stephan@rename-it.nl> (11f38dd8) + + lib-sieve: dict: Fixed memory allocation bug in script object. + + +M src/lib-sieve/storage/dict/sieve-dict-script.c + +2015-03-12 22:14:44 +0100 Stephan Bosch <stephan@rename-it.nl> (8cc8d605) + + lib-sieve: file storage: Forgot to compare stat.st_dev in equals() method. + + +M src/lib-sieve/storage/file/sieve-file-script.c + +2015-03-12 21:42:31 +0100 Stephan Bosch <stephan@rename-it.nl> (386930cd) + + sievec: Don't pass the filename as script name when compiling a whole + directory. + + +M src/sieve-tools/sievec.c + +2015-03-12 21:41:03 +0100 Stephan Bosch <stephan@rename-it.nl> (bac0703b) + + lib-sieve: file storage: Improved checking of active script link using + t_normpath(). + + +M src/lib-sieve/storage/file/sieve-file-storage-active.c + +2015-03-12 21:37:41 +0100 Stephan Bosch <stephan@rename-it.nl> (a82ebb0c) + + lib-sieve: Restructured parsing of storage options. + + +M src/lib-sieve/sieve-storage.c + +2015-03-14 14:42:30 +0100 Stephan Bosch <stephan@rename-it.nl> (0645eedd) + + lib-sieve: Fixed handling of script stream errors. + + +M src/lib-sieve/storage/file/sieve-file-script.c + +2015-03-12 21:34:10 +0100 Stephan Bosch <stephan@rename-it.nl> (9245e631) + + lib-sieve: Implemented normalization for script storage locations for all + storage drivers. This is particularly important when the location is + recorded in the binary for checking whether it is up-to-date. + + +M src/lib-sieve/sieve-script.c +M src/lib-sieve/storage/dict/sieve-dict-script.c +M src/lib-sieve/storage/dict/sieve-dict-storage.c +M src/lib-sieve/storage/dict/sieve-dict-storage.h +M src/lib-sieve/storage/file/Makefile.am +M src/lib-sieve/storage/file/sieve-file-script.c +M src/lib-sieve/storage/file/sieve-file-storage.c +M src/lib-sieve/storage/ldap/sieve-ldap-script.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.c + +2015-03-12 21:03:28 +0100 Stephan Bosch <stephan@rename-it.nl> (a64bca4a) + + lib-sieve: Implemented utility functions to normalize filesystem paths. + + +M src/lib-sieve/util/Makefile.am +A src/lib-sieve/util/realpath.c +A src/lib-sieve/util/realpath.h + +2015-03-11 23:59:51 +0100 Stephan Bosch <stephan@rename-it.nl> (c2edac3b) + + lib-sieve: script: Added more debug output about metadata up-to-date status. + + +M src/lib-sieve/sieve-script.c + +2015-03-10 03:19:39 +0100 Stephan Bosch <stephan@rename-it.nl> (fb9f1f0e) + + Added signature for changeset 27ad95fd05a0 + + +M .hgsigs + +2015-03-10 03:17:53 +0100 Stephan Bosch <stephan@rename-it.nl> (5e008647) + + Added tag 0.4.7.rc1 for changeset 27ad95fd05a0 + + +2015-03-10 03:17:33 +0100 Stephan Bosch <stephan@rename-it.nl> (b63e87a0) + + Released v0.4.7.rc1 for Dovecot v2.2.16.rc1. + + +M NEWS +M configure.ac + +2015-03-10 02:42:53 +0100 Stephan Bosch <stephan@rename-it.nl> (5280156c) + + Updated README with addition of support for the metadata extensions. + + +M README + +2015-03-06 21:36:40 +0100 Stephan Bosch <stephan@rename-it.nl> (ed5196bc) + + lib-sieve: Moved lexical scanner to system pool. + + +M src/lib-sieve/sieve-lexer.c + +2015-03-06 21:14:01 +0100 Stephan Bosch <stephan@rename-it.nl> (665fba16) + + lib-sieve: Cleaned up error handling for the lexical scanner. + + +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h + +2015-03-06 20:02:15 +0100 Stephan Bosch <stephan@rename-it.nl> (d01da0de) + + lib-sieve: editheader extension: Made protection against addition and + deletion of headers configurable separately. Also, the received and + auto-submitted headers are now only protected against deletion as required + in the RFC. Updated the documentation accordingly. + + +M doc/extensions/editheader.txt +M src/lib-sieve/plugins/editheader/cmd-addheader.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.h +M tests/extensions/editheader/protected.svtest + +2015-03-06 19:02:53 +0100 Stephan Bosch <stephan@rename-it.nl> (01b297b6) + + metadata: Fixed testsuite after changes in Dovecot. Currently cannot freely + assing server metadata items for testing. Disabled tests for now. + + +M tests/extensions/metadata/execute.svtest + +2015-03-06 18:59:46 +0100 Stephan Bosch <stephan@rename-it.nl> (35f7d173) + + lda sieve plugin: Started using smtp_client_deinit_timeout() to give a + session timeout. + + +M src/lib-sieve/sieve-smtp.c +M src/lib-sieve/sieve-types.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h + +2015-03-06 17:12:35 +0100 Stephan Bosch <stephan@rename-it.nl> (9fe14573) + + doveadm sieve plugin: Forgot to add new headers to distribution. + + +M src/plugins/doveadm-sieve/Makefile.am + +2015-02-23 09:21:10 +0100 Stephan Bosch <stephan@rename-it.nl> (ccfd86f6) + + lib-sieve: Fixed bug in `:matches' match-type that made a pattern without + wildcards match as if there were a '*' at the beginning. + + +M src/lib-sieve/mcht-matches.c +M tests/match-types/matches.svtest + +2015-02-21 18:44:30 +0100 Stephan Bosch <stephan@rename-it.nl> (13e14c9f) + + doveadm sieve plugin: Forgot to change one sieve_script_delete() invocation + in previous change. + + +M src/plugins/doveadm-sieve/doveadm-sieve-sync.c + +2015-02-21 17:28:22 +0100 Stephan Bosch <stephan@rename-it.nl> (7246ef04) + + doveadm sieve plugin: Implemented commands for managing Sieve scripts. This + allows performing ManageSieve actions at command line or through doveadm + server. + + +M .hgignore +M doc/man/Makefile.am +A doc/man/doveadm-sieve.1.in +A doc/man/global-options-formatter.inc +A doc/man/global-options.inc +A doc/man/option-A.inc +A doc/man/option-S-socket.inc +A doc/man/option-u-user.inc +M doc/man/pigeonhole.7.in +M doc/man/reporting-bugs.inc +M doc/man/sed.sh +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/managesieve/cmd-deletescript.c +M src/plugins/doveadm-sieve/Makefile.am +A src/plugins/doveadm-sieve/doveadm-sieve-cmd-activate.c +A src/plugins/doveadm-sieve/doveadm-sieve-cmd-delete.c +A src/plugins/doveadm-sieve/doveadm-sieve-cmd-get.c +A src/plugins/doveadm-sieve/doveadm-sieve-cmd-list.c +A src/plugins/doveadm-sieve/doveadm-sieve-cmd-put.c +A src/plugins/doveadm-sieve/doveadm-sieve-cmd-rename.c +A src/plugins/doveadm-sieve/doveadm-sieve-cmd.c +A src/plugins/doveadm-sieve/doveadm-sieve-cmd.h +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c +A src/plugins/doveadm-sieve/doveadm-sieve-plugin.h +A src/plugins/doveadm-sieve/doveadm-sieve-sync.c + +2015-02-19 01:00:19 +0100 Stephan Bosch <stephan@rename-it.nl> (ccd5660e) + + managesieve: Forgot to dereference script object in RENAMESCRIPT command. + + +M src/managesieve/cmd-renamescript.c + +2015-02-01 13:23:15 +0100 Stephan Bosch <stephan@rename-it.nl> (ddcb1828) + + Updated TODO. + + +M TODO + +2015-01-16 18:25:51 +0100 Stephan Bosch <stephan@rename-it.nl> (9514b62e) + + lib-sieve: file storage: Restructured storage initialization to address + backwards compatibility issues. + + +M src/lib-sieve/storage/file/sieve-file-script.c +M src/lib-sieve/storage/file/sieve-file-storage-active.c +M src/lib-sieve/storage/file/sieve-file-storage-list.c +M src/lib-sieve/storage/file/sieve-file-storage-quota.c +M src/lib-sieve/storage/file/sieve-file-storage-save.c +M src/lib-sieve/storage/file/sieve-file-storage.c +M src/lib-sieve/storage/file/sieve-file-storage.h + +2015-01-16 18:23:49 +0100 Stephan Bosch <stephan@rename-it.nl> (3971b095) + + lib-sieve: Make sure internal script storage errors clear previous error. + + +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-storage.c + +2015-01-08 02:07:51 +0100 Stephan Bosch <stephan@rename-it.nl> (116ace11) + + Updated copyright notices to include the year 2015. + + +M doc/man/pigeonhole.7.in +M doc/man/sieve-dump.1.in +M doc/man/sieve-filter.1.in +M doc/man/sieve-test.1.in +M doc/man/sievec.1.in +M src/lib-managesieve/managesieve-arg.c +M src/lib-managesieve/managesieve-arg.h +M src/lib-managesieve/managesieve-parser.c +M src/lib-managesieve/managesieve-parser.h +M src/lib-managesieve/managesieve-quote.c +M src/lib-managesieve/managesieve-quote.h +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/mail-raw.h +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/cmp-i-ascii-casemap.c +M src/lib-sieve/cmp-i-octet.c +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/copy/sieve-ext-copy.h +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/ext-date-common.h +M src/lib-sieve/plugins/date/ext-date.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.c +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.h +M src/lib-sieve/plugins/duplicate/ext-duplicate.c +M src/lib-sieve/plugins/duplicate/tst-duplicate.c +M src/lib-sieve/plugins/editheader/cmd-addheader.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.h +M src/lib-sieve/plugins/editheader/ext-editheader-limits.h +M src/lib-sieve/plugins/editheader/ext-editheader.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify-limits.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.h +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/environment/ext-environment-common.h +M src/lib-sieve/plugins/environment/ext-environment.c +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/ihave/cmd-error.c +M src/lib-sieve/plugins/ihave/ext-ihave-binary.c +M src/lib-sieve/plugins/ihave/ext-ihave-binary.h +M src/lib-sieve/plugins/ihave/ext-ihave-common.c +M src/lib-sieve/plugins/ihave/ext-ihave-common.h +M src/lib-sieve/plugins/ihave/ext-ihave.c +M src/lib-sieve/plugins/ihave/tst-ihave.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-limits.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/index/ext-index-common.c +M src/lib-sieve/plugins/index/ext-index-common.h +M src/lib-sieve/plugins/index/ext-index.c +M src/lib-sieve/plugins/index/tag-index.c +M src/lib-sieve/plugins/mailbox/ext-mailbox-common.h +M src/lib-sieve/plugins/mailbox/ext-mailbox.c +M src/lib-sieve/plugins/mailbox/sieve-ext-mailbox.h +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/metadata/ext-metadata-common.h +M src/lib-sieve/plugins/metadata/ext-metadata.c +M src/lib-sieve/plugins/metadata/tst-metadata.c +M src/lib-sieve/plugins/metadata/tst-metadataexists.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.h +M src/lib-sieve/plugins/notify/ext-notify-limits.h +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/plugins/regex/ext-regex-common.c +M src/lib-sieve/plugins/regex/ext-regex-common.h +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/lib-sieve/plugins/vacation/ext-vacation-seconds.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.h +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables-dump.h +M src/lib-sieve/plugins/variables/ext-variables-limits.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-name.c +M src/lib-sieve/plugins/variables/ext-variables-name.h +M src/lib-sieve/plugins/variables/ext-variables-namespaces.c +M src/lib-sieve/plugins/variables/ext-variables-namespaces.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug-common.h +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary-code.c +M src/lib-sieve/sieve-binary-debug.c +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-objects.c +M src/lib-sieve/sieve-objects.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-plugins.c +M src/lib-sieve/sieve-plugins.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-runtime-trace.c +M src/lib-sieve/sieve-runtime-trace.h +M src/lib-sieve/sieve-runtime.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve-smtp.c +M src/lib-sieve/sieve-smtp.h +M src/lib-sieve/sieve-storage-private.h +M src/lib-sieve/sieve-storage-sync.c +M src/lib-sieve/sieve-storage.c +M src/lib-sieve/sieve-storage.h +M src/lib-sieve/sieve-stringlist.c +M src/lib-sieve/sieve-stringlist.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/storage/dict/sieve-dict-script.c +M src/lib-sieve/storage/dict/sieve-dict-storage.c +M src/lib-sieve/storage/dict/sieve-dict-storage.h +M src/lib-sieve/storage/file/sieve-file-script-sequence.c +M src/lib-sieve/storage/file/sieve-file-script.c +M src/lib-sieve/storage/file/sieve-file-storage-active.c +M src/lib-sieve/storage/file/sieve-file-storage-list.c +M src/lib-sieve/storage/file/sieve-file-storage-quota.c +M src/lib-sieve/storage/file/sieve-file-storage-save.c +M src/lib-sieve/storage/file/sieve-file-storage.c +M src/lib-sieve/storage/file/sieve-file-storage.h +M src/lib-sieve/storage/ldap/sieve-ldap-db.c +M src/lib-sieve/storage/ldap/sieve-ldap-script.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage-settings.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c +M src/lib-sieve/tst-truefalse.c +M src/lib-sieve/util/edit-mail.c +M src/lib-sieve/util/edit-mail.h +M src/lib-sieve/util/program-client-local.c +M src/lib-sieve/util/program-client-private.h +M src/lib-sieve/util/program-client-remote.c +M src/lib-sieve/util/program-client.c +M src/lib-sieve/util/program-client.h +M src/lib-sieve/util/rfc2822.c +M src/lib-sieve/util/rfc2822.h +M src/managesieve-login/client-authenticate.c +M src/managesieve-login/client-authenticate.h +M src/managesieve-login/client.c +M src/managesieve-login/client.h +M src/managesieve-login/managesieve-login-settings-plugin.c +M src/managesieve-login/managesieve-login-settings-plugin.h +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve-login/managesieve-login-settings.h +M src/managesieve-login/managesieve-proxy.c +M src/managesieve-login/managesieve-proxy.h +M src/managesieve/cmd-capability.c +M src/managesieve/cmd-deletescript.c +M src/managesieve/cmd-getscript.c +M src/managesieve/cmd-havespace.c +M src/managesieve/cmd-listscripts.c +M src/managesieve/cmd-logout.c +M src/managesieve/cmd-noop.c +M src/managesieve/cmd-putscript.c +M src/managesieve/cmd-renamescript.c +M src/managesieve/cmd-setactive.c +M src/managesieve/main.c +M src/managesieve/managesieve-capabilities.c +M src/managesieve/managesieve-capabilities.h +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h +M src/managesieve/managesieve-commands.c +M src/managesieve/managesieve-commands.h +M src/managesieve/managesieve-common.h +M src/managesieve/managesieve-quota.c +M src/managesieve/managesieve-quota.h +M src/managesieve/managesieve-settings.c +M src/managesieve/managesieve-settings.h +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/plugins/lda-sieve/lda-sieve-plugin.h +M src/plugins/settings/pigeonhole-settings.c +M src/plugins/sieve-extprograms/cmd-execute.c +M src/plugins/sieve-extprograms/cmd-filter.c +M src/plugins/sieve-extprograms/cmd-pipe.c +M src/plugins/sieve-extprograms/ext-execute.c +M src/plugins/sieve-extprograms/ext-filter.c +M src/plugins/sieve-extprograms/ext-pipe.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.h +M src/plugins/sieve-extprograms/sieve-extprograms-plugin.c +M src/plugins/sieve-extprograms/sieve-extprograms-plugin.h +M src/sieve-tools/sieve-dump.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-imap-metadata.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-result.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-arguments.c +M src/testsuite/testsuite-arguments.h +M src/testsuite/testsuite-binary.c +M src/testsuite/testsuite-binary.h +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-log.h +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-result.h +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-script.h +M src/testsuite/testsuite-settings.c +M src/testsuite/testsuite-settings.h +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite-substitutions.c +M src/testsuite/testsuite-substitutions.h +M src/testsuite/testsuite-variables.c +M src/testsuite/testsuite-variables.h +M src/testsuite/testsuite.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-action.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c + +2015-01-01 17:12:17 +0100 Stephan Bosch <stephan@rename-it.nl> (bc3c7ff7) + + lib-sieve: Added more debug output to binary up-to-date checking. + + +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/storage/file/sieve-file-script.c + +2014-12-30 23:01:04 +0100 Stephan Bosch <stephan@rename-it.nl> (9420e6de) + + lib-sieve: Fixed crash in validation of the string parameter of the + comparator tag. It couldn't handle a missing parameter (which also means + missing arguments of the test itself in most cases). This is fixed by using + the sieve_validate_tag_parameter() utility function. Testsuite is also + extended. + + +M src/lib-sieve/sieve-comparators.c +M tests/compile/errors.svtest +A tests/compile/errors/comparator.sieve + +2014-12-30 22:57:07 +0100 Stephan Bosch <stephan@rename-it.nl> (86f27058) + + testsuite: Added syntax checks for body test. + + +M Makefile.am +A tests/extensions/body/errors.svtest +A tests/extensions/body/errors/syntax.sieve + +2014-12-30 22:56:11 +0100 Stephan Bosch <stephan@rename-it.nl> (7260b4d4) + + lib-sieve: Fixed parameter validation error message for tagged argument. It + had a whitespace where it didn't belong. + + +M src/lib-sieve/sieve-validator.c + +2014-12-20 18:18:16 +0100 Stephan Bosch <stephan@rename-it.nl> (d9ca5247) + + lib-sieve: Turned message envelope address parse errors into warnings. + + +M src/lib-sieve/sieve-message.c + +2014-12-20 16:45:32 +0100 Stephan Bosch <stephan@rename-it.nl> (2c77b286) + + lib-sieve: Accept non-standard domain names, e.g. containing '_'. + + +M src/lib-sieve/sieve-address.c +M tests/extensions/envelope.svtest + +2014-12-17 01:15:04 +0100 Stephan Bosch <stephan@rename-it.nl> (cffd007e) + + Updated LGPL license. + + +M COPYING.LGPL + +2014-12-17 01:12:43 +0100 Stephan Bosch <stephan@rename-it.nl> (797e9294) + + lib-sieve: program client: Made sure supplemental group privileges are also + dropped. + + +M src/lib-sieve/util/program-client-local.c + +2014-12-17 00:58:58 +0100 Stephan Bosch <stephan@rename-it.nl> (b279890d) + + tests: Fixed extprograms test suite. Recent changes in handling of unknown + tags caused `make test-plugins' to fail. + + +M tests/plugins/extprograms/execute/errors/syntax.sieve + +2014-12-17 00:35:47 +0100 Stephan Bosch <stephan@rename-it.nl> (00c807f2) + + lib-sieve: Fixed printing of hybrid command type. + + +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h + +2014-11-22 00:17:13 +0100 Stephan Bosch <stephan@rename-it.nl> (60c8e9d4) + + lib-sieve: Consolidated checking mailbox name. + + +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/metadata/tst-metadata.c +M src/lib-sieve/plugins/metadata/tst-metadataexists.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h + +2014-11-21 01:23:15 +0100 Stephan Bosch <stephan@rename-it.nl> (aa8e4148) + + lib-sieve: metadata extensions: Implemented proper checking of annotation + names everywhere. Also added testsuite items to test syntax. + + +M Makefile.am +M src/lib-sieve/plugins/metadata/tst-metadataexists.c +A tests/extensions/metadata/errors.svtest +A tests/extensions/metadata/errors/syntax.sieve +M tests/extensions/metadata/execute.svtest + +2014-11-20 01:04:00 +0100 Stephan Bosch <stephan@rename-it.nl> (f898a54a) + + lib-sieve: Flush duplicate database during start phase of result execution + rather than commit phase. This will release the duplicate database lock + earlier, even before a mail storage transation is started. + + +M src/lib-sieve/sieve-result.c + +2014-11-20 00:53:41 +0100 Stephan Bosch <stephan@rename-it.nl> (ccf3c957) + + testsuite: Created tests for the Sieve servermetadata extension. + + +M src/testsuite/cmd-test-imap-metadata.c +M src/testsuite/testsuite-mailstore.c +M tests/extensions/metadata/execute.svtest + +2014-11-20 00:51:09 +0100 Stephan Bosch <stephan@rename-it.nl> (2b08d727) + + lib-sieve: servermetadata extension: Fixed segfault. + + +M src/lib-sieve/plugins/metadata/tst-metadata.c + +2014-11-17 02:20:40 +0100 Stephan Bosch <stephan@rename-it.nl> (bad772f5) + + Added basic testsuite items for new Sieve metadata support. + + +M Makefile.am +M src/lib-sieve/plugins/metadata/tst-metadata.c +M src/testsuite/Makefile.am +A src/testsuite/cmd-test-imap-metadata.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite.c +A tests/extensions/metadata/execute.svtest + +2014-11-16 23:16:38 +0100 Stephan Bosch <stephan@rename-it.nl> (31b2c8d7) + + Merged concurrent changes. + + +2014-11-16 23:13:58 +0100 Stephan Bosch <stephan@rename-it.nl> (f63b20cd) + + lib-sieve: Finished support for mboxmetadata and servermetadata extensions. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +M src/lib-sieve/plugins/metadata/Makefile.am +M src/lib-sieve/plugins/metadata/ext-metadata-common.h +M src/lib-sieve/plugins/metadata/tst-metadata.c +M src/lib-sieve/plugins/metadata/tst-metadataexists.c +M src/lib-sieve/sieve-extensions.c +M src/sieve-tools/sieve-test.c + +2014-11-13 09:37:21 +0100 Stephan Bosch <stephan@rename-it.nl> (ab8d1ef0) + + lib-sieve: Increased binary minor version due to changes in optional operand + codes. + + +M src/lib-sieve/sieve-binary.h + +2014-11-13 09:36:13 +0100 Stephan Bosch <stephan@rename-it.nl> (79d6a5b8) + + lib-sieve: Fixed bug in handling of binary errors for action side-effects + and message overrides. + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h + +2014-11-12 22:21:14 +0100 Stephan Bosch <stephan@rename-it.nl> (0cb62bcc) + + Updated README with with implementation status. + + +M README + +2014-11-12 22:10:25 +0100 Stephan Bosch <stephan@rename-it.nl> (9a193393) + + lib-sieve: Implemented the Sieve index extension (RFC 5260). + + +M Makefile.am +M configure.ac +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/index/Makefile.am +A src/lib-sieve/plugins/index/ext-index-common.c +A src/lib-sieve/plugins/index/ext-index-common.h +A src/lib-sieve/plugins/index/ext-index.c +A src/lib-sieve/plugins/index/tag-index.c +M src/lib-sieve/sieve-extensions.c +A tests/extensions/index/basic.svtest +A tests/extensions/index/errors.svtest +A tests/extensions/index/errors/syntax.sieve + +2014-11-12 22:10:24 +0100 Stephan Bosch <stephan@rename-it.nl> (842ebbec) + + lib-sieve: Created message override infrastructure. This allows extension of + test commands that evaluate the message somehow. Currently this is + implemented only for the message header. Extensions can thereby influence + what headers are evaluated and how. + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M tests/compile/errors.svtest + +2014-11-12 22:10:23 +0100 Stephan Bosch <stephan@rename-it.nl> (bddc00a5) + + lib-sieve: Implemented the index stringlist class which selects an item of + the parent at a particular index. + + +M src/lib-sieve/sieve-stringlist.c +M src/lib-sieve/sieve-stringlist.h + +2014-11-12 22:09:44 +0100 Stephan Bosch <stephan@rename-it.nl> (fa4ae816) + + lib-sieve: Made validator resolve all tagged command arguments before + validating them. This is needed so that argument validation functions can + reliably verify other arguments at arbitrary positions. + + +M src/lib-sieve/sieve-validator.c + +2014-11-02 18:35:34 +0100 Stephan Bosch <stephan@rename-it.nl> (60012e68) + + Added signature for changeset 99d796a8cd26 + + +M .hgsigs + +2014-11-02 18:32:40 +0100 Stephan Bosch <stephan@rename-it.nl> (8b664b06) + + Added tag 0.4.6 for changeset 99d796a8cd26 + + +2014-11-02 18:32:06 +0100 Stephan Bosch <stephan@rename-it.nl> (a06cc4be) + + Released v0.4.6 for Dovecot v2.2.15. + + +M NEWS +M configure.ac + +2014-10-31 00:50:28 +0100 Stephan Bosch <stephan@rename-it.nl> (b0be4ab4) + + After make distclean the distributed tarball would fail to recompile. + + +M Makefile.am + +2014-10-30 23:27:42 +0100 Stephan Bosch <stephan@rename-it.nl> (409858f5) + + Added signature for changeset f5e3ef477a32 + + +M .hgsigs + +2014-10-30 23:25:20 +0100 Stephan Bosch <stephan@rename-it.nl> (1702fccc) + + Added tag 0.4.5 for changeset f5e3ef477a32 + + +2014-10-30 23:25:07 +0100 Stephan Bosch <stephan@rename-it.nl> (890ae8e7) + + Released v0.4.5 for Dovecot v2.2.15. + + +M NEWS +M configure.ac + +2014-10-30 23:15:45 +0100 Stephan Bosch <stephan@rename-it.nl> (00df2072) + + Previous change actually didn't work completely. + + +M configure.ac + +2014-10-30 22:40:16 +0100 Stephan Bosch <stephan@rename-it.nl> (41895b01) + + Fixed distcheck problem caused by pigeonhole-version.h. + + +M Makefile.am +M configure.ac + +2014-10-30 18:47:26 +0100 Stephan Bosch <stephan@rename-it.nl> (26cb5e95) + + New pigeonhole-version.h header was installed in the wrong directory. + + +M Makefile.am + +2014-10-30 09:43:18 +0100 Stephan Bosch <stephan@rename-it.nl> (5be0f805) + + lib-sieve: Fixed handling of implicit keep. The sieve_result_execute() + function returned the wrong status result. + + +M src/lib-sieve/sieve-result.c + +2014-10-29 22:00:31 +0100 Stephan Bosch <stephan@rename-it.nl> (16b50682) + + Added dummy settings plugin that adds a Pigeonhole version banner to + doveconf output. + + +M configure.ac +M src/plugins/Makefile.am +A src/plugins/settings/Makefile.am +A src/plugins/settings/pigeonhole-settings.c + +2014-10-29 21:37:07 +0100 Stephan Bosch <stephan@rename-it.nl> (178e1f5e) + + Forgot to add and ignore new files in latest commit. + + +M .hgignore +A is-tagged.py +A update-version.sh + +2014-10-29 03:05:43 +0100 Stephan Bosch <stephan@rename-it.nl> (a3a616c3) + + Implmented reporting full Pigeonhole version with hg tag so that builds + between releases can be distinguished. Copied from Dovecot for the most + part. + + +M Makefile.am +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.c +M src/plugins/sieve-extprograms/sieve-extprograms-plugin.c + +2014-10-28 22:34:48 +0100 Stephan Bosch <stephan@rename-it.nl> (76c59355) + + lib-sieve: sieve script: Made sure there is a script name for when + sieve_script_open() fails. + + +M src/lib-sieve/storage/file/sieve-file-script.c + +2014-10-28 14:53:39 +0100 Stephan Bosch <stephan@rename-it.nl> (1552383d) + + lib-sieve: Fixed potential segfault bug in file storage driver. + + +M src/lib-sieve/storage/file/sieve-file-script.c + +2014-10-28 01:53:46 +0100 Stephan Bosch <stephan@rename-it.nl> (2c03f457) + + Added signature for changeset b3303f675157 + + +M .hgsigs + +2014-10-28 01:39:32 +0100 Stephan Bosch <stephan@rename-it.nl> (e634184d) + + Added tag 0.4.4 for changeset b3303f675157 + + +2014-10-28 01:39:14 +0100 Stephan Bosch <stephan@rename-it.nl> (cc57bb25) + + Released v0.4.4 for Dovecot v2.2.15. + + +M NEWS +M configure.ac + +2014-10-28 00:54:15 +0100 Stephan Bosch <stephan@rename-it.nl> (52c305a3) + + doveadm-sieve: Fixed timeout leaks occuring while running doveadm. This was + caused by a circular reference. + + +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-storage-private.h +M src/lib-sieve/sieve-storage-sync.c +M src/lib-sieve/sieve-storage.c + +2014-10-27 21:58:13 +0100 Stephan Bosch <stephan@rename-it.nl> (42693b97) + + doveadm-sieve: Fixed problem with synchronizing the active script. + + +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-storage-private.h +M src/lib-sieve/sieve-storage-sync.c +M src/lib-sieve/sieve-storage.c +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2014-10-26 14:10:27 +0100 Stephan Bosch <stephan@rename-it.nl> (591a6272) + + lib-sieve: storage: Fixed bug in synchronization intialization. Storage flag + checks were bogus. + + +M src/lib-sieve/sieve-storage-sync.c + +2014-10-25 21:51:16 +0200 Stephan Bosch <stephan@rename-it.nl> (2403ce99) + + Adjusted to datastack-related changes in Dovecot lib-storage. + + +M src/lib-sieve/util/edit-mail.c + +2014-10-19 22:50:23 +0200 Stephan Bosch <stephan@rename-it.nl> (fd9d0bd4) + + managesieve: If client gets disconnected due to iostream error, log the full + error. + + +M src/managesieve/managesieve-client.c + +2014-10-19 18:14:20 +0200 Stephan Bosch <stephan@rename-it.nl> (59b3963e) + + doveadm-sieve plugin: Improved debugging a bit. + + +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2014-10-19 13:39:37 +0200 Stephan Bosch <stephan@rename-it.nl> (53b93a44) + + managesieve-login: The AUTHENTICATE command returned bogus ALERT response + code. + + +M src/managesieve-login/client-authenticate.c + +2014-10-19 13:37:38 +0200 Stephan Bosch <stephan@rename-it.nl> (9503c3a5) + + managesieve-login: Fixed handling of invalid initial response argument to + AUTHENTICATE command. + + +M src/managesieve-login/client-authenticate.c + +2014-10-19 13:36:57 +0200 Stephan Bosch <stephan@rename-it.nl> (a66396b3) + + Forgot one file in last commit. + + +M src/lib-managesieve/managesieve-parser.c + +2014-10-19 13:10:27 +0200 Stephan Bosch <stephan@rename-it.nl> (f365ceb3) + + managesieve: Changed managesieve parser's quoted string stream to use + io_stream_set_error(). + + +M src/managesieve-login/client-authenticate.c +M src/managesieve/cmd-putscript.c + +2014-10-19 11:01:17 +0200 Stephan Bosch <stephan@rename-it.nl> (4f55d83f) + + lib-sieve: Improved handling of stream errors in lexical scannner. + + +M src/lib-sieve/sieve-lexer.c + +2014-10-19 09:37:48 +0200 Stephan Bosch <stephan@rename-it.nl> (3b4e4daa) + + lib-sieve: Removed implicitly resolved FIXME. + + +M src/lib-sieve/sieve-actions.c + +2014-10-19 09:34:03 +0200 Stephan Bosch <stephan@rename-it.nl> (83175c96) + + managesieve: Fixed handling of o_stream_send_istream() errors during + GETSCRIPT command. + + +M src/managesieve/cmd-getscript.c + +2014-10-19 01:02:02 +0200 Stephan Bosch <stephan@rename-it.nl> (617dcd99) + + lib-sieve: Improved (temporary) error handling from mail storage and io + streams. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/duplicate/tst-duplicate.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.h +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/tst-exists.c +M src/plugins/sieve-extprograms/cmd-execute.c +M src/plugins/sieve-extprograms/cmd-filter.c +M src/plugins/sieve-extprograms/cmd-pipe.c + +2014-10-17 21:07:36 +0200 Stephan Bosch <stephan@rename-it.nl> (6211d99e) + + lib-sieve: Flush duplicate database before committing storage transactions. + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-types.h +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2014-10-17 20:49:57 +0200 Stephan Bosch <stephan@rename-it.nl> (94c1a2b6) + + lib-sieve: Restructured result execution, so that all actions which involve + mail storage are always committed before all others. + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c + +2014-10-15 00:23:55 +0200 Stephan Bosch <stephan@rename-it.nl> (908467a2) + + lib-sieve: Implemented sieve_redirect_envelope_from setting, which allows + configuring the envelope sender of redirected messages. Can either be set to + the envelope sender, recipient, or orignal recipient of the processed + message or it can be set explicitly to a static address. + + +M INSTALL +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve.c +M src/testsuite/cmd-test-config.c +M tests/execute/smtp.svtest + +2014-10-14 03:22:23 +0200 Stephan Bosch <stephan@rename-it.nl> (ffdbb1f0) + + lib-sieve: mailbox extension: The `:create' tag erroneously subscribed an + existing folder. It should only subscribe it when it is newly created. + + +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c + +2014-10-11 01:33:15 +0200 Stephan Bosch <stephan@rename-it.nl> (002ca395) + + LDA Sieve plugin: Fixed handling of temporary SMTP errors. These caused a + BUG error to be reported during delivery. Solved by signalling the + occurrence of storage errors as a separate execution status flag, rather + than querying the last storage itself for errors, which won't work. + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-types.h +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2014-10-11 00:44:27 +0200 Stephan Bosch <stephan@rename-it.nl> (00d27ba0) + + Removed useless mail-storage includes. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/duplicate/tst-duplicate.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/storage/file/sieve-file-storage.h +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-size.c +M src/testsuite/cmd-test-message.c +M src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite-smtp.c + +2014-10-11 00:42:39 +0200 Stephan Bosch <stephan@rename-it.nl> (ce5d301c) + + lib-sieve: Omitted handling errors from mail_get_headers() in message header + stringlist. Mail storage errors now trigger a runtime error. + + +M src/lib-sieve/sieve-message.c + +2014-10-08 00:32:28 +0200 Stephan Bosch <stephan@rename-it.nl> (f1bfb896) + + lib-sieve: Addressed race condition writing to user error log file. + + +M src/lib-sieve/sieve-error.c + +2014-10-07 23:12:20 +0200 Stephan Bosch <stephan@rename-it.nl> (eb775e8a) + + lib-sieve-tool: Simplified seekable stream callback for raw mail. No longer + needed to create the temp directory. + + +M src/lib-sieve-tool/mail-raw.c + +2014-09-12 12:17:38 +0200 Stephan Bosch <stephan@rename-it.nl> (72563215) + + lib-sieve: duplicate extension: Fixed erroneous compile error about + conflicting tags when ":handle" argument was used last. + + +M src/lib-sieve/plugins/duplicate/tst-duplicate.c + +2014-09-05 14:38:35 +0200 Stephan Bosch <stephan@rename-it.nl> (ccf79840) + + Valgrindn needs --trace-children to work properly these days. + + +M Makefile.am + +2014-08-28 15:38:39 +0200 Stephan Bosch <stephan@rename-it.nl> (2aea3112) + + doveadm sieve plugin: Fixed segfault occuring when main script storage does + not support synchronization. Would occur with any other script storage + intialization error as well. + + +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2014-08-28 11:34:37 +0200 Stephan Bosch <stephan@rename-it.nl> (08676552) + + Doveadm Sieve plugin: Attempting synchronization with LDAP/DICT caused write + access error. If the main script storage does not allow synchronization, it + is now just logged as a debug message. + + +M src/lib-sieve/sieve-storage-sync.c +M src/lib-sieve/sieve-storage.c + +2014-08-27 00:19:40 +0200 Stephan Bosch <stephan@rename-it.nl> (cac0ac7a) + + Fixed handling of SMTP errors. Logging was mixed up; it logged permanent + SMTP failures as errors rather than mere info. Redirect now handles + temporary failure as a separate error condition, causing LDA to return a + temporary failure if no other (storage) actions were performed. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c + +2014-08-24 00:27:40 +0200 Stephan Bosch <stephan@rename-it.nl> (2df6d4b5) + + lib-sieve: Added version to script storage class. Updated binary version. + + +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-storage-private.h +M src/lib-sieve/storage/dict/sieve-dict-storage.c +M src/lib-sieve/storage/file/sieve-file-storage.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.c + +2014-08-23 22:52:30 +0200 Stephan Bosch <stephan@rename-it.nl> (0de1dadc) + + Added support for Japanese mail addresses with dots at non-standard places + in localpart. Based on patch by Timo Sirainen. + + +M src/lib-sieve/sieve-address.c +M tests/compile/errors/out-address.sieve +M tests/extensions/envelope.svtest + +2014-08-23 21:16:34 +0200 Stephan Bosch <stephan@rename-it.nl> (f4677eca) + + Changed handling of ENOSPACE to a normal temporary failure and added + handling of ENOQUOTA as a user error. Patch by Timo Sirainen. + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-types.h +M src/lib-sieve/storage/file/sieve-file-storage-save.c +M src/managesieve/managesieve-client.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2014-08-23 21:11:54 +0200 Stephan Bosch <stephan@rename-it.nl> (9f8863d3) + + lib-sieve: file storage: Warning about active script not being a symlink was + triggered at inappropriate times. Fixed by issueing the warning only when + storage is opened as READWRITE (ManageSieve). + + +M src/lib-sieve/storage/file/sieve-file-storage-active.c + +2014-08-05 18:25:12 +0200 Stephan Bosch <stephan@rename-it.nl> (9e6b63f8) + + lib-sieve: editheader extension: Fixed several problems in deleteheader + command. + + +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/util/edit-mail.c +M tests/extensions/editheader/deleteheader.svtest + +2014-08-05 03:55:56 +0200 Stephan Bosch <stephan@rename-it.nl> (c4575f2e) + + lib-sieve: file storage: Fixed assert failure in script sequence code. + Single script was only initialized and not actually opened. + + +M src/lib-sieve/storage/file/sieve-file-script-sequence.c +M src/lib-sieve/storage/file/sieve-file-script.c +M src/lib-sieve/storage/file/sieve-file-storage.h + +2014-08-05 03:47:36 +0200 Stephan Bosch <stephan@rename-it.nl> (5e42bce1) + + lib-sieve: file storage: Fixed segfault bug in script sequence code. + + +M src/lib-sieve/storage/file/sieve-file-script-sequence.c + +2014-07-31 02:17:50 +0200 Stephan Bosch <stephan@rename-it.nl> (2006f4cb) + + lib-sieve: util: edit-mail: Fixed a few bugs in previous commit. + + +M src/lib-sieve/util/edit-mail.c + +2014-07-31 01:37:22 +0200 Stephan Bosch <stephan@rename-it.nl> (c85782ca) + + lib-sieve: util: edit-mail: Added header replacement API. + + +M src/lib-sieve/util/edit-mail.c +M src/lib-sieve/util/edit-mail.h + +2014-07-30 19:57:17 +0200 Stephan Bosch <stephan@rename-it.nl> (8fa71536) + + lib-sieve: mailbox extension: Made :create tag available for new commands. + + +M src/lib-sieve/plugins/mailbox/Makefile.am +M src/lib-sieve/plugins/mailbox/ext-mailbox-common.h +M src/lib-sieve/plugins/mailbox/ext-mailbox.c +A src/lib-sieve/plugins/mailbox/sieve-ext-mailbox.h +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c + +2014-07-30 13:50:48 +0200 Stephan Bosch <stephan@rename-it.nl> (4e8120b9) + + lib-sieve: variables extension: Added API for assigning cstrings to + variables. + + +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2014-07-30 13:50:12 +0200 Stephan Bosch <stephan@rename-it.nl> (e6074922) + + lib-sieve: Fixed problem in validator extension handling. The validate hook + only worked for one extension. + + +M src/lib-sieve/sieve-validator.c + +2014-07-30 13:49:24 +0200 Stephan Bosch <stephan@rename-it.nl> (2432a185) + + lib-sieve: Made binary code functions capable of skipping data. + + +M src/lib-sieve/sieve-binary-code.c +M src/lib-sieve/sieve-binary.h + +2014-07-30 00:15:08 +0200 Stephan Bosch <stephan@rename-it.nl> (fecb8e43) + + lib-sieve: Restructured native extension declarations a bit. + + +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/sieve-extensions.c + +2014-07-29 01:34:25 +0200 Stephan Bosch <stephan@rename-it.nl> (c92959ec) + + doveadm sieve plugin: Fixed segfault issue caused in lib-sieve. Erroneously + set pointer to NULL in sieve_storage_list_deinit(). + + +M src/lib-sieve/sieve-storage.c + +2014-07-28 09:27:59 +0200 Stephan Bosch <stephan@rename-it.nl> (71a92bec) + + lib-sieve: ldap storage: Fixed --with-ldap=no compile. + + +M src/lib-sieve/storage/ldap/sieve-ldap-db.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.h + +2014-07-26 01:17:51 +0200 Stephan Bosch <stephan@rename-it.nl> (ce342b01) + + lib-sieve: ldap storage: Implemented checking config mtime for binary + recompile. + + +M src/lib-sieve/storage/ldap/sieve-ldap-script.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage-settings.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.h + +2014-07-26 00:47:29 +0200 Stephan Bosch <stephan@rename-it.nl> (1e515e44) + + Forgot to remove a few files in earlier lib-sieve/storage change. + + +D src/lib-sieve/sieve-script-dict.c +D src/lib-sieve/sieve-script-file.c + +2014-07-26 00:46:26 +0200 Stephan Bosch <stephan@rename-it.nl> (321dde03) + + Fixed compile problem reported by OpenSUSE build service. + + +M src/lib-sieve/storage/file/sieve-file-script-sequence.c +M src/lib-sieve/storage/file/sieve-file-script.c +M src/lib-sieve/storage/file/sieve-file-storage-active.c +M src/lib-sieve/storage/file/sieve-file-storage-list.c +M src/lib-sieve/storage/file/sieve-file-storage-quota.c +M src/lib-sieve/storage/file/sieve-file-storage-save.c +M src/lib-sieve/storage/file/sieve-file-storage.c +M src/lib-sieve/storage/file/sieve-file-storage.h + +2014-07-25 15:59:40 +0200 Stephan Bosch <stephan@rename-it.nl> (19dd4638) + + lda-sieve plugin: Dereferenced default script storage at wrong nesting + level, causing an assert failure. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2014-07-24 15:21:29 +0200 Stephan Bosch <stephan@rename-it.nl> (bace39ec) + + lib-sieve: file storage: Erroneously always ignored active script setting. + + +M src/lib-sieve/sieve-storage.c +M src/lib-sieve/storage/file/sieve-file-storage.c + +2014-07-24 15:20:47 +0200 Stephan Bosch <stephan@rename-it.nl> (e25a71e4) + + lib-sieve: file storage: Don't tempfail on missing active script. + + +M src/lib-sieve/storage/file/sieve-file-storage-active.c + +2014-07-24 12:53:51 +0200 Stephan Bosch <stephan@rename-it.nl> (a1d29d31) + + Fixed moduledir for Sieve plugins. + + +M src/lib-sieve/storage/ldap/Makefile.am +M src/plugins/sieve-extprograms/Makefile.am + +2014-07-24 09:27:14 +0200 Stephan Bosch <stephan@rename-it.nl> (85980973) + + Adjusted documentation to mention LDAP support can be compiled as a plugin. + + +M INSTALL +M doc/script-location-ldap.txt + +2014-07-24 09:17:07 +0200 Stephan Bosch <stephan@rename-it.nl> (2a049da8) + + lib-sieve: Fixed LDAP storage compiled as a plugin. + + +M src/lib-sieve/storage/ldap/sieve-ldap-storage.c +M src/lib-sieve/storage/ldap/sieve-ldap-storage.h + +2014-07-24 02:05:28 +0200 Stephan Bosch <stephan@rename-it.nl> (343c5793) + + lib-sieve: Made LDAP plugin compile properly. LDAP storage as a plugin is + still not problem-free though. + + +M src/lib-sieve/storage/ldap/Makefile.am +M src/lib-sieve/storage/ldap/sieve-ldap-storage.c + +2014-07-24 02:04:47 +0200 Stephan Bosch <stephan@rename-it.nl> (a86e3fd8) + + lib-sieve: Fixed file storage sequence implementation. Directory iteration + was very broken. + + +M src/lib-sieve/storage/file/sieve-file-script-sequence.c +M src/lib-sieve/storage/file/sieve-file-script.c + +2014-07-23 19:36:00 +0200 Stephan Bosch <stephan@rename-it.nl> (593b91e5) + + lib-sieve: Created sieve LDAP storage driver. + + +M INSTALL +M TODO +M configure.ac +M doc/example-config/conf.d/90-sieve.conf +A doc/example-config/sieve-ldap.conf +A doc/script-location-ldap.txt +M pigeonhole-config.h.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/sieve-storage.c +M src/lib-sieve/storage/Makefile.am +A src/lib-sieve/storage/ldap/Makefile.am +A src/lib-sieve/storage/ldap/sieve-ldap-db.c +A src/lib-sieve/storage/ldap/sieve-ldap-db.h +A src/lib-sieve/storage/ldap/sieve-ldap-script.c +A src/lib-sieve/storage/ldap/sieve-ldap-storage-settings.c +A src/lib-sieve/storage/ldap/sieve-ldap-storage.c +A src/lib-sieve/storage/ldap/sieve-ldap-storage.h + +2014-07-23 19:28:07 +0200 Stephan Bosch <stephan@rename-it.nl> (5a8c6b89) + + lib-sieve: Implemented support for generic Sieve storages. Doveadm-sieve + plugin may be broken at this point; not tested so far. + + +M TODO +M configure.ac +M src/Makefile.am +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-script-dict.c +D src/lib-sieve/sieve-script-file.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +A src/lib-sieve/sieve-storage-private.h +A src/lib-sieve/sieve-storage-sync.c +A src/lib-sieve/sieve-storage.c +A src/lib-sieve/sieve-storage.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +A src/lib-sieve/storage/Makefile.am +A src/lib-sieve/storage/dict/Makefile.am +A src/lib-sieve/storage/dict/sieve-dict-script.c +A src/lib-sieve/storage/dict/sieve-dict-storage.c +A src/lib-sieve/storage/dict/sieve-dict-storage.h +A src/lib-sieve/storage/file/Makefile.am +A src/lib-sieve/storage/file/sieve-file-script-sequence.c +A src/lib-sieve/storage/file/sieve-file-script.c +A src/lib-sieve/storage/file/sieve-file-storage-active.c +A src/lib-sieve/storage/file/sieve-file-storage-list.c +R054 src/lib-sievestorage/sieve-storage-quota.c src/lib-sieve/storage/file/sieve-file-storage-quota.c +A src/lib-sieve/storage/file/sieve-file-storage-save.c +A src/lib-sieve/storage/file/sieve-file-storage.c +A src/lib-sieve/storage/file/sieve-file-storage.h +D src/lib-sievestorage/Makefile.am +D src/lib-sievestorage/sieve-storage-list.c +D src/lib-sievestorage/sieve-storage-list.h +D src/lib-sievestorage/sieve-storage-private.h +D src/lib-sievestorage/sieve-storage-quota.h +D src/lib-sievestorage/sieve-storage-save.c +D src/lib-sievestorage/sieve-storage-save.h +D src/lib-sievestorage/sieve-storage-script.c +D src/lib-sievestorage/sieve-storage-script.h +D src/lib-sievestorage/sieve-storage.c +D src/lib-sievestorage/sieve-storage.h +M src/managesieve/Makefile.am +M src/managesieve/cmd-deletescript.c +M src/managesieve/cmd-getscript.c +M src/managesieve/cmd-havespace.c +M src/managesieve/cmd-listscripts.c +M src/managesieve/cmd-putscript.c +M src/managesieve/cmd-renamescript.c +M src/managesieve/cmd-setactive.c +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-quota.c +M src/plugins/Makefile.am +M src/plugins/doveadm-sieve/Makefile.am +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sievec.c +M src/testsuite/testsuite-binary.c +M src/testsuite/testsuite-script.c +M tests/extensions/include/execute.svtest + +2014-06-26 23:25:43 +0200 Stephan Bosch <stephan@rename-it.nl> (4ae41e1d) + + doveadm sieve plugin: Fixed assert crash occuring when Sieve script + attribute assignment fails. + + +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2014-06-19 00:10:53 +0200 Stephan Bosch <stephan@rename-it.nl> (8a7cecee) + + managesieve: Compared to imap and incorporated a few differences from there. + Most important change is that mail service_user was not freed. + + +M src/managesieve/main.c +M src/managesieve/managesieve-client.c + +2014-06-18 00:08:03 +0200 Stephan Bosch <stephan@rename-it.nl> (38732434) + + Some ATTR_FORMAT additions by Timo. + + +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.h + +2014-06-17 23:43:10 +0200 Stephan Bosch <stephan@rename-it.nl> (975707d3) + + lib-sieve: program client: Fixed copy-paste error in destroy function. Would + cause a segfault. Reported by Coverity. + + +M src/lib-sieve/util/program-client.c + +2014-06-17 23:37:46 +0200 Stephan Bosch <stephan@rename-it.nl> (53940810) + + lib-sieve: edit mail: Fixed header iteration. Handling of + edit_mail_header_find() result was incoherent. Problem reported by Coverity. + + +M src/lib-sieve/util/edit-mail.c + +2014-06-17 23:28:53 +0200 Stephan Bosch <stephan@rename-it.nl> (a3c55d8c) + + sieve extprograms plugin: Fixed dead code problems. Reported by Coverity. + + +M src/plugins/sieve-extprograms/cmd-execute.c +M src/plugins/sieve-extprograms/cmd-pipe.c + +2014-06-17 23:19:37 +0200 Stephan Bosch <stephan@rename-it.nl> (840ce64b) + + lib-sieve: relational extension: Fixed error handling of :value match. + Switch statement item is never reached and return value was bool instead of + int. Problem reported by Coverity. + + +M src/lib-sieve/plugins/relational/mcht-value.c + +2014-06-17 23:04:24 +0200 Stephan Bosch <stephan@rename-it.nl> (19b4dee4) + + lib-sievestorage: Fixed file path comparison function. Forgot a few '*' + there. Reported by Coverity. + + +M src/lib-sievestorage/sieve-storage-script.c + +2014-06-17 22:52:32 +0200 Stephan Bosch <stephan@rename-it.nl> (2d78f622) + + lib-sieve: edit mail: Fixed header unfolding. Forgot break in switch + statement. Reported by Coverity. + + +M src/lib-sieve/util/edit-mail.c + +2014-06-17 22:45:23 +0200 Stephan Bosch <stephan@rename-it.nl> (1dc9b818) + + lib-sieve: program client: Forgot break in switch statement for handling of + response from script service. Reported by Coverity. + + +M src/lib-sieve/util/program-client-remote.c + +2014-06-17 22:38:12 +0200 Stephan Bosch <stephan@rename-it.nl> (543c10a8) + + testsuite: Fixed out-of-bounds read in (currently unused) string + substitution implementation. Reported by Coverity. + + +M src/testsuite/testsuite-substitutions.c + +2014-06-17 22:28:06 +0200 Stephan Bosch <stephan@rename-it.nl> (511700be) + + sieve-storage: Fixed resource leak in storage listing implementation + occuring at error. Reported by Coverity. + + +M src/lib-sievestorage/sieve-storage-list.c + +2014-06-17 22:13:52 +0200 Stephan Bosch <stephan@rename-it.nl> (62313f89) + + Use the new [io]_stream_create_fd_*autoclose() functions wherever possible. + Parallel to identical Dovecot change. + + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/sieve-script-file.c +M src/lib-sieve/sieve-script-private.h +M src/testsuite/testsuite-smtp.c + +2014-06-17 20:58:23 +0200 Stephan Bosch <stephan@rename-it.nl> (7b7a9e09) + + managesieve: Remove the client from clients-list at the very end of the + destroy function. Parallel to identical Dovecot change for imap and pop3. + + +M src/managesieve/managesieve-client.c + +2014-06-17 20:48:50 +0200 Stephan Bosch <stephan@rename-it.nl> (7719fc03) + + lib-sieve: code dumper: Fixed handling of undefined extensions. Reported by + Coverity. + + +M src/lib-sieve/sieve-code-dumper.c + +2014-06-17 20:44:47 +0200 Stephan Bosch <stephan@rename-it.nl> (a14ee75d) + + lib-sieve: Small change in Sieve generator to make static analyzer happier. + Reported by Coverity. + + +M src/lib-sieve/sieve-generator.c + +2014-06-17 20:41:53 +0200 Stephan Bosch <stephan@rename-it.nl> (d9cbd268) + + doveadm sieve plugin: Fixed dereference before NULL check problem. Found by + Coverity. + + +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2014-06-17 20:35:18 +0200 Stephan Bosch <stephan@rename-it.nl> (b928bbd9) + + lib: pair VA_COPY with va_end. A va_copy creates a initialised va_list, as + if a va_start had been done on it. Therefore, pedantically, a va_end should + also be done on it. On most platforms this is a no-op, and for those where + it isn't, the pairing is important. + + This change matches parallel change in Dovecot. Also signalled by Coverity. + +M src/lib-sieve/sieve-error.c +M src/testsuite/testsuite-log.c + +2014-05-15 19:48:27 +0200 Stephan Bosch <stephan@rename-it.nl> (c71c21d9) + + Fixed several problems reported by CLang 3.4. + + +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve.c +M src/lib-sieve/util/edit-mail.c +M src/testsuite/testsuite-script.c + +2014-05-12 21:27:13 +0200 Stephan Bosch <stephan@rename-it.nl> (8d984203) + + Wrong date in NEWS. + + +M NEWS + +2014-05-12 21:14:44 +0200 Stephan Bosch <stephan@rename-it.nl> (25c38e42) + + Added signature for changeset 1c6130ff5dd6 + + +M .hgsigs + +2014-05-12 21:12:34 +0200 Stephan Bosch <stephan@rename-it.nl> (fb6b23fe) + + Added tag 0.4.3 for changeset 1c6130ff5dd6 + + +2014-05-12 21:12:24 +0200 Stephan Bosch <stephan@rename-it.nl> (84dde15e) + + Released v0.4.3 for Dovecot v2.2.13. + + +M NEWS +M configure.ac + +2014-05-12 20:40:39 +0200 Stephan Bosch <stephan@rename-it.nl> (d2206ede) + + lib-sieve: sieve-error.c: Made static analyzer happier. + + +M src/lib-sieve/sieve-error.c + +2014-05-12 20:22:30 +0200 Stephan Bosch <stephan@rename-it.nl> (45db1c22) + + lib-sieve: include extension: Fixed problem with handling of duplicate + includes. Flags weren't actually updated. + + +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c + +2014-05-09 08:55:02 +0200 Stephan Bosch <stephan@rename-it.nl> (15e090d6) + + testsuite: editheader: Made test failure messages a bit more verbose. + + +M tests/extensions/editheader/addheader.svtest + +2014-05-09 01:32:52 +0200 Stephan Bosch <stephan@rename-it.nl> (e2abf9e2) + + lib-sieve: redirect: Adjusted loop detection to show leniency to resent + messages. + + +M src/lib-sieve/cmd-redirect.c + +2014-05-08 21:23:24 +0200 Stephan Bosch <stephan@rename-it.nl> (1bbbe727) + + lib-sieve: program-client: Made sure that programs are never forked with + root privileges. + + +M src/lib-sieve/util/program-client-local.c +M src/lib-sieve/util/program-client.h +M src/plugins/sieve-extprograms/sieve-extprograms-common.c + +2014-05-07 21:17:43 +0200 Stephan Bosch <stephan@rename-it.nl> (2ad87784) + + lib-sieve: editheader: Made control characters allowed for editheader, + except NUL. NOTE: Dovecot doesn't currently MIME-encode these in the + headers. + + +M src/lib-sieve/plugins/editheader/cmd-addheader.c +M tests/extensions/editheader/addheader.svtest +M tests/extensions/editheader/errors.svtest +M tests/extensions/editheader/errors/field-value.sieve + +2014-05-07 20:15:07 +0200 Stephan Bosch <stephan@rename-it.nl> (0683c506) + + lib-sieve: Fixed indenting problem in runtime trace output. Also cleaned up + the surrounding code a bit. + + +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h + +2014-05-07 20:03:10 +0200 Stephan Bosch <stephan@rename-it.nl> (b4ab2e7c) + + lib-sieve: Added final result execution stage for the duplicate extension. + This way, a duplicate is only marked when the script execution succeeds, as + required in the specification. + + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/duplicate/ext-duplicate-common.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c +M src/plugins/sieve-extprograms/cmd-pipe.c + +2014-05-05 17:09:10 +0200 Stephan Bosch <stephan@rename-it.nl> (b3dccbd0) + + lib-sieve: vacation extension: Fixed log message for discarded response. + Presence of :addresses argument was represented incorrectly. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2014-05-01 00:07:27 +0200 Stephan Bosch <stephan@rename-it.nl> (ee69b175) + + lib-sieve: editheader: Adjusted to change in Dovecot lib-storage mail API. + + +M src/lib-sieve/util/edit-mail.c + +2014-04-29 02:13:35 +0200 Stephan Bosch <stephan@rename-it.nl> (923b1b94) + + lib-sieve: Adjusted to more SMTP API changes in Dovecot. SMTP API now + supports adding multiple recipients to a single SMTP transaction. This makes + enotify/notify more efficient, since only one message is actually sent. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-smtp.c +M src/lib-sieve/sieve-smtp.h +M src/lib-sieve/sieve-types.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite.c +M tests/deprecated/notify/mailto.svtest + +2014-04-28 22:08:47 +0200 Stephan Bosch <stephan@rename-it.nl> (5dc50ad9) + + lib-sieve: Switched to new Dovecot SMTP API. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-smtp.c +M src/lib-sieve/sieve-smtp.h +M src/lib-sieve/sieve-types.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h + +2014-04-25 23:53:40 +0200 Stephan Bosch <stephan@rename-it.nl> (ba7aff60) + + lib-sieve: Fixed sieve_result_global_log_error to log only as i_info in + administrator log (syslog) if executed from multiscript context. Previously, + this would work correcly only from the user's personal script and not from + multiscript (sieve_before/sieve_after). + + +M src/lib-sieve/sieve-error.c + +2014-04-15 23:11:46 +0200 Stephan Bosch <stephan@rename-it.nl> (793ee9b0) + + Dovecot change: Replaced mail_get_real_mail() with mail_get_backend_mail(). + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/util/edit-mail.c + +2014-03-04 22:28:56 +0100 Stephan Bosch <stephan@rename-it.nl> (f5505c87) + + lib-sieve: Upgraded "vnd.dovecot.duplicate" to "duplicate". Backwards + compatibility is provided for vnd.dovecot.duplicate. Still need to fix the + constraint that it must not track duplicates from failed Sieve executions. + + +M Makefile.am +M README +M configure.ac +A doc/extensions/duplicate.txt +D doc/extensions/vnd.dovecot.duplicate.txt +A doc/rfc/draft-ietf-appsawg-sieve-duplicate-03.txt +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +R092 src/lib-sieve/plugins/vnd.dovecot/duplicate/Makefile.am src/lib-sieve/plugins/duplicate/Makefile.am +R077 src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate-common.c src/lib-sieve/plugins/duplicate/ext-duplicate-common.c +R085 src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate-common.h src/lib-sieve/plugins/duplicate/ext-duplicate-common.h +A src/lib-sieve/plugins/duplicate/ext-duplicate.c +R073 src/lib-sieve/plugins/vnd.dovecot/duplicate/tst-duplicate.c src/lib-sieve/plugins/duplicate/tst-duplicate.c +M src/lib-sieve/plugins/vnd.dovecot/Makefile.am +M src/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug-common.h +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c +D src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate.c +M src/lib-sieve/sieve-extensions.c +M src/plugins/sieve-extprograms/cmd-execute.c +M src/plugins/sieve-extprograms/cmd-filter.c +M src/plugins/sieve-extprograms/cmd-pipe.c +M src/plugins/sieve-extprograms/ext-execute.c +M src/plugins/sieve-extprograms/ext-filter.c +M src/plugins/sieve-extprograms/ext-pipe.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.h +M src/plugins/sieve-extprograms/sieve-extprograms-plugin.c +A tests/extensions/duplicate/errors.svtest +A tests/extensions/duplicate/errors/conflict-vnd.sieve +A tests/extensions/duplicate/errors/conflict.sieve +R100 tests/extensions/vnd.dovecot/duplicate/errors/syntax.sieve tests/extensions/duplicate/errors/syntax-vnd.sieve +A tests/extensions/duplicate/errors/syntax.sieve +R100 tests/extensions/vnd.dovecot/duplicate/execute.svtest tests/extensions/duplicate/execute-vnd.svtest +A tests/extensions/duplicate/execute.svtest +D tests/extensions/vnd.dovecot/duplicate/errors.svtest + +2014-02-25 00:49:08 +0100 Stephan Bosch <stephan@rename-it.nl> (fdcfea49) + + lib-sieve: program-client: Removed stale assert. + + +M src/lib-sieve/util/program-client-local.c + +2014-01-12 23:23:50 +0100 Stephan Bosch <stephan@rename-it.nl> (c167b196) + + Prevent compiled binaries in testsuite from ending up in distribution + tarball. + + +M Makefile.am + +2014-01-07 18:57:38 +0100 Stephan Bosch <stephan@rename-it.nl> (0172e14c) + + lib-sieve: Changed sieve_script_binary_get_directory() to + sieve_script_binary_get_prefix(). This function now returns the binary + prefix (file path until '.svbin) rather than just the path of the directory + where the binary would be stored. + + +M src/lib-sieve/sieve-script-file.c +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h + +2014-01-07 18:54:57 +0100 Stephan Bosch <stephan@rename-it.nl> (37dc5b60) + + lda-sieve plugin: Changed name of main script. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2014-01-05 11:16:25 +0100 Stephan Bosch <stephan@rename-it.nl> (a20f038b) + + Fixed Valgrind in testsuite using libtool --mode=execute. + + +M Makefile.am + +2014-01-05 11:15:45 +0100 Stephan Bosch <stephan@rename-it.nl> (690c4483) + + lib-sieve/util: Fixed small memory leak in program client. + + +M src/lib-sieve/util/program-client-local.c + +2014-01-05 10:40:38 +0100 Stephan Bosch <stephan@rename-it.nl> (4021b059) + + Adjusted dovecot.m4 to make second-level plugin packages work properly at + distcheck. + + +M m4/dovecot.m4 + +2014-01-04 02:13:44 +0100 Stephan Bosch <stephan@rename-it.nl> (5e7bf46c) + + lib-sieve/util: program-client: Added support for retrieving side-channel + data through extra fds. Some programs can be instructed to output special + status information to an extra fd other than stdout or stderr. Also added an + option to drop stderr output from program to /dev/null. + + +M src/lib-sieve/util/program-client-local.c +M src/lib-sieve/util/program-client-private.h +M src/lib-sieve/util/program-client-remote.c +M src/lib-sieve/util/program-client.c +M src/lib-sieve/util/program-client.h + +2014-01-01 23:58:16 +0100 Stephan Bosch <stephan@rename-it.nl> (0fc64c0e) + + Updated copyright notices to include the year 2014. + + +M doc/man/pigeonhole.7.in +M doc/man/sieve-dump.1.in +M doc/man/sieve-filter.1.in +M doc/man/sieve-test.1.in +M doc/man/sievec.1.in +M src/lib-managesieve/managesieve-arg.c +M src/lib-managesieve/managesieve-arg.h +M src/lib-managesieve/managesieve-parser.c +M src/lib-managesieve/managesieve-parser.h +M src/lib-managesieve/managesieve-quote.c +M src/lib-managesieve/managesieve-quote.h +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/mail-raw.h +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/cmp-i-ascii-casemap.c +M src/lib-sieve/cmp-i-octet.c +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/copy/sieve-ext-copy.h +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/ext-date-common.h +M src/lib-sieve/plugins/date/ext-date.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/editheader/cmd-addheader.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.h +M src/lib-sieve/plugins/editheader/ext-editheader-limits.h +M src/lib-sieve/plugins/editheader/ext-editheader.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify-limits.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.h +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/environment/ext-environment-common.h +M src/lib-sieve/plugins/environment/ext-environment.c +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/ihave/cmd-error.c +M src/lib-sieve/plugins/ihave/ext-ihave-binary.c +M src/lib-sieve/plugins/ihave/ext-ihave-binary.h +M src/lib-sieve/plugins/ihave/ext-ihave-common.c +M src/lib-sieve/plugins/ihave/ext-ihave-common.h +M src/lib-sieve/plugins/ihave/ext-ihave.c +M src/lib-sieve/plugins/ihave/tst-ihave.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-limits.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/mailbox/ext-mailbox-common.h +M src/lib-sieve/plugins/mailbox/ext-mailbox.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/metadata/ext-metadata-common.h +M src/lib-sieve/plugins/metadata/ext-metadata.c +M src/lib-sieve/plugins/metadata/tst-metadata.c +M src/lib-sieve/plugins/metadata/tst-metadataexists.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.h +M src/lib-sieve/plugins/notify/ext-notify-limits.h +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/plugins/regex/ext-regex-common.c +M src/lib-sieve/plugins/regex/ext-regex-common.h +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/lib-sieve/plugins/vacation/ext-vacation-seconds.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.h +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables-dump.h +M src/lib-sieve/plugins/variables/ext-variables-limits.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-name.c +M src/lib-sieve/plugins/variables/ext-variables-name.h +M src/lib-sieve/plugins/variables/ext-variables-namespaces.c +M src/lib-sieve/plugins/variables/ext-variables-namespaces.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug-common.h +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c +M src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate-common.c +M src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate-common.h +M src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate.c +M src/lib-sieve/plugins/vnd.dovecot/duplicate/tst-duplicate.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary-code.c +M src/lib-sieve/sieve-binary-debug.c +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-objects.c +M src/lib-sieve/sieve-objects.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-plugins.c +M src/lib-sieve/sieve-plugins.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-runtime-trace.c +M src/lib-sieve/sieve-runtime-trace.h +M src/lib-sieve/sieve-runtime.h +M src/lib-sieve/sieve-script-dict.c +M src/lib-sieve/sieve-script-file.c +M src/lib-sieve/sieve-script-file.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve-smtp.c +M src/lib-sieve/sieve-smtp.h +M src/lib-sieve/sieve-stringlist.c +M src/lib-sieve/sieve-stringlist.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c +M src/lib-sieve/tst-truefalse.c +M src/lib-sieve/util/edit-mail.c +M src/lib-sieve/util/edit-mail.h +M src/lib-sieve/util/program-client-local.c +M src/lib-sieve/util/program-client-private.h +M src/lib-sieve/util/program-client-remote.c +M src/lib-sieve/util/program-client.c +M src/lib-sieve/util/program-client.h +M src/lib-sieve/util/rfc2822.c +M src/lib-sieve/util/rfc2822.h +M src/lib-sievestorage/sieve-storage-list.c +M src/lib-sievestorage/sieve-storage-list.h +M src/lib-sievestorage/sieve-storage-private.h +M src/lib-sievestorage/sieve-storage-quota.c +M src/lib-sievestorage/sieve-storage-quota.h +M src/lib-sievestorage/sieve-storage-save.c +M src/lib-sievestorage/sieve-storage-save.h +M src/lib-sievestorage/sieve-storage-script.c +M src/lib-sievestorage/sieve-storage-script.h +M src/lib-sievestorage/sieve-storage.c +M src/lib-sievestorage/sieve-storage.h +M src/managesieve-login/client-authenticate.c +M src/managesieve-login/client-authenticate.h +M src/managesieve-login/client.c +M src/managesieve-login/client.h +M src/managesieve-login/managesieve-login-settings-plugin.c +M src/managesieve-login/managesieve-login-settings-plugin.h +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve-login/managesieve-login-settings.h +M src/managesieve-login/managesieve-proxy.c +M src/managesieve-login/managesieve-proxy.h +M src/managesieve/cmd-capability.c +M src/managesieve/cmd-deletescript.c +M src/managesieve/cmd-getscript.c +M src/managesieve/cmd-havespace.c +M src/managesieve/cmd-listscripts.c +M src/managesieve/cmd-logout.c +M src/managesieve/cmd-noop.c +M src/managesieve/cmd-putscript.c +M src/managesieve/cmd-renamescript.c +M src/managesieve/cmd-setactive.c +M src/managesieve/main.c +M src/managesieve/managesieve-capabilities.c +M src/managesieve/managesieve-capabilities.h +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h +M src/managesieve/managesieve-commands.c +M src/managesieve/managesieve-commands.h +M src/managesieve/managesieve-common.h +M src/managesieve/managesieve-quota.c +M src/managesieve/managesieve-quota.h +M src/managesieve/managesieve-settings.c +M src/managesieve/managesieve-settings.h +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/plugins/lda-sieve/lda-sieve-plugin.h +M src/plugins/sieve-extprograms/cmd-execute.c +M src/plugins/sieve-extprograms/cmd-filter.c +M src/plugins/sieve-extprograms/cmd-pipe.c +M src/plugins/sieve-extprograms/ext-execute.c +M src/plugins/sieve-extprograms/ext-filter.c +M src/plugins/sieve-extprograms/ext-pipe.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.h +M src/plugins/sieve-extprograms/sieve-extprograms-plugin.c +M src/plugins/sieve-extprograms/sieve-extprograms-plugin.h +M src/sieve-tools/sieve-dump.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-result.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-arguments.c +M src/testsuite/testsuite-arguments.h +M src/testsuite/testsuite-binary.c +M src/testsuite/testsuite-binary.h +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-log.h +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-result.h +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-script.h +M src/testsuite/testsuite-settings.c +M src/testsuite/testsuite-settings.h +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite-substitutions.c +M src/testsuite/testsuite-substitutions.h +M src/testsuite/testsuite-variables.c +M src/testsuite/testsuite-variables.h +M src/testsuite/testsuite.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-action.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c + +2013-12-30 17:54:23 +0100 Stephan Bosch <stephan@rename-it.nl> (41018d2e) + + lib-sieve: Added macros for argument generation errors. + + +M src/lib-sieve/sieve-commands.h + +2013-12-28 09:43:33 +0100 Stephan Bosch <stephan@rename-it.nl> (021a007e) + + Fixed messy documentation indent caused by earlier change. + + +M doc/extensions/spamtest-virustest.txt + +2013-12-28 09:41:24 +0100 Stephan Bosch <stephan@rename-it.nl> (8e67eb94) + + lib-sieve: spamtest/virustest extensions: Tests were erroneously performed + against the original message. When used together with extprograms filter to + add the spam headers, the changes were not being used by the spamtest and + virustest extensions. + + +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +A tests/plugins/extprograms/bin/spamc +M tests/plugins/extprograms/filter/execute.svtest + +2013-12-28 09:24:42 +0100 Stephan Bosch <stephan@rename-it.nl> (b50a4b4f) + + doc/extensions/spamtest-virustest.txt: Clarified that these extensions use + the extended POSIX regular expressions. + + +M doc/extensions/spamtest-virustest.txt + +2013-12-25 21:57:38 +0100 Stephan Bosch <stephan@rename-it.nl> (a9240aba) + + Fixed consistent spelling mistake. + + +M NEWS +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/util/edit-mail.c +M tests/compile/redirect.sieve + +2013-12-25 21:48:15 +0100 Stephan Bosch <stephan@rename-it.nl> (0f0cbe31) + + Fixed compiler warning. + + +M src/lib-sieve/plugins/ihave/ext-ihave-binary.c + +2013-12-25 21:45:47 +0100 Stephan Bosch <stephan@rename-it.nl> (9fba343d) + + sieve_extprograms plugin: Changed program client such that the filter + command only needs to create a temporary file when the program output is + very large. This commit also includes a small change that makes it possible + to run a program several times. + + +M src/lib-sieve/util/program-client-local.c +M src/lib-sieve/util/program-client-private.h +M src/lib-sieve/util/program-client-remote.c +M src/lib-sieve/util/program-client.c +M src/lib-sieve/util/program-client.h +M src/plugins/sieve-extprograms/cmd-filter.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.h + +2013-12-25 21:42:05 +0100 Stephan Bosch <stephan@rename-it.nl> (b0dfde0e) + + lib-sieve: Added post_save hook to binary object. + + +M src/lib-sieve/plugins/ihave/ext-ihave-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary.h + +2013-12-25 21:40:19 +0100 Stephan Bosch <stephan@rename-it.nl> (b59f6ec6) + + lib-sieve: Added method to script object for obtaining the directory where + the script binary is stored. + + +M src/lib-sieve/sieve-script-dict.c +M src/lib-sieve/sieve-script-file.c +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h + +2013-12-25 21:36:55 +0100 Stephan Bosch <stephan@rename-it.nl> (d673f117) + + lib-sieve: Added path to temporary directory to Sieve instance object. + + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2013-12-21 21:32:13 +0100 Stephan Bosch <stephan@rename-it.nl> (160ddddd) + + Moved script-client from extprograms plugin to lib-sieve/util and renamed it + to program-client for generic use. + + +M src/lib-sieve/util/Makefile.am +R058 src/plugins/sieve-extprograms/script-client-local.c src/lib-sieve/util/program-client-local.c +A src/lib-sieve/util/program-client-private.h +R051 src/plugins/sieve-extprograms/script-client-remote.c src/lib-sieve/util/program-client-remote.c +A src/lib-sieve/util/program-client.c +A src/lib-sieve/util/program-client.h +M src/plugins/sieve-extprograms/Makefile.am +D src/plugins/sieve-extprograms/script-client-private.h +D src/plugins/sieve-extprograms/script-client.c +D src/plugins/sieve-extprograms/script-client.h +M src/plugins/sieve-extprograms/sieve-extprograms-common.c + +2013-12-21 21:10:13 +0100 Stephan Bosch <stephan@rename-it.nl> (389457bb) + + lib-sieve: Moved utility source modules to sub-directory. In the future, + much of these can be moved to Dovecot. + + +M configure.ac +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/editheader/Makefile.am +M src/lib-sieve/plugins/enotify/mailto/Makefile.am +M src/lib-sieve/plugins/ihave/Makefile.am +M src/lib-sieve/plugins/metadata/Makefile.am +M src/lib-sieve/plugins/notify/Makefile.am +M src/lib-sieve/plugins/subaddress/Makefile.am +M src/lib-sieve/plugins/vacation/Makefile.am +M src/lib-sieve/plugins/vnd.dovecot/debug/Makefile.am +M src/lib-sieve/plugins/vnd.dovecot/duplicate/Makefile.am +A src/lib-sieve/util/Makefile.am +R100 src/lib-sieve/edit-mail.c src/lib-sieve/util/edit-mail.c +R100 src/lib-sieve/edit-mail.h src/lib-sieve/util/edit-mail.h +R100 src/lib-sieve/rfc2822.c src/lib-sieve/util/rfc2822.c +R100 src/lib-sieve/rfc2822.h src/lib-sieve/util/rfc2822.h + +2013-12-21 15:09:32 +0100 Stephan Bosch <stephan@rename-it.nl> (9c96a4c3) + + Sieve extprograms plugin: Fixed 'Bad filedescriptor' error occurring when + disconnecting script client. + + +M src/plugins/sieve-extprograms/script-client.c + +2013-12-13 21:35:58 +0100 Stephan Bosch <stephan@rename-it.nl> (16e57463) + + Sieve extprograms plugin: Fixed fd leak and handling of output shutdown. + Output stream remained open, including the flush io, causing a second assert + failure. Whether this fixes the problem entirely remains to be seen. + + +M src/plugins/sieve-extprograms/script-client-local.c +M src/plugins/sieve-extprograms/script-client.c + +2013-11-20 19:34:28 +0100 Stephan Bosch <stephan@rename-it.nl> (e556155c) + + Small improvements to the test suite. + + +M tests/test-header.svtest + +2013-11-15 23:13:32 +0100 Stephan Bosch <stephan@rename-it.nl> (ae7d86cd) + + Sieve extprograms plugin: Improved handing of extension configuration. + + +M src/plugins/sieve-extprograms/sieve-extprograms-common.c + +2013-11-11 01:44:19 +0100 Stephan Bosch <stephan@rename-it.nl> (5d3094d7) + + Merged changes from Pigeonhole v0.3 tree. + + +2013-11-11 01:31:08 +0100 Stephan Bosch <stephan@rename-it.nl> (a59a694e) + + lib-sieve: deprecated notify extension: Fixed segfault problems in message + string substitution. + + +M src/lib-sieve/plugins/notify/ext-notify-common.c +M tests/deprecated/notify/basic.svtest + +2013-11-09 11:42:07 +0100 Stephan Bosch <stephan@rename-it.nl> (51fee5e5) + + lib-sievestorage: Fixed active link verification to handle redundant path + slashes correctly. + + +M src/lib-sievestorage/sieve-storage-script.c + +2013-11-03 02:02:56 +0100 Stephan Bosch <stephan@rename-it.nl> (3d455add) + + lib-sieve: Added skeletons for mboxmetadata and servermetadata extensions. + This is still an unfinished feature. + + +M configure.ac +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/metadata/Makefile.am +A src/lib-sieve/plugins/metadata/ext-metadata-common.h +A src/lib-sieve/plugins/metadata/ext-metadata.c +A src/lib-sieve/plugins/metadata/tst-metadata.c +A src/lib-sieve/plugins/metadata/tst-metadataexists.c +M src/lib-sieve/sieve-extensions.c + +2013-10-11 07:57:21 +0200 Stephan Bosch <stephan@rename-it.nl> (b23aa783) + + lib-sieve: vacation extension: Fixed interaction of + sieve_vacation_dont_check_recipient with sieve_vacation_send_from_recipient + setting. If sieve_vacation_dont_check_recipient was active, + sieve_vacation_send_from_recipient had no effect. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2013-10-06 22:14:01 +0200 Stephan Bosch <stephan@rename-it.nl> (5033c8cd) + + Sieve extprograms plugin: Forgot to disable the alarm() timeouts set for + script execution. This may cause later syscalls to exit with EINTR + unexpectedly. + + +M src/plugins/sieve-extprograms/script-client-local.c + +2013-09-26 21:44:37 +0200 Stephan Bosch <stephan@rename-it.nl> (9d606b9f) + + Added signature for changeset 87d8f0aae957 + + +M .hgsigs + +2013-09-26 21:43:09 +0200 Stephan Bosch <stephan@rename-it.nl> (5757a3f0) + + Added signature for changeset 2176d400eca4 + + +M .hgsigs + +2013-09-26 21:41:35 +0200 Stephan Bosch <stephan@rename-it.nl> (fb73bf70) + + Added tag 0.3.6 for changeset 87d8f0aae957 + + +2013-09-26 21:41:24 +0200 Stephan Bosch <stephan@rename-it.nl> (1d852227) + + Released v0.3.6 for Dovecot v2.1.17. + + +M NEWS +M configure.in + +2013-09-26 21:40:34 +0200 Stephan Bosch <stephan@rename-it.nl> (eeeb8cbe) + + Added tag 0.4.2 for changeset 2176d400eca4 + + +2013-09-26 21:40:22 +0200 Stephan Bosch <stephan@rename-it.nl> (a0808437) + + Released v0.4.2 for Dovecot v2.2.6. + + +M NEWS +M configure.ac + +2013-09-23 22:01:38 +0200 Stephan Bosch <stephan@rename-it.nl> (18f75c6b) + + lib-sieve: vacation extension: Added support for sending vacation messages + with an actual sender. Use sieve_vacation_send_from_recipient to enable this + behavior. Documentation in doc/extensions/vacation.txt is updated. + + +M doc/extensions/vacation.txt +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M tests/extensions/vacation/message.svtest + +2013-09-23 20:58:02 +0200 Stephan Bosch <stephan@rename-it.nl> (2e1a3ddd) + + managesieve: Updated to changes in Dovecot listeners regarding SO_REUSEPORT. + + +M src/managesieve-login/managesieve-login-settings.c + +2013-09-22 11:51:38 +0200 Stephan Bosch <stephan@rename-it.nl> (f995169c) + + doveadm sieve plugin: Fixed the `Invalid value for default sieve attribute' + problem. The attribute type code data was allocated on the stack rather than + statically, causing the returned stream to point to invalid data. + + +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2013-09-17 23:57:05 +0200 Stephan Bosch <stephan@rename-it.nl> (11e2c26c) + + doveadm sieve plugin: Changed root attribute for Sieve. + + +M src/lib-sievestorage/sieve-storage.h + +2013-09-17 23:55:59 +0200 Stephan Bosch <stephan@rename-it.nl> (e6be8418) + + doveadm sieve plugin: Small initialization fix. + + +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2013-09-16 01:15:55 +0200 Stephan Bosch <stephan@rename-it.nl> (e01cb4d9) + + Merged changes from v0.3 tree. + + +2013-09-16 00:55:29 +0200 Stephan Bosch <stephan@rename-it.nl> (ed345afe) + + lib-sieve: variables extension: Fixed code corruption bug in 'set' command. + Bug whould occur when modifier was used and the value became "" at some + point. In that case not all operands (modifiers) were read, causing the + subsequent operation to start at an erroneous position. + + +M src/lib-sieve/plugins/variables/cmd-set.c + +2013-09-16 00:46:21 +0200 Stephan Bosch <stephan@rename-it.nl> (5fe59daf) + + sieve-dump tool: Fixed hex output. Messed up signed/unsigned characters. + + +M src/lib-sieve/sieve-binary-dumper.c + +2013-09-16 00:43:55 +0200 Stephan Bosch <stephan@rename-it.nl> (e56c6e53) + + lib-sieve: variables extension: fixed data stack problem in 'set' command. + + +M src/lib-sieve/plugins/variables/cmd-set.c + +2013-09-15 17:47:53 +0200 Stephan Bosch <stephan@rename-it.nl> (0449820b) + + lib-sieve: Fixed code block read bounds checking. + + +M src/lib-sieve/sieve-binary-code.c + +2013-09-15 12:47:33 +0200 Stephan Bosch <stephan@rename-it.nl> (d8269667) + + doveadm-sieve plugin: Fixed segfault bug. + + +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2013-09-15 12:43:25 +0200 Stephan Bosch <stephan@rename-it.nl> (8a861359) + + Merged changes from Pigeonhole 0.3 tree. + + +2013-09-15 12:19:10 +0200 Stephan Bosch <stephan@rename-it.nl> (5d695ea3) + + lib-sieve: spamtest virustest extensions: Fixed end-of-string testing in + configuration parser. + + +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c + +2013-09-04 18:12:44 +0200 Stephan Bosch <stephan@rename-it.nl> (05f714c2) + + doveadm-sieve plugin: Fixed a few crash issues. Patches by Timo Sirainen. + + +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2013-08-15 21:07:56 +0200 Stephan Bosch <stephan@rename-it.nl> (219ad23f) + + Merged changes from Pigeonhole v0.3 tree. + + +2013-08-15 21:02:37 +0200 Stephan Bosch <stephan@rename-it.nl> (dbf6ec23) + + Various fixes for CLang warnings. Patch by Timo Sirainen (modified). + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-validator.c +M src/managesieve-login/client-authenticate.c +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite.c + +2013-08-15 20:48:54 +0200 Stephan Bosch <stephan@rename-it.nl> (932477e5) + + lib-sieve: include extension: Fixed implementation of new :options flag. + Mixed up pre-existing boolean once parameter with new flags parameter. This + probably means that :optional partially implied :once for previous + revisions. + + +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h + +2013-08-15 20:15:08 +0200 Stephan Bosch <stephan@rename-it.nl> (a23ea5cd) + + lda-sieve plugin: Don't access already freed memory when deinitializing. + Patch by Timo Sirainen (modified). + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2013-08-15 19:59:18 +0200 Stephan Bosch <stephan@rename-it.nl> (65847885) + + extprograms plugin: Compiler warning fix for 32bit systems. Patch by Timo + Sirainen. + + +M src/plugins/sieve-extprograms/script-client-local.c + +2013-07-10 23:34:34 +0200 Stephan Bosch <stephan@rename-it.nl> (8dc55ce8) + + Updated Sieve extension status in comments. + + +M src/lib-sieve/plugins/editheader/ext-editheader.c +M src/lib-sieve/plugins/environment/ext-environment.c +M src/lib-sieve/plugins/ihave/ext-ihave.c +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/mailbox/ext-mailbox.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c +M src/lib-sieve/plugins/vacation/ext-vacation-seconds.c +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c +M src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate.c +M src/plugins/sieve-extprograms/ext-execute.c +M src/plugins/sieve-extprograms/ext-filter.c +M src/plugins/sieve-extprograms/ext-pipe.c + +2013-07-03 22:06:58 +0200 Stephan Bosch <stephan@rename-it.nl> (c705c2a2) + + Added signature for changeset f1535e2255cd + + +M .hgsigs + +2013-07-03 22:05:13 +0200 Stephan Bosch <stephan@rename-it.nl> (383ec2ec) + + Added tag 0.4.1 for changeset f1535e2255cd + + +2013-07-03 22:05:04 +0200 Stephan Bosch <stephan@rename-it.nl> (3ae0c2bb) + + Released v0.4.1 for Dovecot v2.2.4. + + +M NEWS +M configure.ac + +2013-07-03 21:35:12 +0200 Stephan Bosch <stephan@rename-it.nl> (e29f2b98) + + Merged changes from Pigeonhole v0.3 tree. + + +2013-06-18 22:04:50 +0200 Stephan Bosch <stephan@rename-it.nl> (2e5ed35b) + + Fixed deprecated INCLUDE= assignment in Makefile.am + + +M src/lib-sievestorage/Makefile.am + +2013-06-18 08:34:26 +0200 Stephan Bosch <stephan@rename-it.nl> (f8b9adf0) + + lib-sievestorage: Removed PATH_MAX limitation for active symlink. Fixes + issue for GNU/Hurd. + + +M src/lib-sievestorage/sieve-storage-script.c + +2013-06-18 08:24:40 +0200 Stephan Bosch <stephan@rename-it.nl> (46bf4c6c) + + Fixed line endings in X-Sieve headers added by redirect command. Modified + patch by Andriy Syrovenko. + + +M src/lib-sieve/cmd-redirect.c + +2013-06-18 08:11:37 +0200 Stephan Bosch <stephan@rename-it.nl> (bb90042a) + + Don't access ns->storage. Patch by Timo Sirainen. + + +M src/sieve-tools/sieve-filter.c + +2013-06-02 16:08:22 +0200 Stephan Bosch <stephan@rename-it.nl> (af703f2e) + + Finished support for temporary failures. This change is bigger than I would + have liked, so this needs to be tested more. + + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate-common.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-script-dict.c +M src/lib-sieve/sieve-script-file.c +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sievestorage/sieve-storage.c +M src/managesieve/managesieve-client.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/plugins/sieve-extprograms/cmd-pipe.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite.c + +2013-05-24 13:12:24 +0200 Stephan Bosch <stephan@rename-it.nl> (f47475ae) + + Merged changes from Pigeonhole v0.3 tree. + + +2013-05-24 13:07:23 +0200 Stephan Bosch <stephan@rename-it.nl> (bbb5be0c) + + managesieve-login: Fixed '[' ']' stupidity for response codes. Emerged when + Sieve and ManageSieve were merged into Pigeonhole. + + +M src/managesieve-login/client.c + +2013-05-20 21:20:04 +0200 Stephan Bosch <stephan@rename-it.nl> (ba95ae62) + + Sieve extprograms plugin: Fixed interaction between pipe command and remote + script service. The output from the script service was never read, causing a + broken pipe error at the script service. Apparently, this was broken since + the I/O handling for extprograms was last revised. + + +M src/plugins/sieve-extprograms/script-client-remote.c +M src/plugins/sieve-extprograms/script-client.c + +2013-05-15 21:59:32 +0200 Stephan Bosch <stephan@rename-it.nl> (51c2d126) + + lib-sieve: Fixed datastack problem in message header composition. + + +M src/lib-sieve/rfc2822.c + +2013-05-12 19:14:18 +0200 Stephan Bosch <stephan@rename-it.nl> (66085257) + + Fixed setting name in example-config/conf.d/20-managesieve.conf. + + +M doc/example-config/conf.d/20-managesieve.conf + +2013-05-09 16:39:41 +0200 Stephan Bosch <stephan@rename-it.nl> (8e08342a) + + Forgot to update Dovecot version in README and man pages. + + +M README +M doc/man/pigeonhole.7.in +M doc/man/sieve-dump.1.in +M doc/man/sieve-filter.1.in +M doc/man/sieve-test.1.in +M doc/man/sievec.1.in + +2013-05-09 15:41:42 +0200 Stephan Bosch <stephan@rename-it.nl> (cf64d222) + + Added signature for changeset 3a8dc1250e9b + + +M .hgsigs + +2013-05-09 15:40:25 +0200 Stephan Bosch <stephan@rename-it.nl> (71e1f2a2) + + Added tag 0.4.0 for changeset 3a8dc1250e9b + + +2013-05-09 15:39:17 +0200 Stephan Bosch <stephan@rename-it.nl> (9791b4af) + + Released v0.4.0 for Dovecot v2.2.1. + + +2013-05-09 15:21:43 +0200 Stephan Bosch <stephan@rename-it.nl> (58d7ff3d) + + Added signature for changeset 374ec9399958 + + +M .hgsigs + +2013-05-09 15:19:32 +0200 Stephan Bosch <stephan@rename-it.nl> (d228de08) + + Updated dovecot.m4 to latest version. + + +M m4/dovecot.m4 + +2013-05-09 15:18:13 +0200 Stephan Bosch <stephan@rename-it.nl> (a41a16ce) + + Added tag 0.3.5 for changeset 374ec9399958 + + +2013-05-09 15:18:05 +0200 Stephan Bosch <stephan@rename-it.nl> (46755a82) + + Released v0.3.5 for Dovecot v2.1.16. + + +M NEWS +M configure.in + +2013-05-09 15:11:13 +0200 Stephan Bosch <stephan@rename-it.nl> (fb122b93) + + Fixed problem in `make distcheck`. Added --disable-shared to + DISTCHECK_CONFIGURE_FLAGS (in dovecot.m4) to prevent libtool from relinking + the libraries. + + +M m4/dovecot.m4 + +2013-05-09 12:22:39 +0200 Stephan Bosch <stephan@rename-it.nl> (19e0ed1e) + + Removed UNSTABLE notice from configure. + + +M configure.ac + +2013-05-09 12:21:31 +0200 Stephan Bosch <stephan@rename-it.nl> (d0367e8b) + + Merged changed from Pigeonhole v0.3. + + +2013-05-09 11:28:44 +0200 Stephan Bosch <stephan@rename-it.nl> (77ec8981) + + doveadm-sieve: Fixed synchronization of script deletions. Sieve storage now + updates sieve attributes in the user's INBOX if used by ManageSieve. + + +M src/lib-sievestorage/sieve-storage-private.h +M src/lib-sievestorage/sieve-storage-save.c +M src/lib-sievestorage/sieve-storage-script.c +M src/lib-sievestorage/sieve-storage.c +M src/lib-sievestorage/sieve-storage.h +M src/managesieve/managesieve-client.c +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2013-05-06 22:48:59 +0200 Stephan Bosch <stephan@rename-it.nl> (9337fee9) + + doveadm-sieve: Fix ping-pong problem in active Sieve script synchronization. + Patch by Timo Sirainen. + + +M src/lib-sievestorage/sieve-storage.c +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2013-05-02 21:37:36 +0200 Stephan Bosch <stephan@rename-it.nl> (6b7fe6f5) + + lib-sieve: editheader extension: Fixed interaction with body extension. + Forgot to rewind mail stream before header parsing. Wrapped mail stream is + obtained long before parsing, so if it is used in the mean time, it must be + rewound to the beginning. + + +M src/lib-sieve/edit-mail.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M tests/extensions/editheader/deleteheader.svtest + +2013-04-23 22:55:03 +0200 Stephan Bosch <stephan@rename-it.nl> (59625262) + + doveadm-sieve: Fixed mtime updates. Patch by Timo Sirainen. + + +M src/lib-sievestorage/sieve-storage-private.h +M src/lib-sievestorage/sieve-storage-save.c +M src/lib-sievestorage/sieve-storage-script.c +M src/lib-sievestorage/sieve-storage-script.h +M src/lib-sievestorage/sieve-storage.c +M src/managesieve/cmd-setactive.c +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2013-04-20 21:27:15 +0200 Stephan Bosch <stephan@rename-it.nl> (03a16d96) + + doveadm-sieve: Set mtime of modified scripts and sieve dir to timestamp from + dsync. Still does not fix the ping-pong issue. + + +M src/lib-sievestorage/sieve-storage-save.c +M src/lib-sievestorage/sieve-storage-save.h +M src/lib-sievestorage/sieve-storage.c +M src/lib-sievestorage/sieve-storage.h +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2013-04-19 23:21:35 +0200 Stephan Bosch <stephan@rename-it.nl> (3b6c9b06) + + doveadm-sieve: Made active script last_change time always dependent on + sieve_dir mtime. Change is preliminary. Still doing some experiments, + 'ping-pong' problem is not solved. + + +M src/lib-sievestorage/sieve-storage-save.c +M src/lib-sievestorage/sieve-storage-script.c + +2013-04-19 22:26:32 +0200 Stephan Bosch <stephan@rename-it.nl> (06bfdd06) + + doveadm-sieve: Prevented Sieve storage from logging useless while + synchronizing. Added flag to prevent warnings about non-link active scripts + and disable critical error logging. A rather fundamental synchronization + problem remains to be solved. + + +M src/lib-sievestorage/sieve-storage-private.h +M src/lib-sievestorage/sieve-storage-script.c +M src/lib-sievestorage/sieve-storage.c +M src/lib-sievestorage/sieve-storage.h +M src/managesieve/managesieve-client.c +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2013-04-19 09:46:49 +0200 Stephan Bosch <stephan@rename-it.nl> (3b0fc8c3) + + Made preparations for first v0.4 release. + + +M INSTALL +M NEWS +M README +M TODO +M doc/plugins/sieve_extprograms.txt + +2013-04-19 09:45:15 +0200 Stephan Bosch <stephan@rename-it.nl> (35c7ebad) + + Fixed distcheck failure on sieve_extprograms plugin testsuite. + + +M src/testsuite/testsuite-variables.c +A tests/plugins/extprograms/bin/sleep10 +M tests/plugins/extprograms/execute/command.svtest +M tests/plugins/extprograms/execute/errors.svtest +M tests/plugins/extprograms/execute/execute.svtest +M tests/plugins/extprograms/filter/command.svtest +M tests/plugins/extprograms/filter/errors.svtest +M tests/plugins/extprograms/filter/execute.svtest +M tests/plugins/extprograms/pipe/command.svtest +M tests/plugins/extprograms/pipe/errors.svtest +M tests/plugins/extprograms/pipe/errors/timeout.sieve +M tests/plugins/extprograms/pipe/execute.svtest + +2013-04-19 09:15:01 +0200 Stephan Bosch <stephan@rename-it.nl> (aa2cfbaa) + + Fixed test suite for vnd.dovecot.execute extension. Testsuite hostname is + now true local hostname. + + +M tests/plugins/extprograms/execute/execute.svtest + +2013-04-12 20:25:02 +0200 Stephan Bosch <stephan@rename-it.nl> (0e0a359c) + + Fixed doveconf crash caused by previous change. Patch by Timo Sirainen. + + +M src/lib-sieve/sieve.c + +2013-04-11 22:40:07 +0200 Stephan Bosch <stephan@rename-it.nl> (9fc9fa97) + + lib-sieve: environment extension: Finally finished this extension a much as + possible. Some environment items in the base specification are not (yet) + applicable to Dovecot and are therefore not supported. + + +M README +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M tests/extensions/environment/basic.svtest +M tests/extensions/environment/rfc.svtest + +2013-04-11 20:42:41 +0200 Stephan Bosch <stephan@rename-it.nl> (7d4ca027) + + doveadm-sieve: Updated to dsync changes in Dovecot mail storage API. Patch + by Timo Sirainen. + + +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2013-04-07 23:42:04 +0200 Stephan Bosch <stephan@rename-it.nl> (365c8db9) + + Compile warning fixes. + + +M src/plugins/sieve-extprograms/script-client-remote.c +M src/plugins/sieve-extprograms/sieve-extprograms-common.h + +2013-04-07 05:12:57 +0200 Stephan Bosch <stephan@rename-it.nl> (100602de) + + testsuite: fixed local timezone dependency in date extension tests. + + +M tests/extensions/date/basic.svtest + +2013-04-07 02:30:11 +0200 Stephan Bosch <stephan@rename-it.nl> (6744a189) + + Updated TODO to include items related to sieve_extprograms plugin. + + +M TODO + +2013-04-07 02:25:46 +0200 Stephan Bosch <stephan@rename-it.nl> (b08ad1e5) + + Added sieve_extprograms plugin to the main Pigeonhole tree. It is still a + plugin, but no longer a separate package. + + +M INSTALL +M Makefile.am +M configure.ac +M doc/Makefile.am +A doc/example-config/conf.d/90-sieve-extprograms.conf +M doc/example-config/conf.d/90-sieve.conf +M doc/example-config/conf.d/Makefile.am +A doc/plugins/sieve_extprograms.txt +A doc/rfc/spec-bosch-sieve-extprograms.txt +A doc/rfc/xml/reference.DSN.xml +A doc/rfc/xml/reference.MDN.xml +A doc/rfc/xml/reference.NET-UNICODE.xml +A doc/rfc/xml/reference.RFC.3894.xml +A doc/rfc/xml/reference.RFC.5429.xml +A doc/rfc/xml/reference.SUBADDRESS.xml +A doc/rfc/xml/reference.UTF-8.xml +A doc/rfc/xml/spec-bosch-sieve-extprograms.xml +M src/plugins/Makefile.am +A src/plugins/sieve-extprograms/Makefile.am +A src/plugins/sieve-extprograms/cmd-execute.c +A src/plugins/sieve-extprograms/cmd-filter.c +A src/plugins/sieve-extprograms/cmd-pipe.c +A src/plugins/sieve-extprograms/ext-execute.c +A src/plugins/sieve-extprograms/ext-filter.c +A src/plugins/sieve-extprograms/ext-pipe.c +A src/plugins/sieve-extprograms/script-client-local.c +A src/plugins/sieve-extprograms/script-client-private.h +A src/plugins/sieve-extprograms/script-client-remote.c +A src/plugins/sieve-extprograms/script-client.c +A src/plugins/sieve-extprograms/script-client.h +A src/plugins/sieve-extprograms/sieve-extprograms-common.c +A src/plugins/sieve-extprograms/sieve-extprograms-common.h +A src/plugins/sieve-extprograms/sieve-extprograms-plugin.c +A src/plugins/sieve-extprograms/sieve-extprograms-plugin.h +A tests/plugins/extprograms/bin/addheader +A tests/plugins/extprograms/bin/cat +A tests/plugins/extprograms/bin/env +A tests/plugins/extprograms/bin/frame +A tests/plugins/extprograms/bin/modify +A tests/plugins/extprograms/bin/program +A tests/plugins/extprograms/bin/replace +A tests/plugins/extprograms/bin/sleep2 +A tests/plugins/extprograms/bin/stderr +A tests/plugins/extprograms/errors.svtest +A tests/plugins/extprograms/errors/arguments.sieve +A tests/plugins/extprograms/errors/programname.sieve +A tests/plugins/extprograms/execute/command.svtest +A tests/plugins/extprograms/execute/errors.svtest +A tests/plugins/extprograms/execute/errors/syntax.sieve +A tests/plugins/extprograms/execute/errors/variables.sieve +A tests/plugins/extprograms/execute/execute.svtest +A tests/plugins/extprograms/filter/command.svtest +A tests/plugins/extprograms/filter/errors.svtest +A tests/plugins/extprograms/filter/errors/syntax.sieve +A tests/plugins/extprograms/filter/execute.svtest +A tests/plugins/extprograms/pipe/command.svtest +A tests/plugins/extprograms/pipe/errors.svtest +A tests/plugins/extprograms/pipe/errors/syntax.sieve +A tests/plugins/extprograms/pipe/errors/timeout.sieve +A tests/plugins/extprograms/pipe/execute.svtest + +2013-04-07 00:58:40 +0200 Stephan Bosch <stephan@rename-it.nl> (9279e66b) + + Updated TODO. + + +M TODO + +2013-04-07 00:41:19 +0200 Stephan Bosch <stephan@rename-it.nl> (f3ae16df) + + Merged changes from Pigeonhole v0.3 tree. + + +2013-04-07 00:33:41 +0200 Stephan Bosch <stephan@rename-it.nl> (f4ceacd2) + + doveadm-sieve: Fixed handling of non-link active script. Unsetting the + normal active script attribute would 'rescue' the non-link script and turn + it into a symlink. + + +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2013-04-06 22:37:46 +0200 Stephan Bosch <stephan@rename-it.nl> (08892a5d) + + Added signature for changeset 493202676845 + + +M .hgsigs + +2013-04-06 22:37:39 +0200 Stephan Bosch <stephan@rename-it.nl> (4db2bd64) + + Added tag 0.3.4 for changeset 493202676845 + + +2013-04-06 22:37:02 +0200 Stephan Bosch <stephan@rename-it.nl> (173e9dd5) + + Released v0.3.4 for Dovecot v2.1.16. + + +M NEWS +M TODO +M configure.in + +2013-04-06 16:54:57 +0200 Stephan Bosch <stephan@rename-it.nl> (8c9ef2fc) + + Updated copyright notices to include the year 2013. + + +M src/lib-managesieve/managesieve-arg.c +M src/lib-managesieve/managesieve-arg.h +M src/lib-managesieve/managesieve-parser.c +M src/lib-managesieve/managesieve-parser.h +M src/lib-managesieve/managesieve-quote.c +M src/lib-managesieve/managesieve-quote.h +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/mail-raw.h +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/cmp-i-ascii-casemap.c +M src/lib-sieve/cmp-i-octet.c +M src/lib-sieve/edit-mail.c +M src/lib-sieve/edit-mail.h +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/copy/sieve-ext-copy.h +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/ext-date-common.h +M src/lib-sieve/plugins/date/ext-date.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/editheader/cmd-addheader.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.h +M src/lib-sieve/plugins/editheader/ext-editheader-limits.h +M src/lib-sieve/plugins/editheader/ext-editheader.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify-limits.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.h +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/environment/ext-environment-common.h +M src/lib-sieve/plugins/environment/ext-environment.c +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/ihave/cmd-error.c +M src/lib-sieve/plugins/ihave/ext-ihave-binary.c +M src/lib-sieve/plugins/ihave/ext-ihave-binary.h +M src/lib-sieve/plugins/ihave/ext-ihave-common.c +M src/lib-sieve/plugins/ihave/ext-ihave-common.h +M src/lib-sieve/plugins/ihave/ext-ihave.c +M src/lib-sieve/plugins/ihave/tst-ihave.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-limits.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/mailbox/ext-mailbox-common.h +M src/lib-sieve/plugins/mailbox/ext-mailbox.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.h +M src/lib-sieve/plugins/notify/ext-notify-limits.h +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/plugins/regex/ext-regex-common.c +M src/lib-sieve/plugins/regex/ext-regex-common.h +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/lib-sieve/plugins/vacation/ext-vacation-seconds.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.h +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables-dump.h +M src/lib-sieve/plugins/variables/ext-variables-limits.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-name.c +M src/lib-sieve/plugins/variables/ext-variables-name.h +M src/lib-sieve/plugins/variables/ext-variables-namespaces.c +M src/lib-sieve/plugins/variables/ext-variables-namespaces.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug-common.h +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c +M src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate-common.c +M src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate-common.h +M src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate.c +M src/lib-sieve/plugins/vnd.dovecot/duplicate/tst-duplicate.c +M src/lib-sieve/rfc2822.c +M src/lib-sieve/rfc2822.h +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary-code.c +M src/lib-sieve/sieve-binary-debug.c +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-objects.c +M src/lib-sieve/sieve-objects.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-plugins.c +M src/lib-sieve/sieve-plugins.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-runtime-trace.c +M src/lib-sieve/sieve-runtime-trace.h +M src/lib-sieve/sieve-runtime.h +M src/lib-sieve/sieve-script-dict.c +M src/lib-sieve/sieve-script-file.c +M src/lib-sieve/sieve-script-file.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve-smtp.c +M src/lib-sieve/sieve-smtp.h +M src/lib-sieve/sieve-stringlist.c +M src/lib-sieve/sieve-stringlist.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c +M src/lib-sieve/tst-truefalse.c +M src/lib-sievestorage/sieve-storage-list.c +M src/lib-sievestorage/sieve-storage-list.h +M src/lib-sievestorage/sieve-storage-private.h +M src/lib-sievestorage/sieve-storage-quota.c +M src/lib-sievestorage/sieve-storage-quota.h +M src/lib-sievestorage/sieve-storage-save.c +M src/lib-sievestorage/sieve-storage-save.h +M src/lib-sievestorage/sieve-storage-script.c +M src/lib-sievestorage/sieve-storage-script.h +M src/lib-sievestorage/sieve-storage.c +M src/lib-sievestorage/sieve-storage.h +M src/managesieve-login/client-authenticate.c +M src/managesieve-login/client-authenticate.h +M src/managesieve-login/client.c +M src/managesieve-login/client.h +M src/managesieve-login/managesieve-login-settings-plugin.c +M src/managesieve-login/managesieve-login-settings-plugin.h +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve-login/managesieve-login-settings.h +M src/managesieve-login/managesieve-proxy.c +M src/managesieve-login/managesieve-proxy.h +M src/managesieve/cmd-capability.c +M src/managesieve/cmd-deletescript.c +M src/managesieve/cmd-getscript.c +M src/managesieve/cmd-havespace.c +M src/managesieve/cmd-listscripts.c +M src/managesieve/cmd-logout.c +M src/managesieve/cmd-noop.c +M src/managesieve/cmd-putscript.c +M src/managesieve/cmd-renamescript.c +M src/managesieve/cmd-setactive.c +M src/managesieve/main.c +M src/managesieve/managesieve-capabilities.c +M src/managesieve/managesieve-capabilities.h +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h +M src/managesieve/managesieve-commands.c +M src/managesieve/managesieve-commands.h +M src/managesieve/managesieve-common.h +M src/managesieve/managesieve-quota.c +M src/managesieve/managesieve-quota.h +M src/managesieve/managesieve-settings.c +M src/managesieve/managesieve-settings.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/plugins/lda-sieve/lda-sieve-plugin.h +M src/sieve-tools/sieve-dump.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-result.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-arguments.c +M src/testsuite/testsuite-arguments.h +M src/testsuite/testsuite-binary.c +M src/testsuite/testsuite-binary.h +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-log.h +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-result.h +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-script.h +M src/testsuite/testsuite-settings.c +M src/testsuite/testsuite-settings.h +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite-substitutions.c +M src/testsuite/testsuite-substitutions.h +M src/testsuite/testsuite-variables.c +M src/testsuite/testsuite-variables.h +M src/testsuite/testsuite.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-action.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c + +2013-04-05 18:08:19 +0200 Stephan Bosch <stephan@rename-it.nl> (572bc510) + + doveadm-sieve: Adjusted to Dovecot API change. + + +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2013-04-03 00:08:05 +0200 Stephan Bosch <stephan@rename-it.nl> (dff5598c) + + doveadm-sieve: Prevented initializing the Sieve storage multiple times. + + +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2013-04-02 23:14:37 +0200 Stephan Bosch <stephan@rename-it.nl> (5a27c7eb) + + Merged changes from Pigeonhole v0.3 tree. + + +2013-04-02 23:14:13 +0200 Stephan Bosch <stephan@rename-it.nl> (c2b71b1b) + + doveadm-sieve: Implemented handling the situation when the main active + script is a regular file. Tested whether this change breaks ManageSieve and + basic dsync, but not much more. More tests pending. If you use sync be + careful with this commit. + + +M src/lib-sieve/sieve-plugins.c +M src/lib-sievestorage/sieve-storage-list.c +M src/lib-sievestorage/sieve-storage-save.c +M src/lib-sievestorage/sieve-storage-save.h +M src/lib-sievestorage/sieve-storage-script.c +M src/lib-sievestorage/sieve-storage-script.h +M src/lib-sievestorage/sieve-storage.c +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2013-04-02 23:09:14 +0200 Stephan Bosch <stephan@rename-it.nl> (7261c0cb) + + lib-sieve: Fixed plugin module load functionality. Initializing multiple + Sieve instances would hang. + + +M src/lib-sieve/sieve-plugins.c + +2013-03-28 22:14:21 +0100 Stephan Bosch <stephan@rename-it.nl> (824b68d6) + + Merged changes from Pigeonhole v0.3 tree. + + +2013-03-28 22:12:03 +0100 Stephan Bosch <stephan@rename-it.nl> (c6ee18c9) + + lib-sievestorage: Fixed a few potential problems in script save code. + + +M src/lib-sievestorage/sieve-storage-save.c + +2013-03-28 21:33:31 +0100 Stephan Bosch <stephan@rename-it.nl> (7cde39ab) + + Merged changes from Pigeonhole v0.3 tree. + + +2013-03-28 21:31:59 +0100 Stephan Bosch <stephan@rename-it.nl> (856ccbb4) + + lib-sievestorage: A few debug messages were still logged using i_info() + instead of i_debug(). + + +M src/lib-sievestorage/sieve-storage-script.c +M src/lib-sievestorage/sieve-storage.c + +2013-03-28 21:27:53 +0100 Stephan Bosch <stephan@rename-it.nl> (e4ec7f70) + + doveadm-sieve: Implemented obtaining last modification time for the active + script attribute. It compiles, doesn't break normal ManageSieve operation, + but it remains untested otherwise. + + +M src/lib-sievestorage/sieve-storage-private.h +M src/lib-sievestorage/sieve-storage-script.c +M src/lib-sievestorage/sieve-storage-script.h +M src/lib-sievestorage/sieve-storage.c +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2013-03-25 12:34:13 +0100 Stephan Bosch <stephan@rename-it.nl> (d0fd30b5) + + doveadm-sieve: Crash instead of writing empty .sieve files. Patch by Timo + Sirainen. + + +M src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2013-03-23 12:14:14 +0100 Stephan Bosch <stephan@rename-it.nl> (884351e8) + + Fixed compile order for previous change. + + +M src/Makefile.am + +2013-03-22 23:09:57 +0100 Stephan Bosch <stephan@rename-it.nl> (9d33676d) + + Committed Timo's patch that adds a plugin that provides Sieve dsync support. + http://dovecot.org/patches/2.2/doveadm-sieve-plugin.diff Made some small + modifications. This code should not interfere with normal ManageSieve + operation, so I commit this right now without much testing. The actual + doveadm sieve plugin has a few open issues that need to be resolved still. + + +M configure.ac +M src/lib-sievestorage/Makefile.am +M src/lib-sievestorage/sieve-storage.c +M src/lib-sievestorage/sieve-storage.h +M src/managesieve/Makefile.am +M src/plugins/Makefile.am +A src/plugins/doveadm-sieve/Makefile.am +A src/plugins/doveadm-sieve/doveadm-sieve-plugin.c + +2013-03-04 22:26:15 +0100 Stephan Bosch <stephan@rename-it.nl> (59de1b42) + + lib-sieve: Fixed segfault bug in reject. Passed senv->script_context rather + than senv itself. Somehow the compiler fails to warn about this. + + +M src/lib-sieve/sieve-actions.c + +2013-03-03 18:07:30 +0100 Stephan Bosch <stephan@rename-it.nl> (6d707527) + + Merged changes from Pigeonhole v0.3. + + +2013-03-03 18:03:33 +0100 Stephan Bosch <stephan@rename-it.nl> (e6a1b593) + + LDA Sieve plugin: further reduced useless error messages in administrator + log. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2013-03-03 17:35:37 +0100 Stephan Bosch <stephan@rename-it.nl> (079c5271) + + LDA Sieve plugin: fixed bug in opening script files for multiscript. Used + sieve_script_create instead of sieve_script_create_open. Changed plugin + debug output a bit as well. + + +M src/lib-sieve/sieve-script.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2013-03-03 16:55:05 +0100 Stephan Bosch <stephan@rename-it.nl> (4d0cf9d8) + + Merged changes from Pigeonhole v0.3. + + +2013-03-03 16:52:39 +0100 Stephan Bosch <stephan@rename-it.nl> (f2f90bb2) + + LDA Sieve plugin: fixed stupid mistake in error handling for multiscript. + Used errno instead of error variable. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2013-03-02 23:27:13 +0100 Stephan Bosch <stephan@rename-it.nl> (d9a984ac) + + lib-sieve: added debug message showing Pigeonhole version at initialization. + Very useful to show that debugging is enabled and what version of pigeonhole + is actually running. + + +M src/lib-sieve/sieve.c + +2013-03-02 22:36:55 +0100 Stephan Bosch <stephan@rename-it.nl> (d56dd089) + + LDA Sieve plugin: adjusted script compile/load error reporting. Made normal + compile error an info log item in the administrator log. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2013-02-28 23:37:31 +0100 Stephan Bosch <stephan@rename-it.nl> (783fdcae) + + Sieve: editheader: fixed bug in header cloning for snapshot. Forgot to + increment count for the clone. + + +M src/lib-sieve/edit-mail.c +M tests/extensions/editheader/alternating.svtest + +2013-02-28 23:06:47 +0100 Stephan Bosch <stephan@rename-it.nl> (58f32d2c) + + Sieve: editheader: fixed bug in full header parsing when addheader :last is + used. + + +M src/lib-sieve/edit-mail.c + +2013-02-06 21:24:30 +0100 Stephan Bosch <stephan@rename-it.nl> (dec32238) + + managesieve: Fixed bug in skipping of CRLF at end of AUTHENTICATE command. + Setting skip_newline is useless when the connection is transfered to another + process after successful login. + + +M src/managesieve-login/client-authenticate.c + +2013-01-26 09:10:26 +0100 Stephan Bosch <stephan@rename-it.nl> (f26a0dc3) + + lib-sieve: Increased a few initial memory pool sizes. + + +M src/lib-sieve/plugins/editheader/ext-editheader-common.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-validator.c + +2013-01-26 08:52:27 +0100 Stephan Bosch <stephan@rename-it.nl> (81245ddf) + + Changed behavior of redirect in case of a duplicate message delivery or a + mail loop. If a duplicate is detected the implicit keep is canceled, as + though the redirect was successful. This prevents getting local deliveries. + The original SMTP recipient is used when it is available to augment the + entry in the LDA duplicate database. This way, duplicates are only detected + when (initially) addressed to the same recipient. The main goal of the + duplicate detection is mail loop prevention, but this also has the effect + that mere duplicate deliveries are handled specially whithout a good reason. + We should fix this in a future version. + + +M src/lib-sieve/cmd-redirect.c + +2013-01-14 12:57:58 +0100 Stephan Bosch <stephan@rename-it.nl> (7f559d44) + + Merged changes from Pigeonhole v0.3 tree. + + +2013-01-09 00:55:49 +0100 Stephan Bosch <stephan@rename-it.nl> (40a0bb91) + + Fixed SMTP crash. By Timo Sirainen. + + +M src/lib-sieve/sieve-smtp.c + +2013-01-09 00:38:07 +0100 Stephan Bosch <stephan@rename-it.nl> (35e2fff1) + + Adjusted to changes in Dovecot. + + +M src/lib-sieve/edit-mail.c + +2012-12-26 11:52:03 +0100 Stephan Bosch <stephan@rename-it.nl> (312ce006) + + Fixed compile on Mageia Linux. Added LIBDOVECOT_STORAGE to library + dependencies in src/lib-sieve/Makefile.am. + + +M src/lib-sieve/Makefile.am + +2012-12-22 22:27:34 +0100 Stephan Bosch <stephan@rename-it.nl> (7da1a76d) + + lib-sieve: Prevent passing NULL sender to raw mail storage when active + message is substituted. + + +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-message.c + +2012-11-26 21:16:54 +0100 Stephan Bosch <stephan@rename-it.nl> (ca6601ba) + + lib-sieve: vacation extension: Fixed determination of From: address for when + sieve_vacation_dont_check_recipient is active. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2012-10-29 22:42:34 +0100 Stephan Bosch <stephan@rename-it.nl> (19c2f6a6) + + Renamed configure.in to configure.ac. Apparently automakes in future won't + support configure.in anymore. + + +R100 configure.in configure.ac + +2012-10-17 22:22:02 +0200 Stephan Bosch <stephan@rename-it.nl> (9791083b) + + lib-sieve: Fixed a stupidity in the dict script implementation. + + +M src/lib-sieve/sieve-script-dict.c + +2012-10-17 22:11:16 +0200 Stephan Bosch <stephan@rename-it.nl> (aa0b16ea) + + Updated installation documentation for vnd.dovecot.duplicate extension. + + +M doc/extensions/vnd.dovecot.duplicate.txt + +2012-10-17 22:10:50 +0200 Stephan Bosch <stephan@rename-it.nl> (4e9e42df) + + lib-sieve: vnd.dovecot.duplicate: Fixed default max period setting. + + +M src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate-common.c + +2012-10-17 21:49:55 +0200 Stephan Bosch <stephan@rename-it.nl> (7f18f33d) + + Improved specification of the vnd.dovecot.duplicate extension. + + +M doc/rfc/spec-bosch-sieve-duplicate.txt +A doc/rfc/xml/reference.INCLUDE.xml +M doc/rfc/xml/spec-bosch-sieve-duplicate.xml + +2012-10-17 02:55:07 +0200 Stephan Bosch <stephan@rename-it.nl> (266bc73e) + + lib-sieve: vnd.dovecot.duplicate extension: Only track duplicate when Sieve + script executes successfully. + + +M src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate-common.c +M src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate-common.h +M src/lib-sieve/plugins/vnd.dovecot/duplicate/tst-duplicate.c + +2012-10-17 02:15:04 +0200 Stephan Bosch <stephan@rename-it.nl> (7dc1be65) + + lib-sieve: vnd.dovecot.duplicate extension: Fixed segfault occurring in + testsuite. + + +M src/lib-sieve/plugins/vnd.dovecot/duplicate/tst-duplicate.c + +2012-10-17 02:09:55 +0200 Stephan Bosch <stephan@rename-it.nl> (aa3bcb0f) + + lib-sieve: vnd.dovecot.duplicate extension: fixed bug in previous change. + Forgot to initialize variable, causing a segfault at runtime. + + +M src/lib-sieve/plugins/vnd.dovecot/duplicate/tst-duplicate.c + +2012-10-16 21:33:15 +0200 Stephan Bosch <stephan@rename-it.nl> (a425a57d) + + lib-sieve: vnd.dovecot.duplicate extension: Added new features to the + duplicate test. It is now possible to track duplicates based on arbitrary + headers or even arbitrary string values using the new :header and :value + arguments respectively. The experation time can be configured using the new + :seconds argument. This change is backwards compatible as long as the name + argument wasn't used. This is now a :handle <handle> argument. + + +M doc/rfc/spec-bosch-sieve-duplicate.txt +A doc/rfc/xml/reference.IMAP4FLAGS.xml +A doc/rfc/xml/reference.MAILBOX.xml +A doc/rfc/xml/reference.VACATION.xml +M doc/rfc/xml/spec-bosch-sieve-duplicate.xml +M src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate-common.c +M src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate-common.h +M src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate.c +M src/lib-sieve/plugins/vnd.dovecot/duplicate/tst-duplicate.c +M tests/extensions/vnd.dovecot/duplicate/errors.svtest +M tests/extensions/vnd.dovecot/duplicate/errors/syntax.sieve +M tests/extensions/vnd.dovecot/duplicate/execute.svtest + +2012-10-13 10:36:11 +0200 Stephan Bosch <stephan@rename-it.nl> (5f6ea36e) + + Adjusted to Dovecot dict API changes. + + +M src/lib-sieve/sieve-script-dict.c + +2012-10-13 10:35:19 +0200 Stephan Bosch <stephan@rename-it.nl> (f617c4e6) + + Merged changes from Pigeonhole v0.3. + + +2012-10-13 10:30:57 +0200 Stephan Bosch <stephan@rename-it.nl> (9224df2b) + + lib-sieve: dict script: fixed potential segfault occuring when dict + initialization fails. + + +M src/lib-sieve/sieve-script-dict.c + +2012-10-12 19:25:10 +0200 Stephan Bosch <stephan@rename-it.nl> (98d9957d) + + Incorporated Dovecot plugin ABI changes (forgot a few issues). + + +M src/lib-sieve/sieve-plugins.c +M src/managesieve-login/managesieve-login-settings-plugin.c +M src/managesieve/managesieve-settings.c + +2012-10-12 00:54:03 +0200 Stephan Bosch <stephan@rename-it.nl> (4ba1f32c) + + Incorporated Dovecot plugin ABI changes. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2012-10-11 22:07:50 +0200 Stephan Bosch <stephan@rename-it.nl> (7adde42a) + + ManageSieve: fixed handling of unkown commands pre-login. Forgot to skip + line upon error. + + +M src/managesieve-login/client.c + +2012-10-11 20:26:03 +0200 Stephan Bosch <stephan@rename-it.nl> (7e18cd0b) + + lib-sieve: Further improved handling of quota errors. Added means to log + user errors/warnings as info in master log. Previous change was inadequate + because an error was still logged. + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2012-10-11 01:48:29 +0200 Stephan Bosch <stephan@rename-it.nl> (8fc29444) + + lib-sieve: fileinto/keep: don't log quota errors to syslog but rather to + user's log. Prevents administrator frustration about useless log messages + caused by users with too much mail. + + +M src/lib-sieve/sieve-actions.c + +2012-10-03 18:00:50 +0200 Stephan Bosch <stephan@rename-it.nl> (58abc04e) + + Adjusted to changes in Dovecot network API. + + +M src/managesieve-login/client.h +M src/managesieve/managesieve-client.c + +2012-09-26 21:52:32 +0200 Stephan Bosch <stephan@rename-it.nl> (4fba9b25) + + testsuite: date extension: Added test for date comparisons. + + +M tests/extensions/date/basic.svtest + +2012-09-26 21:51:46 +0200 Stephan Bosch <stephan@rename-it.nl> (dd6875f5) + + lib-sieve: date extension: Generate warning when invalid date part is + specified. + + +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/ext-date-common.h +M src/lib-sieve/plugins/date/tst-date.c + +2012-09-23 17:14:58 +0200 Stephan Bosch <stephan@rename-it.nl> (5e955ec3) + + Merged changes from Pigeonhole v0.3. + + +2012-09-23 17:09:26 +0200 Stephan Bosch <stephan@rename-it.nl> (7e1f287a) + + lib-sieve: mailbox extension: After creating mailbox only open it, don't + bother syncing it. + + +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c + +2012-09-20 01:22:29 +0200 Stephan Bosch <stephan@rename-it.nl> (ed882314) + + lib-sieve: include extension: didn't get semantics of mixing optional and + non-optional includes for the same script quite right. + + +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-common.c + +2012-09-20 00:57:02 +0200 Stephan Bosch <stephan@rename-it.nl> (bb91536d) + + sieve-tools: The -D option wasn't enabled and documented for all tools. + Change backported from Pigeonhole v0.4 tree, which means that this change + will duplicate there upon merge. + + +M doc/man/sieve-dump.1.in +M doc/man/sievec.1.in +M src/sieve-tools/sieve-dump.c +M src/sieve-tools/sievec.c + +2012-09-20 00:54:17 +0200 Stephan Bosch <stephan@rename-it.nl> (349732f6) + + lib-sieve: include extension: fixed missing error cleanup that caused a + resource leak. + + +M src/lib-sieve/plugins/include/ext-include-binary.c + +2012-09-20 00:51:09 +0200 Stephan Bosch <stephan@rename-it.nl> (66dabb2f) + + Fixed a few resource leaks caused by previous change. + + +M src/lib-sieve/plugins/include/ext-include-binary.c + +2012-09-20 00:22:36 +0200 Stephan Bosch <stephan@rename-it.nl> (e09ca009) + + lib-sieve: Finished implementation of include extension. Added support for + the :optional tag of the include command. Changed Sieve script API in the + process; opening the script is now available as a separate step. + + +M Makefile.am +M README +M TODO +D doc/rfc/draft-ietf-sieve-include-05.txt +A doc/rfc/include.rfc6609.txt +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-script-dict.c +M src/lib-sieve/sieve-script-file.c +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve.c +M src/lib-sievestorage/sieve-storage-script.c +M src/managesieve/cmd-getscript.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +A tests/extensions/include/execute/optional.sieve +A tests/extensions/include/included/optional-1.sieve +A tests/extensions/include/included/optional-2.sieve +A tests/extensions/include/optional.svtest + +2012-09-20 00:18:10 +0200 Stephan Bosch <stephan@rename-it.nl> (9e05b84b) + + sieve-tools: The -D option wasn't enabled and documented for all tools. + + +M doc/man/sieve-dump.1.in +M doc/man/sievec.1.in +M src/sieve-tools/sieve-dump.c +M src/sieve-tools/sievec.c + +2012-09-19 22:44:10 +0200 Stephan Bosch <stephan@rename-it.nl> (c8e81d26) + + Last commit was quite inadequate. + + +M src/managesieve-login/managesieve-login-settings-plugin.c + +2012-09-19 21:59:08 +0200 Stephan Bosch <stephan@rename-it.nl> (db52d175) + + Updated to changes in Dovecot config API. + + +M src/managesieve-login/managesieve-login-settings-plugin.c + +2012-09-18 21:30:45 +0200 Stephan Bosch <stephan@rename-it.nl> (a69b29f2) + + Added signature for changeset 64474c359678 + + +M .hgsigs + +2012-09-18 21:29:16 +0200 Stephan Bosch <stephan@rename-it.nl> (37e477e4) + + Added tag 0.3.3 for changeset 64474c359678 + + +2012-09-18 21:29:11 +0200 Stephan Bosch <stephan@rename-it.nl> (4ad40fc1) + + Released v0.3.3 for Dovecot v2.1.10. + + +M NEWS +M configure.in + +2012-09-18 20:42:25 +0200 Stephan Bosch <stephan@rename-it.nl> (56c73516) + + Fixed compile against installed Dovecot headers. This was broken by the + ld.gold fix. + + +M src/lib-sieve/Makefile.am + +2012-09-18 16:20:22 +0200 Stephan Bosch <stephan@rename-it.nl> (89d4adbc) + + Added signature for changeset 265061e0d3f4 + + +M .hgsigs + +2012-09-18 16:13:09 +0200 Stephan Bosch <stephan@rename-it.nl> (2dc8ed62) + + Added tag 0.3.2 for changeset 265061e0d3f4 + + +2012-09-18 16:12:44 +0200 Stephan Bosch <stephan@rename-it.nl> (0102b7f1) + + Released v0.3.2 for Dovecot v2.1.9. + + +M configure.in + +2012-09-18 16:01:48 +0200 Stephan Bosch <stephan@rename-it.nl> (f212df40) + + Updated NEWS file for next release. + + +M NEWS + +2012-09-18 14:44:44 +0200 Stephan Bosch <stephan@rename-it.nl> (a7a64d56) + + Minor change to TODO. + + +M TODO + +2012-09-18 14:37:55 +0200 Stephan Bosch <stephan@rename-it.nl> (20aaacaf) + + lib-sieve: Added version numbers to Sieve extensions. Those version numbers + are now also stored in the binary, making sure it is recompiled when a new + version of an extension is used. This avoids updating the binary version for + minor changes to extensions and also makes this work for plugins. + + +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-extensions.h + +2012-09-18 14:02:12 +0200 Stephan Bosch <stephan@rename-it.nl> (17129d97) + + lib-sieve: Changed the way Sieve extensions are defined to a more compact + format. + + +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/date/ext-date.c +M src/lib-sieve/plugins/editheader/ext-editheader.c +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/environment/ext-environment.c +M src/lib-sieve/plugins/ihave/ext-ihave.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/mailbox/ext-mailbox.c +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/ext-vacation-seconds.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c +M src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-match-types.c +M src/testsuite/ext-testsuite.c + +2012-09-18 12:10:53 +0200 Stephan Bosch <stephan@rename-it.nl> (ca8505ea) + + lib-sieve: date extension: composition of iso8601 dates is moved to Dovecot. + + +M src/lib-sieve/plugins/date/ext-date-common.c + +2012-09-18 11:59:47 +0200 Stephan Bosch <stephan@rename-it.nl> (dbca1b6a) + + Updated to recent changes in Dovecot. + + +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/sieve-script-dict.c + +2012-09-09 10:45:46 +0200 Stephan Bosch <stephan@rename-it.nl> (40792452) + + sieve-refilter: improved man page documentation by explicitly specifying the + syntax used for mailbox arguments. + + +M doc/man/sieve-filter.1.in + +2012-09-06 09:00:59 +0200 Stephan Bosch <stephan@rename-it.nl> (6daa706c) + + Adjusted to buffer API change in Dovecot. + + +M src/managesieve/main.c + +2012-09-02 18:54:01 +0200 Stephan Bosch <stephan@rename-it.nl> (032ddf89) + + Small compile fix. + + +M src/lib-sieve/Makefile.am + +2012-08-29 19:35:17 +0200 Stephan Bosch <stephan@rename-it.nl> (ff9841b6) + + lib-sieve: fixed edit-mail istream to work with latest Dovecot. Testsuite + failed with an assertion, because the stream returned -2 at an unexpected + time. I've restructured the buffering implementation to prevent this. The + testsuite succeeds now, but this needs to be tested more thoroughly. + + +M src/lib-sieve/edit-mail.c + +2012-08-28 23:07:36 +0200 Stephan Bosch <stephan@rename-it.nl> (6fc44fad) + + Adjusted to changes in Dovecot istream API. + + +M src/lib-managesieve/managesieve-parser.c +M src/lib-sieve/edit-mail.c +M src/lib-sieve/sieve-lexer.c + +2012-08-20 09:13:32 +0200 Stephan Bosch <stephan@rename-it.nl> (52a41995) + + Adjusted to some more changes in Dovecot API. + + +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/sieve-extensions.c +M src/testsuite/testsuite-settings.c + +2012-08-20 08:43:55 +0200 Stephan Bosch <stephan@rename-it.nl> (c245aa45) + + Adjusted to changes in Dovecot API regarding arrays and hash tables. Also + contains a few other small fixes by Timo. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/edit-mail.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/ihave/ext-ihave-binary.c +M src/lib-sieve/plugins/ihave/ext-ihave-common.h +M src/lib-sieve/plugins/ihave/tst-ihave.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-stringlist.c +M src/lib-sieve/sieve-validator.c +M src/managesieve/cmd-putscript.c +M src/managesieve/managesieve-capabilities.c +M src/managesieve/managesieve-commands.c +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-settings.c +M src/testsuite/testsuite-smtp.c + +2012-08-16 22:28:06 +0200 Stephan Bosch <stephan@rename-it.nl> (7534c8c0) + + lib-sieve: spamvirustest: improved trace debugging of score calculation. + + +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c + +2012-08-15 00:55:05 +0200 Stephan Bosch <stephan@rename-it.nl> (e3d60566) + + sieve-tools: sievec and sieve-dump now ignore mail_uid and mail_gid settings + when run as root. Before, sievec and sieve-dump would switch to + mail_uid:mail_gid and then fail to compile/dump a root script. + + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/sieve-tools/sieve-dump.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/testsuite/testsuite.c + +2012-08-12 16:16:21 +0200 Stephan Bosch <stephan@rename-it.nl> (4dcfc2d4) + + lib-sieve: Adjusted edit-mail.c to changes in Dovecot mail storage API. + + +M src/lib-sieve/edit-mail.c + +2012-08-12 16:02:36 +0200 Stephan Bosch <stephan@rename-it.nl> (87759d7e) + + Merged changes from Pigeonhole v0.3. + + +2012-08-12 15:50:27 +0200 Stephan Bosch <stephan@rename-it.nl> (10986994) + + Removed trailing whitespace everywhere. + + +M AUTHORS +M COPYING +M INSTALL +M Makefile.am +M NEWS +M README +M TODO +M configure.in +M doc/devel/DESIGN +M doc/example-config/conf.d/20-managesieve.conf +M doc/example-config/conf.d/90-sieve.conf +M doc/extensions/editheader.txt +M doc/extensions/include.txt +M doc/extensions/spamtest-virustest.txt +M doc/extensions/vacation.txt +M doc/man/pigeonhole.7.in +M doc/man/sieve-dump.1.in +M doc/man/sieve-filter.1.in +M doc/man/sieve-test.1.in +M doc/man/sievec.1.in +M doc/script-location-dict.txt +M src/lib-managesieve/Makefile.am +M src/lib-managesieve/managesieve-arg.c +M src/lib-managesieve/managesieve-arg.h +M src/lib-managesieve/managesieve-parser.c +M src/lib-managesieve/managesieve-parser.h +M src/lib-managesieve/managesieve-quote.c +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/cmp-i-ascii-casemap.c +M src/lib-sieve/cmp-i-octet.c +M src/lib-sieve/edit-mail.c +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/Makefile.am +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/Makefile.am +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/ext-date-common.h +M src/lib-sieve/plugins/date/ext-date.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/editheader/cmd-addheader.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.c +M src/lib-sieve/plugins/editheader/ext-editheader-limits.h +M src/lib-sieve/plugins/editheader/ext-editheader.c +M src/lib-sieve/plugins/enotify/Makefile.am +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify-limits.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.h +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/environment/ext-environment-common.h +M src/lib-sieve/plugins/environment/ext-environment.c +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/ihave/ext-ihave-binary.c +M src/lib-sieve/plugins/ihave/ext-ihave-binary.h +M src/lib-sieve/plugins/ihave/ext-ihave-common.c +M src/lib-sieve/plugins/ihave/ext-ihave.c +M src/lib-sieve/plugins/ihave/tst-ihave.c +M src/lib-sieve/plugins/imap4flags/Makefile.am +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/mailbox/ext-mailbox.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.h +M src/lib-sieve/plugins/notify/ext-notify-limits.h +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/plugins/regex/ext-regex-common.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/Makefile.am +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/lib-sieve/plugins/vacation/ext-vacation-seconds.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/Makefile.am +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.h +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables-dump.h +M src/lib-sieve/plugins/variables/ext-variables-limits.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-name.h +M src/lib-sieve/plugins/variables/ext-variables-namespaces.c +M src/lib-sieve/plugins/variables/ext-variables-namespaces.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate-common.c +M src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate-common.h +M src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate.c +M src/lib-sieve/plugins/vnd.dovecot/duplicate/tst-duplicate.c +M src/lib-sieve/rfc2822.c +M src/lib-sieve/rfc2822.h +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary-code.c +M src/lib-sieve/sieve-binary-debug.c +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-objects.c +M src/lib-sieve/sieve-objects.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-plugins.c +M src/lib-sieve/sieve-plugins.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-runtime-trace.c +M src/lib-sieve/sieve-runtime-trace.h +M src/lib-sieve/sieve-runtime.h +M src/lib-sieve/sieve-script-dict.c +M src/lib-sieve/sieve-script-file.c +M src/lib-sieve/sieve-script-file.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-stringlist.c +M src/lib-sieve/sieve-stringlist.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c +M src/lib-sieve/tst-truefalse.c +M src/lib-sievestorage/Makefile.am +M src/lib-sievestorage/sieve-storage-list.c +M src/lib-sievestorage/sieve-storage-list.h +M src/lib-sievestorage/sieve-storage-private.h +M src/lib-sievestorage/sieve-storage-quota.c +M src/lib-sievestorage/sieve-storage-quota.h +M src/lib-sievestorage/sieve-storage-save.c +M src/lib-sievestorage/sieve-storage-script.c +M src/lib-sievestorage/sieve-storage.c +M src/lib-sievestorage/sieve-storage.h +M src/managesieve-login/client-authenticate.c +M src/managesieve-login/client.c +M src/managesieve-login/client.h +M src/managesieve-login/managesieve-login-settings-plugin.c +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve-login/managesieve-proxy.c +M src/managesieve/Makefile.am +M src/managesieve/cmd-capability.c +M src/managesieve/cmd-deletescript.c +M src/managesieve/cmd-getscript.c +M src/managesieve/cmd-listscripts.c +M src/managesieve/cmd-putscript.c +M src/managesieve/cmd-renamescript.c +M src/managesieve/cmd-setactive.c +M src/managesieve/managesieve-capabilities.c +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h +M src/managesieve/managesieve-commands.c +M src/managesieve/managesieve-quota.c +M src/managesieve/managesieve-settings.c +M src/plugins/lda-sieve/Makefile.am +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/Makefile.am +M src/sieve-tools/sieve-dump.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-result.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-arguments.c +M src/testsuite/testsuite-binary.c +M src/testsuite/testsuite-binary.h +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-result.h +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-script.h +M src/testsuite/testsuite-settings.c +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite-substitutions.c +M src/testsuite/testsuite-substitutions.h +M src/testsuite/testsuite-variables.c +M src/testsuite/testsuite-variables.h +M src/testsuite/testsuite.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-action.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c +M tests/compile/errors.svtest +M tests/compile/errors/address.sieve +M tests/compile/errors/envelope.sieve +M tests/compile/errors/if.sieve +M tests/compile/errors/keep.sieve +M tests/compile/errors/lexer.sieve +M tests/compile/errors/out-address.sieve +M tests/compile/errors/parser.sieve +M tests/compile/errors/require.sieve +M tests/compile/errors/size.sieve +M tests/compile/errors/tag.sieve +M tests/compile/errors/typos.sieve +M tests/compile/errors/unsupported.sieve +M tests/compile/recover.svtest +M tests/control-if.svtest +M tests/deprecated/notify/basic.svtest +M tests/deprecated/notify/mailto.svtest +M tests/execute/actions.svtest +M tests/execute/actions/redirect.sieve +M tests/execute/errors.svtest +M tests/execute/examples.svtest +M tests/execute/mailstore.svtest +M tests/extensions/body/basic.svtest +M tests/extensions/body/content.svtest +M tests/extensions/body/raw.svtest +M tests/extensions/date/basic.svtest +M tests/extensions/date/zones.svtest +M tests/extensions/editheader/addheader.svtest +M tests/extensions/editheader/alternating.svtest +M tests/extensions/editheader/deleteheader.svtest +M tests/extensions/editheader/errors.svtest +M tests/extensions/editheader/errors/command-syntax.sieve +M tests/extensions/editheader/protected.svtest +M tests/extensions/encoded-character.svtest +M tests/extensions/enotify/basic.svtest +M tests/extensions/enotify/errors/uri-mailto.sieve +M tests/extensions/enotify/mailto.svtest +M tests/extensions/enotify/valid_notify_method.svtest +M tests/extensions/envelope.svtest +M tests/extensions/environment/rfc.svtest +M tests/extensions/imap4flags/basic.svtest +M tests/extensions/imap4flags/execute.svtest +M tests/extensions/imap4flags/execute/flags-side-effect.sieve +M tests/extensions/imap4flags/hasflag.svtest +M tests/extensions/imap4flags/multiscript.svtest +M tests/extensions/include/execute.svtest +M tests/extensions/regex/basic.svtest +M tests/extensions/regex/match-values.svtest +M tests/extensions/relational/basic.svtest +M tests/extensions/relational/comparators.svtest +M tests/extensions/relational/errors/validation.sieve +M tests/extensions/relational/rfc.svtest +M tests/extensions/spamvirustest/spamtest.svtest +M tests/extensions/subaddress/basic.svtest +M tests/extensions/subaddress/rfc.svtest +M tests/extensions/vacation/execute.svtest +M tests/extensions/vacation/execute/no-handle.sieve +M tests/extensions/vacation/message.svtest +M tests/extensions/vacation/reply.svtest +M tests/extensions/vacation/utf-8.svtest +M tests/extensions/variables/basic.svtest +M tests/extensions/variables/errors/limits.sieve +M tests/extensions/variables/match.svtest +M tests/extensions/variables/modifiers.svtest +M tests/extensions/variables/quoting.svtest +M tests/extensions/variables/regex.svtest +M tests/extensions/variables/string.svtest +M tests/match-types/contains.svtest +M tests/match-types/is.svtest +M tests/match-types/matches.svtest +M tests/multiscript/basic.svtest +M tests/multiscript/conflicts.svtest +M tests/test-address.svtest +M tests/test-allof.svtest +M tests/test-anyof.svtest +M tests/test-exists.svtest +M tests/test-header.svtest +M tests/testsuite.svtest + +2012-08-09 23:01:43 +0200 Stephan Bosch <stephan@rename-it.nl> (9dc2b1c1) + + Merged changes from Pigeonhole v0.3 tree. + + +2012-08-09 22:58:53 +0200 Stephan Bosch <stephan@rename-it.nl> (0cfb762d) + + Created specification for the vnd.dovecot.debug extension. Also fixed a + small mistake in the spefication for the vnd.dovecot.duplicate extension. + + +A doc/rfc/spec-bosch-sieve-debug.txt +A doc/rfc/xml/reference.VARIABLES.xml +A doc/rfc/xml/spec-bosch-sieve-debug.xml +M doc/rfc/xml/spec-bosch-sieve-duplicate.xml + +2012-08-07 00:36:11 +0200 Stephan Bosch <stephan@rename-it.nl> (68353bbc) + + lib-sieve: increase action instance count (for limit checking) only when an + action is actually created. + + +M src/lib-sieve/sieve-result.c + +2012-08-07 00:34:12 +0200 Stephan Bosch <stephan@rename-it.nl> (2ce4a474) + + lib-sieve: fixed potential action duplication bug. + + +M src/lib-sieve/sieve-result.c + +2012-08-06 23:14:19 +0200 Stephan Bosch <stephan@rename-it.nl> (ba927a91) + + lib-sieve: made action limit error messages more verbose. + + +M src/lib-sieve/sieve-result.c + +2012-08-05 18:42:12 +0200 Stephan Bosch <stephan@rename-it.nl> (93c6c79b) + + Testsuite: fixed compiler warning. + + +M src/testsuite/testsuite-variables.c + +2012-08-05 00:30:14 +0200 Stephan Bosch <stephan@rename-it.nl> (b06f10dd) + + Testsuite: added support for executing sub-scripts and added tst variables + namespace. Added test for interaction between include extension and dict + script location support. + + +M src/testsuite/Makefile.am +M src/testsuite/cmd-test-binary.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-script.h +A src/testsuite/testsuite-variables.c +A src/testsuite/testsuite-variables.h +M src/testsuite/testsuite.c +M tests/extensions/include/execute.svtest +A tests/extensions/include/execute/namespace.sieve +A tests/extensions/include/included-global/namespace.dict +A tests/extensions/include/included/namespace.dict + +2012-08-04 09:34:21 +0200 Stephan Bosch <stephan@rename-it.nl> (aedfe1ee) + + Testsuite: fixed displaying debug messages. + + +M src/testsuite/testsuite-log.c + +2012-08-03 19:52:36 +0200 Stephan Bosch <stephan@rename-it.nl> (14877e2b) + + Include: fixed namespace separation of :global and :personal scripts. Sieve + script equality function implementation was wrong. + + +M src/lib-sieve/sieve-script-dict.c +M src/lib-sieve/sieve-script-file.c +M src/lib-sieve/sieve-script.c +M tests/extensions/include/execute.svtest +A tests/extensions/include/included-global/namespace.sieve +A tests/extensions/include/included/namespace.sieve + +2012-07-31 01:24:28 +0200 Stephan Bosch <stephan@rename-it.nl> (c882d9ee) + + Merged changes from Pigeonhole v0.2 tree. + + +2012-07-31 01:18:15 +0200 Stephan Bosch <stephan@rename-it.nl> (6beefee9) + + Fix linkage with ld.gold. Patch by Eray Aslan. + + +M src/lib-sieve/Makefile.am + +2012-07-30 10:14:42 +0200 Stephan Bosch <stephan@rename-it.nl> (a2d3329a) + + Fixed several Clang compile warnings and a few potential bugs. Patch by Timo + Sirainen. + + +M src/lib-sieve/rfc2822.h +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-runtime-trace.c +M src/lib-sieve/sieve-runtime-trace.h +M src/lib-sievestorage/sieve-storage.c +M src/testsuite/testsuite-log.c + +2012-07-25 09:08:11 +0200 Stephan Bosch <stephan@rename-it.nl> (7d1fd8e3) + + Editheader: name of added header is now first sanitized to have capital + letters where conventional. + + +M src/lib-sieve/plugins/editheader/cmd-addheader.c + +2012-07-16 21:36:23 +0200 Stephan Bosch <stephan@rename-it.nl> (24e432c4) + + Example config: disabled default sections for managesieve and + managesieve-login services. This currently breaks uninstall when the + settings plugins are removed and 20-managesieve.conf remains in conf.d + directory. These sections only need to be active in the config file when + settings for the services themselves need to be disabled. + + +M doc/example-config/conf.d/20-managesieve.conf + +2012-07-13 10:06:46 +0200 Stephan Bosch <stephan@rename-it.nl> (8ba3be21) + + ManageSieve: fixed segfault caused by Dovecot API change. + + +M src/lib-managesieve/managesieve-parser.c + +2012-07-13 00:57:00 +0200 Stephan Bosch <stephan@rename-it.nl> (f27c14e2) + + Merged changes from Dovecot v2.1. + + +2012-07-12 23:57:50 +0200 Stephan Bosch <stephan@rename-it.nl> (b26b4408) + + ManageSieve: fixed segfault bug triggered by CHECKSCRIPT command. + + +M src/lib-sievestorage/sieve-storage-save.c + +2012-07-12 23:40:52 +0200 Stephan Bosch <stephan@rename-it.nl> (db63d938) + + Adjusted to Dovecot API changes. + + +M src/lib-managesieve/managesieve-parser.c +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve/edit-mail.c + +2012-05-26 00:16:35 +0200 Stephan Bosch <stephan@rename-it.nl> (416ee290) + + Added signature for changeset e9ed5d5cef4b + + +M .hgsigs + +2012-05-26 00:14:18 +0200 Stephan Bosch <stephan@rename-it.nl> (b65bde7e) + + Added tag 0.3.1 for changeset e9ed5d5cef4b + + +2012-05-26 00:14:05 +0200 Stephan Bosch <stephan@rename-it.nl> (28ac609c) + + Released v0.3.1 for Dovecot v2.1.6. + + +M NEWS +M configure.in + +2012-05-20 12:16:43 +0200 Stephan Bosch <stephan@rename-it.nl> (e60a6449) + + Merged changes from Pigeonhole v0.2 tree. + + +2012-05-20 12:06:25 +0200 Stephan Bosch <stephan@rename-it.nl> (7f017b49) + + Merged changes from Pigeonhole v0.2 tree. + + +2012-05-20 11:33:49 +0200 Stephan Bosch <stephan@rename-it.nl> (7f2b3f53) + + Merged minor changes from Pigeonhole v0.2 tree (causes a few duplicate + commit messages). + + +2012-05-11 02:54:42 +0200 Stephan Bosch <stephan@rename-it.nl> (8c8d51e5) + + Incorporated sieve_duplicate plugin into main Pigeonhole tree as a normal + extension (vnd.dovecot.duplicate). Also restructured doc dir a bit in the + process. + + +M INSTALL +M Makefile.am +M configure.in +M doc/Makefile.am +R100 doc/editheader.txt doc/extensions/editheader.txt +R100 doc/include.txt doc/extensions/include.txt +R100 doc/spamtest-virustest.txt doc/extensions/spamtest-virustest.txt +R100 doc/vacation.txt doc/extensions/vacation.txt +A doc/extensions/vnd.dovecot.duplicate.txt +A doc/rfc/Makefile.am +A doc/rfc/spec-bosch-sieve-duplicate.txt +A doc/rfc/xml/reference.KEYWORDS.xml +A doc/rfc/xml/reference.SIEVE.xml +A doc/rfc/xml/spec-bosch-sieve-duplicate.xml +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/vnd.dovecot/Makefile.am +A src/lib-sieve/plugins/vnd.dovecot/duplicate/Makefile.am +A src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate-common.c +A src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate-common.h +A src/lib-sieve/plugins/vnd.dovecot/duplicate/ext-duplicate.c +A src/lib-sieve/plugins/vnd.dovecot/duplicate/tst-duplicate.c +M src/lib-sieve/sieve-extensions.c +A tests/extensions/vnd.dovecot/duplicate/errors.svtest +A tests/extensions/vnd.dovecot/duplicate/errors/syntax.sieve +A tests/extensions/vnd.dovecot/duplicate/execute.svtest + +2012-05-11 02:45:33 +0200 Stephan Bosch <stephan@rename-it.nl> (568d37a7) + + Fixed compiler warning. + + +M src/lib-sieve/sieve-validator.c + +2012-05-04 11:40:39 +0200 Stephan Bosch <stephan@rename-it.nl> (f34cbfcc) + + LDA Sieve plugin: fixed sieve_before bug that made it only work when + mail_debug=yes. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2012-05-02 01:17:49 +0200 Stephan Bosch <stephan@rename-it.nl> (8dd6c6a0) + + Fixed several small issues, including a few potential segfault bugs, based + on static analysis. Clang static analyzer is happy now. + + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/edit-mail.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-namespaces.c +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve.c +M src/lib-sievestorage/sieve-storage-quota.c +M src/managesieve-login/managesieve-login-settings-plugin.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-dump.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/testsuite/cmd-test-message.c +M src/testsuite/testsuite.c + +2012-04-30 09:10:44 +0200 Stephan Bosch <stephan@rename-it.nl> (ae68404f) + + Added support for specifying multiple sieve_before and sieve_after paths. + Additional paths are specified by adding a sequence number (starting at 2) + to the setting name. Added support for specifying home-relative paths for + sieve_before and sieve_after. This enables administrators to specify + user-specific global Sieve scripts that cannot be viewed or changed by + virtual users. + + +M INSTALL +M README +M doc/example-config/conf.d/90-sieve.conf +M src/lib-sieve/sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2012-04-27 02:28:13 +0200 Stephan Bosch <stephan@rename-it.nl> (2881344a) + + Fixed segfault bug. Forgot to change Sieve SMTP API to use scriptenv in + stead of script_context directly. + + +M src/lib-sieve/sieve-smtp.c + +2012-04-24 19:33:19 +0200 Stephan Bosch <stephan@rename-it.nl> (4a9c81b9) + + sievec tool: fixed segfault bug and another bug making it omit actually + saving the binary. + + +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-script-file.c +M src/lib-sieve/sieve.c + +2012-04-24 13:08:36 +0200 Stephan Bosch <stephan@rename-it.nl> (00d405f0) + + lib-managesieve: changed EPROTO error to EIO in ManageSieve string stream + because it is apparently not known in BSD. + + +M src/lib-managesieve/managesieve-parser.c +M src/managesieve-login/client-authenticate.c +M src/managesieve/cmd-putscript.c + +2012-04-22 17:16:08 +0200 Stephan Bosch <stephan@rename-it.nl> (ca89209f) + + lib-sieve: fixed cleanup bug in dict script implementation. + + +M src/lib-sieve/sieve-script-dict.c +M src/lib-sieve/sieve-script.c + +2012-04-22 15:36:06 +0200 Stephan Bosch <stephan@rename-it.nl> (767f2b5d) + + Finished documentation example for SQL dict script location type. + + +M doc/script-location-dict.txt + +2012-04-22 15:11:14 +0200 Stephan Bosch <stephan@rename-it.nl> (b714ae82) + + LDA Sieve: fixed bug in debug message. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2012-04-22 11:30:28 +0200 Stephan Bosch <stephan@rename-it.nl> (70256226) + + Added support for retrieving Sieve scripts from dict lookup. - Built + generic interface for alternative script sources. - Implemented dict + script location. NOTE: ManageSieve will not work with this yet, nor will + sieve_before/sieve_after. + + +M INSTALL +M TODO +A doc/script-location-dict.txt +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +A src/lib-sieve/sieve-script-dict.c +A src/lib-sieve/sieve-script-file.c +A src/lib-sieve/sieve-script-file.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sievestorage/sieve-storage-list.c +M src/lib-sievestorage/sieve-storage-quota.c +M src/lib-sievestorage/sieve-storage-save.c +M src/lib-sievestorage/sieve-storage-script.c +M src/lib-sievestorage/sieve-storage.c +M src/managesieve/cmd-getscript.c +M src/managesieve/managesieve-capabilities.c +M src/managesieve/managesieve-client.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/testsuite/testsuite-binary.c +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite.c +M tests/extensions/environment/basic.svtest + +2012-03-26 21:07:14 +0200 Stephan Bosch <stephan@rename-it.nl> (215eb1ee) + + Updated dovecot.m4. + + +M m4/dovecot.m4 + +2012-03-19 22:33:12 +0100 Stephan Bosch <stephan@rename-it.nl> (e5a3004b) + + sieve-tools: forgot to enable debug in error handlers. + + +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c + +2012-03-15 21:29:33 +0100 Stephan Bosch <stephan@rename-it.nl> (d2978b65) + + managesieve-login: fixed x86 compile warning. + + +M src/managesieve-login/client-authenticate.c + +2012-03-08 11:02:05 +0100 Stephan Bosch <stephan@rename-it.nl> (389e72ee) + + Added a "session ID" string for managesieve connections, available in + %{session} variable. This change matches a similar change in Dovecot for + IMAP/POP3. Also includes other small changes that make ManageSieve match + IMAP implementation a little more closely. + + +M src/managesieve/main.c +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h +M src/managesieve/managesieve-common.h + +2012-03-07 22:04:06 +0100 Stephan Bosch <stephan@rename-it.nl> (b00f1672) + + Gave stamp.h.in some content to prevent it from disappearing in patch files. + + +M stamp.h.in + +2012-02-29 22:51:56 +0100 Stephan Bosch <stephan@rename-it.nl> (985dbe10) + + Adjusted Sieve implementation and testsuite to Dovecot's new + smtp_client_open() API. + + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/edit-mail.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/rfc2822.c +M src/lib-sieve/rfc2822.h +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-smtp.c +M src/lib-sieve/sieve-smtp.h +M src/lib-sieve/sieve-types.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h + +2012-02-29 20:07:24 +0100 Stephan Bosch <stephan@rename-it.nl> (cf5d3ac8) + + Fixed bug that caused SunStudio CC compile failure (reported by Piotr + Tarnowski). + + +M src/lib-sieve/sieve.c + +2012-02-29 20:07:24 +0100 Stephan Bosch <stephan@rename-it.nl> (36ffcba3) + + Fixed bug that caused SunStudio CC compile failure (reported by Piotr + Tarnowski). + + +M src/lib-sieve/sieve.c + +2012-02-22 21:43:35 +0100 Stephan Bosch <stephan@rename-it.nl> (6dde8d4a) + + lib-sieve: made error handler part of public runtime environment. + + +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-runtime.h + +2012-02-22 21:43:35 +0100 Stephan Bosch <stephan@rename-it.nl> (cf2e9e48) + + lib-sieve: made error handler part of public runtime environment. + + +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-runtime.h + +2012-02-16 22:07:32 +0100 Stephan Bosch <stephan@rename-it.nl> (4b97b4b7) + + Added signature for changeset fe7bd7ee6c2e + + +M .hgsigs + +2012-02-16 22:02:56 +0100 Stephan Bosch <stephan@rename-it.nl> (5edd59df) + + Added tag 0.3.0 for changeset fe7bd7ee6c2e + + +2012-02-16 22:02:35 +0100 Stephan Bosch <stephan@rename-it.nl> (eb0b1b2a) + + Released v0.3.0 for Dovecot v2.1.0. + + +M NEWS + +2012-02-13 00:01:30 +0100 Stephan Bosch <stephan@rename-it.nl> (18eed660) + + Applied sieve-body-fix.patch. Fixes behavior of body test with multipart + MIME body parts. Testsuite needs to be extended accordingly. + + +M TODO +M src/lib-sieve/plugins/body/ext-body-common.c + +2012-02-12 23:53:31 +0100 Stephan Bosch <stephan@rename-it.nl> (dc004ab1) + + Updated to Dovecot v2.2. Updated version number to v0.4.0 and added a + warning to configure. Applied generic-login.patch. + + +M configure.in +M src/managesieve-login/client-authenticate.c +M src/managesieve-login/client-authenticate.h +M src/managesieve-login/client.c +M src/managesieve-login/client.h +M src/managesieve-login/managesieve-proxy.c +M src/managesieve-login/managesieve-proxy.h + +2012-01-28 14:25:41 +0100 Stephan Bosch <stephan@rename-it.nl> (9f516ae0) + + ManageSieve: cleaned up parser and updated it to match newer structure of + imap parser. + + +M src/lib-managesieve/Makefile.am +A src/lib-managesieve/managesieve-arg.c +A src/lib-managesieve/managesieve-arg.h +M src/lib-managesieve/managesieve-parser.c +M src/lib-managesieve/managesieve-parser.h +M src/managesieve-login/client-authenticate.c +M src/managesieve-login/client-authenticate.h +M src/managesieve-login/client.c +M src/managesieve-login/managesieve-proxy.c +M src/managesieve/cmd-havespace.c +M src/managesieve/cmd-noop.c +M src/managesieve/cmd-putscript.c +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h + +2012-01-27 18:57:42 +0100 Stephan Bosch <stephan@rename-it.nl> (74b3be42) + + managesieve-login: matched proxy and auth_verbose changes in Dovecot. + + +M src/managesieve-login/managesieve-proxy.c + +2012-01-27 17:22:17 +0100 Stephan Bosch <stephan@rename-it.nl> (c4734e6a) + + testsuite: fixed compile warning. + + +M src/testsuite/cmd-test-message.c + +2012-01-23 00:43:37 +0100 Stephan Bosch <stephan@rename-it.nl> (a1ef6659) + + ManageSieve: fixed quota problem in previous change. + + +M src/managesieve/cmd-putscript.c + +2012-01-22 21:57:45 +0100 Stephan Bosch <stephan@rename-it.nl> (7f428312) + + ManageSieve: added support for reading quoted and literal strings as a + stream. Fixes support for handing large SASL responses. Also resolves + long-standing FIXME regarding the second parameter of PUTSCRIPT: it can now + be a quoted string. Includes a few small changes in the login daemon that + were done in the dovecot equivalents before. + + +M src/lib-managesieve/managesieve-parser.c +M src/lib-managesieve/managesieve-parser.h +M src/lib-sievestorage/sieve-storage-quota.c +M src/lib-sievestorage/sieve-storage-quota.h +M src/managesieve-login/client-authenticate.c +M src/managesieve-login/client.c +M src/managesieve-login/client.h +M src/managesieve-login/managesieve-proxy.c +M src/managesieve/cmd-putscript.c +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-quota.c +M src/managesieve/managesieve-quota.h + +2012-01-20 22:26:53 +0100 Stephan Bosch <stephan@rename-it.nl> (b684406b) + + managesieve: Added -t parameter to specify post-login script timeout + (Dovecot change). + + +M src/managesieve/main.c + +2012-01-12 18:43:13 +0100 Stephan Bosch <stephan@rename-it.nl> (b55a8548) + + managesieve-login: Include hostname and timestamp in "temporary auth + failure" message. + + +M src/managesieve-login/client-authenticate.c + +2012-01-07 16:35:56 +0100 Stephan Bosch <stephan@rename-it.nl> (2e952941) + + Updated copyright notices to include year 2012. + + +M doc/man/pigeonhole.7.in +M doc/man/sieve-dump.1.in +M doc/man/sieve-filter.1.in +M doc/man/sieve-test.1.in +M doc/man/sievec.1.in +M src/lib-managesieve/managesieve-parser.c +M src/lib-managesieve/managesieve-parser.h +M src/lib-managesieve/managesieve-quote.c +M src/lib-managesieve/managesieve-quote.h +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/mail-raw.h +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/cmp-i-ascii-casemap.c +M src/lib-sieve/cmp-i-octet.c +M src/lib-sieve/edit-mail.c +M src/lib-sieve/edit-mail.h +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/copy/sieve-ext-copy.h +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/ext-date-common.h +M src/lib-sieve/plugins/date/ext-date.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/editheader/cmd-addheader.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.h +M src/lib-sieve/plugins/editheader/ext-editheader-limits.h +M src/lib-sieve/plugins/editheader/ext-editheader.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify-limits.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.h +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/environment/ext-environment-common.h +M src/lib-sieve/plugins/environment/ext-environment.c +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/ihave/cmd-error.c +M src/lib-sieve/plugins/ihave/ext-ihave-binary.c +M src/lib-sieve/plugins/ihave/ext-ihave-binary.h +M src/lib-sieve/plugins/ihave/ext-ihave-common.c +M src/lib-sieve/plugins/ihave/ext-ihave-common.h +M src/lib-sieve/plugins/ihave/ext-ihave.c +M src/lib-sieve/plugins/ihave/tst-ihave.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-limits.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/mailbox/ext-mailbox-common.h +M src/lib-sieve/plugins/mailbox/ext-mailbox.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.h +M src/lib-sieve/plugins/notify/ext-notify-limits.h +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/plugins/regex/ext-regex-common.c +M src/lib-sieve/plugins/regex/ext-regex-common.h +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/lib-sieve/plugins/vacation/ext-vacation-seconds.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.h +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables-dump.h +M src/lib-sieve/plugins/variables/ext-variables-limits.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-name.c +M src/lib-sieve/plugins/variables/ext-variables-name.h +M src/lib-sieve/plugins/variables/ext-variables-namespaces.c +M src/lib-sieve/plugins/variables/ext-variables-namespaces.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug-common.h +M src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c +M src/lib-sieve/rfc2822.c +M src/lib-sieve/rfc2822.h +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary-code.c +M src/lib-sieve/sieve-binary-debug.c +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-objects.c +M src/lib-sieve/sieve-objects.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-plugins.c +M src/lib-sieve/sieve-plugins.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-runtime-trace.c +M src/lib-sieve/sieve-runtime-trace.h +M src/lib-sieve/sieve-runtime.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve-smtp.c +M src/lib-sieve/sieve-smtp.h +M src/lib-sieve/sieve-stringlist.c +M src/lib-sieve/sieve-stringlist.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c +M src/lib-sieve/tst-truefalse.c +M src/lib-sievestorage/sieve-storage-list.c +M src/lib-sievestorage/sieve-storage-list.h +M src/lib-sievestorage/sieve-storage-private.h +M src/lib-sievestorage/sieve-storage-quota.c +M src/lib-sievestorage/sieve-storage-quota.h +M src/lib-sievestorage/sieve-storage-save.c +M src/lib-sievestorage/sieve-storage-save.h +M src/lib-sievestorage/sieve-storage-script.c +M src/lib-sievestorage/sieve-storage-script.h +M src/lib-sievestorage/sieve-storage.c +M src/lib-sievestorage/sieve-storage.h +M src/managesieve-login/client-authenticate.c +M src/managesieve-login/client-authenticate.h +M src/managesieve-login/client.c +M src/managesieve-login/client.h +M src/managesieve-login/managesieve-login-settings-plugin.c +M src/managesieve-login/managesieve-login-settings-plugin.h +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve-login/managesieve-login-settings.h +M src/managesieve-login/managesieve-proxy.c +M src/managesieve-login/managesieve-proxy.h +M src/managesieve/cmd-capability.c +M src/managesieve/cmd-deletescript.c +M src/managesieve/cmd-getscript.c +M src/managesieve/cmd-havespace.c +M src/managesieve/cmd-listscripts.c +M src/managesieve/cmd-logout.c +M src/managesieve/cmd-noop.c +M src/managesieve/cmd-putscript.c +M src/managesieve/cmd-renamescript.c +M src/managesieve/cmd-setactive.c +M src/managesieve/main.c +M src/managesieve/managesieve-capabilities.c +M src/managesieve/managesieve-capabilities.h +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h +M src/managesieve/managesieve-commands.c +M src/managesieve/managesieve-commands.h +M src/managesieve/managesieve-common.h +M src/managesieve/managesieve-quota.c +M src/managesieve/managesieve-quota.h +M src/managesieve/managesieve-settings.c +M src/managesieve/managesieve-settings.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/plugins/lda-sieve/lda-sieve-plugin.h +M src/sieve-tools/sieve-dump.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-result.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-arguments.c +M src/testsuite/testsuite-arguments.h +M src/testsuite/testsuite-binary.c +M src/testsuite/testsuite-binary.h +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-log.h +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-result.h +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-script.h +M src/testsuite/testsuite-settings.c +M src/testsuite/testsuite-settings.h +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite-substitutions.c +M src/testsuite/testsuite-substitutions.h +M src/testsuite/testsuite.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-action.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c + +2012-01-07 16:01:10 +0100 Stephan Bosch <stephan@rename-it.nl> (204f7fb0) + + LDA Sieve plugin: renamed sieve_global_path setting to sieve_default for + clarity. Old name is now deprecated. Support for the even older + global_script_path name for this setting is dropped. + + +M INSTALL +M README +M doc/example-config/conf.d/90-sieve.conf +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2012-01-07 12:42:01 +0100 Stephan Bosch <stephan@rename-it.nl> (ca3aa5d2) + + lib-sieve: added means to prohibit use of redirect action. Setting + sieve_max_redirects=0 now means that redirects are prohibited rather than + unlimited. Now there is always a limit, but it can be enormous if the + administrator wants to. + + +M INSTALL +M doc/example-config/conf.d/90-sieve.conf +M src/lib-sieve/cmd-redirect.c + +2012-01-06 23:20:59 +0100 Stephan Bosch <stephan@rename-it.nl> (2683ec85) + + Fixed indentation problems in documentation. + + +M INSTALL +M doc/editheader.txt +M doc/include.txt +M doc/spamtest-virustest.txt +M doc/vacation.txt + +2012-01-06 23:03:12 +0100 Stephan Bosch <stephan@rename-it.nl> (a7ce01ed) + + Updated documentation and example config. + + +M doc/editheader.txt +M doc/example-config/conf.d/20-managesieve.conf +M doc/example-config/conf.d/90-sieve.conf +M doc/spamtest-virustest.txt +M doc/vacation.txt + +2011-12-27 22:21:34 +0100 Stephan Bosch <stephan@rename-it.nl> (ae679d44) + + lib-sieve: fixed bug in message snapshots. Message substitutions would not + always cause a proper snapshot. + + +M src/lib-sieve/sieve-message.c + +2011-12-27 21:29:19 +0100 Stephan Bosch <stephan@rename-it.nl> (68615e53) + + lib-sieve: fixed memory leak in previous change. + + +M src/lib-sieve/sieve-message.c + +2011-12-27 21:11:49 +0100 Stephan Bosch <stephan@rename-it.nl> (216f8883) + + lib-sieve: added support for substituting the entire message. This is needed + for the new extprograms plugin. + + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/testsuite/testsuite-message.c + +2011-12-27 11:56:25 +0100 Stephan Bosch <stephan@rename-it.nl> (6b3cd6de) + + lib-sieve-tool: mail_raw: started using mail_temp_dir setting. + + +M src/lib-sieve-tool/mail-raw.c + +2011-12-20 20:05:21 +0100 Stephan Bosch <stephan@rename-it.nl> (c527430b) + + lib-sieve: adjusted code fetch api for handling omitted operands better. + Removes quite a bit of duplicated source code. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h + +2011-12-17 18:58:48 +0100 Stephan Bosch <stephan@rename-it.nl> (afeb564b) + + lib-sieve: made uniform scriptname <-> filename conversion functions. This + puts the ".sieve" and ".svbin" file extension definitions in a single + locatio. IMPORTANT: this fixes a bug in the include extension that + implicitly mapped script names like "name.sieve" to "name". + + +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve.c +M src/lib-sievestorage/sieve-storage-list.c +M src/lib-sievestorage/sieve-storage-quota.c +M src/lib-sievestorage/sieve-storage-save.c +M src/lib-sievestorage/sieve-storage-script.c +M src/lib-sievestorage/sieve-storage-script.h +M src/lib-sievestorage/sieve-storage.c +M src/sieve-tools/sievec.c +M src/testsuite/testsuite-binary.c +M tests/extensions/include/errors/circular-1.sieve +M tests/extensions/include/errors/circular-2.sieve +M tests/extensions/include/included/circular-one.sieve +M tests/extensions/include/included/circular-three-2.sieve +M tests/extensions/include/included/circular-three.sieve +M tests/extensions/include/included/circular-two.sieve +M tests/extensions/include/included/once-2.sieve +M tests/extensions/include/included/twice-2.sieve + +2011-12-17 16:07:16 +0100 Stephan Bosch <stephan@rename-it.nl> (ab5ab2d8) + + lib-managesieve-storage: added code to cleanup tmp directory every once in a + while. This is borrowed from Dovecot's lib-storage/index/maildir. + + +M src/lib-sievestorage/sieve-storage-private.h +M src/lib-sievestorage/sieve-storage.c + +2011-12-17 15:04:59 +0100 Stephan Bosch <stephan@rename-it.nl> (8e9c7953) + + Fixed interaction of Sieve include extension with ManageSieve. Upon upload, + the include extension is more lenient towards circular includes and missing + scripts as required by RFC. The script is now also verified upon SETACTIVE + when it was not active before. However, this new SETACTIVE behavior is not + optimal for the situation where the active script was updated with PUTSCRIPT + and contains an nonexistent include (ignored during upload). This can still + cause runtime errors, since an already active script is not verified again + during SETACTIVE. + + +M TODO +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c +M src/lib-sievestorage/sieve-storage-save.c +M src/lib-sievestorage/sieve-storage-save.h +M src/lib-sievestorage/sieve-storage-script.c +M src/lib-sievestorage/sieve-storage-script.h +M src/managesieve/cmd-putscript.c +M src/managesieve/cmd-setactive.c + +2011-12-17 14:47:23 +0100 Stephan Bosch <stephan@rename-it.nl> (6469f6e6) + + lib-sieve: fixed copy-paste error in sieve_get_warnings() It returned the + number of errors in stead of the number of warnings. + + +M src/lib-sieve/sieve-error.c + +2011-12-17 00:08:01 +0100 Stephan Bosch <stephan@rename-it.nl> (3c4d93f2) + + Updated man pages. + + +M doc/man/pigeonhole.7.in +M doc/man/sieve-dump.1.in +M doc/man/sieve-filter.1.in +M doc/man/sieve-test.1.in +M doc/man/sievec.1.in + +2011-12-16 23:40:34 +0100 Stephan Bosch <stephan@rename-it.nl> (826318f8) + + lib-sieve: made sure that modified messages are not stored in the source + mailbox when it was opened read-only. This is currently only relevant for + the sieve-filter tool to avoid duplicating messages in the source folder. + This can happen when the messages are modified (e.g. by the editheader + extension) and the source folder is opened read-only, thus preventing + deletion of the original message. + + +M src/lib-sieve/edit-mail.c +M src/lib-sieve/sieve-actions.c + +2011-12-12 21:27:59 +0100 Stephan Bosch <stephan@rename-it.nl> (be8cf864) + + lib-sieve: store action: copy flags and keywords from input mail, also when + imap4flags extension is not active. This is currently only relevant for + sieve-filter, which now properly preserves flags with this change. + + +M src/lib-sieve/sieve-actions.c + +2011-12-12 09:01:53 +0100 Stephan Bosch <stephan@rename-it.nl> (ce44f0e0) + + Updated man pages with recent extension configuration changes. + + +M doc/man/sieve-dump.1.in +M doc/man/sieve-filter.1.in +M doc/man/sieve-test.1.in +M doc/man/sievec.1.in + +2011-12-12 00:49:22 +0100 Stephan Bosch <stephan@rename-it.nl> (92dff71e) + + Updated TODO. + + +M TODO + +2011-12-12 00:46:59 +0100 Stephan Bosch <stephan@rename-it.nl> (9ffcf2d8) + + lib-sieve: added support for restricting certain extensions to + (admin-controled) global scripts - Added sieve_global_extensions setting. + + +M INSTALL +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/plugins/ihave/ext-ihave-binary.c +M src/lib-sieve/plugins/ihave/tst-ihave.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-plugins.c +M src/lib-sieve/sieve-runtime.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/managesieve/cmd-putscript.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite.c + +2011-12-12 00:25:47 +0100 Stephan Bosch <stephan@rename-it.nl> (c93b0aee) + + lib-sieve: made sure error locations never report `line 0'. + + +M src/lib-sieve/sieve-error.c + +2011-12-12 00:23:04 +0100 Stephan Bosch <stephan@rename-it.nl> (a4372719) + + lib-sieve: fixed potention segfault occuring when interpreter initialization + fails. + + +M src/lib-sieve/sieve.c + +2011-12-07 22:59:14 +0100 Stephan Bosch <stephan@rename-it.nl> (d28ae8d8) + + Completed sieve-filter tool to a useful state. - Now compiles regularly + without --with-unfinished-features - Still experimental though, so be + careful. - Changed command structure a bit, removing the useless -M option. + + +M TODO +M doc/man/Makefile.am +M doc/man/sieve-filter.1.in +M src/sieve-tools/Makefile.am +M src/sieve-tools/sieve-filter.c + +2011-12-05 22:28:54 +0100 Stephan Bosch <stephan@rename-it.nl> (3a40223e) + + lib-sieve: fixed -Wunused-but-set-variable compiler warning in edit-mail.c. + + +M src/lib-sieve/edit-mail.c + +2011-11-29 22:47:13 +0100 Stephan Bosch <stephan@rename-it.nl> (8f1242ad) + + lib-sieve: implementation of editheader extension completed - Updated + documentation. - Made editheader extension disabled by default + + +M INSTALL +M TODO +A doc/editheader.txt +M src/lib-sieve/sieve-extensions.c + +2011-11-29 22:21:13 +0100 Stephan Bosch <stephan@rename-it.nl> (eef4dfb5) + + lib-sieve: editheader: implemented configurable length limit. + + +M TODO +M src/lib-sieve/plugins/editheader/Makefile.am +M src/lib-sieve/plugins/editheader/cmd-addheader.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.h +A src/lib-sieve/plugins/editheader/ext-editheader-limits.h +M tests/extensions/editheader/errors.svtest +A tests/extensions/editheader/errors/size-limit-runtime.sieve +A tests/extensions/editheader/errors/size-limit.sieve + +2011-11-29 01:10:32 +0100 Stephan Bosch <stephan@rename-it.nl> (0525a3ba) + + testsuite: editheader: fixed test name for command syntax checks. + + +M tests/extensions/editheader/errors.svtest + +2011-11-29 01:09:27 +0100 Stephan Bosch <stephan@rename-it.nl> (482a640e) + + lib-sieve: vacation: made vacation action header checks use the modified + message (editheader). + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2011-11-29 00:57:27 +0100 Stephan Bosch <stephan@rename-it.nl> (b44d9b1d) + + testsuite: editheader: added command syntax checks. + + +M TODO +M tests/extensions/editheader/errors.svtest +A tests/extensions/editheader/errors/command-syntax.sieve + +2011-11-28 23:32:14 +0100 Stephan Bosch <stephan@rename-it.nl> (be2eed8c) + + lib-sieve: editheader: made deleteheader match ignore leading and trailing + whitespace. + + +M src/lib-sieve/edit-mail.c +M tests/extensions/editheader/deleteheader.svtest + +2011-11-28 22:13:18 +0100 Stephan Bosch <stephan@rename-it.nl> (b10608f7) + + lib-sieve: editheader: added simple configuration for protected headers. + + +M Makefile.am +M TODO +M src/lib-sieve/plugins/editheader/Makefile.am +M src/lib-sieve/plugins/editheader/cmd-addheader.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.c +M src/lib-sieve/plugins/editheader/ext-editheader-common.h +M src/lib-sieve/plugins/editheader/ext-editheader.c +A tests/extensions/editheader/protected.svtest + +2011-11-28 08:53:43 +0100 Stephan Bosch <stephan@rename-it.nl> (8ff3a4e3) + + lib-sieve: editheader: fixed normal implicit keep. This was broken by + previous change. It now properly uses the final version of the message + instead of the original. + + +M src/lib-sieve/sieve-result.c +M tests/extensions/editheader/addheader.svtest +M tests/extensions/editheader/deleteheader.svtest + +2011-11-28 00:49:01 +0100 Stephan Bosch <stephan@rename-it.nl> (d4ef9291) + + Updated TODO. + + +M TODO + +2011-11-28 00:40:43 +0100 Stephan Bosch <stephan@rename-it.nl> (42223b14) + + lib-sieve: editheader: fixed implicit keep after runtime error. It did not + use the original message in this case. + + +M src/lib-sieve/sieve-actions.c +M tests/extensions/editheader/errors.svtest +A tests/extensions/editheader/errors/runtime-error.sieve + +2011-11-26 14:19:42 +0100 Stephan Bosch <stephan@rename-it.nl> (a700efef) + + testsuite: editheader extension: added various tests for folded headers. + + +M tests/extensions/editheader/addheader.svtest +M tests/extensions/editheader/deleteheader.svtest + +2011-11-26 14:19:09 +0100 Stephan Bosch <stephan@rename-it.nl> (a2e5e13a) + + lib-sieve: editheader extension: fixed handling of pre-folded header values + for added header fields. + + +M src/lib-sieve/edit-mail.c + +2011-11-26 14:18:05 +0100 Stephan Bosch <stephan@rename-it.nl> (a84da972) + + lib-sieve: editheader extension: fixed compile warning caused by spurious + comma. + + +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c + +2011-11-26 14:06:50 +0100 Stephan Bosch <stephan@rename-it.nl> (3b45ef6c) + + testsuite: added test_message_print command to print the current message + content. + + +M src/testsuite/cmd-test-message.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-common.h + +2011-11-26 11:49:07 +0100 Stephan Bosch <stephan@rename-it.nl> (5831629a) + + testsuite: editheader extension: added error tests for header value + verification. + + +M src/lib-sieve/plugins/editheader/cmd-addheader.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c +M src/lib-sieve/rfc2822.c +M tests/extensions/editheader/errors.svtest +A tests/extensions/editheader/errors/field-value.sieve + +2011-11-26 11:29:07 +0100 Stephan Bosch <stephan@rename-it.nl> (a948375b) + + lib-sieve: fixed bug caused by last change to rfc2822 header verification. + + +M src/lib-sieve/rfc2822.c + +2011-11-26 11:11:43 +0100 Stephan Bosch <stephan@rename-it.nl> (896a84a7) + + testsuite: editheader extension: added error tests for header field name + verification. + + +M Makefile.am +A tests/extensions/editheader/errors.svtest +A tests/extensions/editheader/errors/field-name-runtime.sieve +A tests/extensions/editheader/errors/field-name.sieve + +2011-11-26 11:11:02 +0100 Stephan Bosch <stephan@rename-it.nl> (69c22fa4) + + lib-sieve: editheader extension: added runtime header field name + verification. + + +M src/lib-sieve/plugins/editheader/cmd-addheader.c +M src/lib-sieve/plugins/editheader/cmd-deleteheader.c + +2011-11-26 11:09:58 +0100 Stephan Bosch <stephan@rename-it.nl> (01b034aa) + + lib-sieve: updated rfc2822 header field body verification to exclude + non-printing characters (RFC5322). + + +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c +M src/lib-sieve/rfc2822.c +M src/lib-sieve/rfc2822.h + +2011-11-24 00:50:11 +0100 Stephan Bosch <stephan@rename-it.nl> (5621b7cd) + + lib-sieve: editheader extension: added utf8-decoding-related testsuite item. + + +M tests/extensions/editheader/utf8.svtest + +2011-11-24 00:24:47 +0100 Stephan Bosch <stephan@rename-it.nl> (9e662c12) + + Added editheader support. + + +M Makefile.am +M README +M TODO +M configure.in +A doc/rfc/editheader.rfc5293.txt +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +A src/lib-sieve/edit-mail.c +A src/lib-sieve/edit-mail.h +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/editheader/Makefile.am +A src/lib-sieve/plugins/editheader/cmd-addheader.c +A src/lib-sieve/plugins/editheader/cmd-deleteheader.c +A src/lib-sieve/plugins/editheader/ext-editheader-common.c +A src/lib-sieve/plugins/editheader/ext-editheader-common.h +A src/lib-sieve/plugins/editheader/ext-editheader.c +M src/lib-sieve/rfc2822.c +M src/lib-sieve/rfc2822.h +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-size.c +M src/testsuite/testsuite-message.c +A tests/extensions/editheader/addheader.svtest +A tests/extensions/editheader/alternating.svtest +A tests/extensions/editheader/deleteheader.svtest +A tests/extensions/editheader/utf8.svtest + +2011-11-19 17:51:03 +0100 Stephan Bosch <stephan@rename-it.nl> (13120b95) + + Upgraded package version to 0.3.0 and updated documentation. + + +M INSTALL +M NEWS +M README +M TODO +M configure.in +M doc/man/pigeonhole.7.in +M doc/man/sieve-dump.1.in +M doc/man/sieve-filter.1.in +M doc/man/sieve-test.1.in +M doc/man/sievec.1.in + +2011-11-19 17:17:20 +0100 Stephan Bosch <stephan@rename-it.nl> (28a9e0a5) + + Upgraded to Dovecot v2.1. + + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/mail-raw.h +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/sieve-actions.c +M src/managesieve-login/client.c +M src/testsuite/testsuite-mailstore.c + +2011-11-19 17:02:15 +0100 Stephan Bosch <stephan@rename-it.nl> (8e018db3) + + Added signature for changeset 873baa85e220 + + +M .hgsigs + +2011-11-19 16:59:41 +0100 Stephan Bosch <stephan@rename-it.nl> (6bb95846) + + Added tag 0.2.5 for changeset 873baa85e220 + + +2011-11-19 16:59:27 +0100 Stephan Bosch <stephan@rename-it.nl> (335451a8) + + Released v0.2.5 for Dovecot v2.0.16. + + +M NEWS +M configure.in + +2011-11-09 17:26:18 +0100 Stephan Bosch <stephan@rename-it.nl> (f4dd33c5) + + managesieve-login: Use default_vsz_limit instead of adding our own. This + change matches identical changes for Dovecot's imap-login and pop3-login. + + +M src/managesieve-login/managesieve-login-settings.c + +2011-10-05 19:10:44 +0200 Stephan Bosch <stephan@rename-it.nl> (db06d68b) + + lib-sieve: vacation extension: further tinkered on log message about + implicitly delivered messages. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2011-10-05 19:03:28 +0200 Stephan Bosch <stephan@rename-it.nl> (89f76105) + + sieve-test tool: mixed up original and final envelope recipient in actual + implementation. + + +M src/sieve-tools/sieve-test.c + +2011-10-05 18:45:10 +0200 Stephan Bosch <stephan@rename-it.nl> (de64342d) + + Updated documentation of sieve tools. + + +M doc/man/sieve-dump.1.in +M doc/man/sieve-filter.1.in +M doc/man/sieve-test.1.in +M doc/man/sievec.1.in +M src/sieve-tools/sieve-dump.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c + +2011-10-05 17:43:37 +0200 Stephan Bosch <stephan@rename-it.nl> (15423beb) + + lib-sieve: vacation extension: made discard message for implicit deliver + more verbose. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2011-09-21 11:33:00 +0200 Stephan Bosch <stephan@rename-it.nl> (14132546) + + test suite: forgot to remove test_result_print command in previous change. + + +M tests/extensions/vacation/message.svtest + +2011-09-21 00:55:58 +0200 Stephan Bosch <stephan@rename-it.nl> (1bd391b5) + + lib-sieve: vacation: handled FIXME regarding the use of variables in the + :handle argument. Variables are now handled correctly. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2011-09-21 00:54:52 +0200 Stephan Bosch <stephan@rename-it.nl> (74418886) + + test suite: added test for usage of variables in vacation command. + + +M tests/extensions/vacation/message.svtest + +2011-09-17 09:04:55 +0200 Stephan Bosch <stephan@rename-it.nl> (e0d8e180) + + Merged concurrent changes. + + +2011-09-17 00:31:55 +0200 Stephan Bosch <stephan@rename-it.nl> (d6c297c8) + + Last change did not even compile. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2011-09-17 00:00:03 +0200 Stephan Bosch <stephan@rename-it.nl> (07ef39ee) + + lda-sieve: fall back to global recipient_delimiter setting if + plugin/recipient_delimiter is not set. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2011-09-16 17:57:56 +0200 Stephan Bosch <stephan@rename-it.nl> (b55c31f0) + + Updated TODO. + + +M TODO + +2011-09-14 17:18:24 +0200 Stephan Bosch <stephan@rename-it.nl> (6ce2bc3a) + + testsuite: fixed compiler warning. + + +M src/testsuite/testsuite-script.c + +2011-09-14 17:17:15 +0200 Stephan Bosch <stephan@rename-it.nl> (991b5875) + + body extension: fixed handling of :content message/rfc822. + + +M src/lib-sieve/plugins/body/ext-body-common.c +M tests/extensions/body/content.svtest + +2011-09-13 22:43:27 +0200 Stephan Bosch <stephan@rename-it.nl> (d9c2d870) + + Added signature for changeset 0d071eaa6d5e + + +M .hgsigs + +2011-09-13 22:42:18 +0200 Stephan Bosch <stephan@rename-it.nl> (4c68258d) + + Added tag 0.2.4 for changeset 0d071eaa6d5e + + +2011-09-13 22:42:06 +0200 Stephan Bosch <stephan@rename-it.nl> (ba82a8f1) + + Released v0.2.4 for Dovecot v2.0.14. + + +M NEWS +M configure.in + +2011-09-11 11:56:07 +0200 Stephan Bosch <stephan@rename-it.nl> (ea8ee4e1) + + Updated INSTALL documentation for new configuration options of the include + extension. + + +M INSTALL +A doc/include.txt +R084 doc/rfc/draft-ietf-sieve-include-03.txt doc/rfc/draft-ietf-sieve-include-05.txt +M doc/vacation.txt + +2011-09-11 11:39:07 +0200 Stephan Bosch <stephan@rename-it.nl> (dc31e865) + + include extension: made nesting_depth and max_includes limits configurable. + + +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-limits.h +M src/testsuite/testsuite-script.c +M tests/extensions/include/errors.svtest +A tests/extensions/include/errors/depth-limit.sieve +A tests/extensions/include/errors/include-limit.sieve +A tests/extensions/include/included/depth-limit-1.sieve +A tests/extensions/include/included/depth-limit-2.sieve +A tests/extensions/include/included/depth-limit-3.sieve + +2011-09-11 10:51:40 +0200 Stephan Bosch <stephan@rename-it.nl> (55f2956e) + + include extension: implemented proper configuration handling Configuration + is now only read once at extension initialization. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include.c +M src/testsuite/testsuite.c +R100 tests/extensions/include/errors/included/action-fileinto.sieve tests/extensions/include/included/action-fileinto.sieve +R100 tests/extensions/include/errors/included/action-reject.sieve tests/extensions/include/included/action-reject.sieve +R100 tests/extensions/include/execute/included/actions-fileinto1.sieve tests/extensions/include/included/actions-fileinto1.sieve +R100 tests/extensions/include/execute/included/actions-fileinto2.sieve tests/extensions/include/included/actions-fileinto2.sieve +R100 tests/extensions/include/execute/included/actions-fileinto3.sieve tests/extensions/include/included/actions-fileinto3.sieve +R100 tests/extensions/include/errors/included/circular-one.sieve tests/extensions/include/included/circular-one.sieve +R100 tests/extensions/include/errors/included/circular-three-2.sieve tests/extensions/include/included/circular-three-2.sieve +R100 tests/extensions/include/errors/included/circular-three-3.sieve tests/extensions/include/included/circular-three-3.sieve +R100 tests/extensions/include/errors/included/circular-three.sieve tests/extensions/include/included/circular-three.sieve +R100 tests/extensions/include/errors/included/circular-two-2.sieve tests/extensions/include/included/circular-two-2.sieve +R100 tests/extensions/include/errors/included/circular-two.sieve tests/extensions/include/included/circular-two.sieve + +2011-09-11 00:41:04 +0200 Stephan Bosch <stephan@rename-it.nl> (8ea852c3) + + variables extension: fixed deinitialization problem (unfreed variable scope + data) newly found by Valgrind. + + +M src/lib-sieve/plugins/variables/ext-variables-common.c + +2011-09-11 00:19:07 +0200 Stephan Bosch <stephan@rename-it.nl> (6dc92ae9) + + variables extension: fixed segfault bug triggered when dumping binary + variable scopes. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2011-08-29 17:33:00 +0200 Stephan Bosch <stephan@rename-it.nl> (68c89690) + + Updated NEWS and README for next release. + + +M NEWS +M README + +2011-08-29 17:01:44 +0200 Stephan Bosch <stephan@rename-it.nl> (e8723e76) + + Updated TODO. + + +M TODO + +2011-08-29 16:55:06 +0200 Stephan Bosch <stephan@rename-it.nl> (6b79318f) + + sieve: fixed debug mode; no messages were logged in some situations. + + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-script.c + +2011-08-29 16:14:26 +0200 Stephan Bosch <stephan@rename-it.nl> (2157da61) + + sievec: forgot to enable -D (debug) parameter. + + +M src/sieve-tools/sievec.c + +2011-08-02 17:50:15 +0200 Stephan Bosch <stephan@rename-it.nl> (b9d4ea72) + + lib-sieve: vacation extension: finally added support for using the original + recipient in vacation address check. + + +M doc/vacation.txt +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-objects.c +M tests/extensions/vacation/reply.svtest + +2011-08-02 16:36:06 +0200 Stephan Bosch <stephan@rename-it.nl> (123bdb04) + + lib-sieve: forgot to check for NULL recipient in previous change. + + +M src/lib-sieve/cmd-redirect.c + +2011-08-02 16:25:04 +0200 Stephan Bosch <stephan@rename-it.nl> (5ed91c57) + + lib-sieve: added X-Sieve-Redirected-From header for people using SPF/SRS. + + +M src/lib-sieve/cmd-redirect.c + +2011-07-05 20:32:28 +0200 Stephan Bosch <stephan@rename-it.nl> (3de551b5) + + lib-sieve: include extension: forgot to check variable identifier syntax. + + +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-name.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M tests/extensions/include/rfc-ex2-default.sieve + +2011-07-02 23:58:01 +0200 Stephan Bosch <stephan@rename-it.nl> (a755afd5) + + Merged concurrent changes. + + +2011-07-02 22:58:22 +0200 Stephan Bosch <stephan@rename-it.nl> (b0338390) + + Updated TODO. + + +M TODO + +2011-07-02 12:42:33 +0200 Stephan Bosch <stephan@rename-it.nl> (4558b7d9) + + Updated documentation. + + +M NEWS +M README + +2011-06-29 00:55:48 +0200 Stephan Bosch <stephan@rename-it.nl> (a454ba13) + + lib-sieve: variables extension: fixed -Wunused-but-set-variable compiler + warning. + + +M src/lib-sieve/plugins/variables/ext-variables-common.c + +2011-06-26 23:23:33 +0200 Stephan Bosch <stephan@rename-it.nl> (9ea19c87) + + Added ihave RFC to repository. + + +A doc/rfc/ihave.rfc5463.txt + +2011-06-26 23:07:33 +0200 Stephan Bosch <stephan@rename-it.nl> (3aa7648d) + + lib-sieve: finished ihave extension. + + +M Makefile.am +M src/lib-sieve/plugins/ihave/Makefile.am +A src/lib-sieve/plugins/ihave/cmd-error.c +M src/lib-sieve/plugins/ihave/ext-ihave-common.h +M src/lib-sieve/plugins/ihave/ext-ihave.c +M src/lib-sieve/plugins/ihave/tst-ihave.c +A tests/extensions/ihave/errors.svtest +A tests/extensions/ihave/errors/error.sieve +A tests/extensions/ihave/restrictions.svtest + +2011-06-26 22:35:31 +0200 Stephan Bosch <stephan@rename-it.nl> (3c1c2d99) + + Updated TODO list. + + +M TODO + +2011-06-26 22:34:09 +0200 Stephan Bosch <stephan@rename-it.nl> (d4685130) + + lib-sieve: implemented ihave extension. + + +M Makefile.am +M configure.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-require.c +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/ihave/Makefile.am +A src/lib-sieve/plugins/ihave/ext-ihave-binary.c +A src/lib-sieve/plugins/ihave/ext-ihave-binary.h +A src/lib-sieve/plugins/ihave/ext-ihave-common.c +A src/lib-sieve/plugins/ihave/ext-ihave-common.h +A src/lib-sieve/plugins/ihave/ext-ihave.c +A src/lib-sieve/plugins/ihave/tst-ihave.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +A tests/extensions/ihave/execute.svtest +A tests/extensions/ihave/execute/ihave.sieve + +2011-06-26 17:07:53 +0200 Stephan Bosch <stephan@rename-it.nl> (a2e42ebd) + + lib-sieve: optimized compilation of tests that yield constant results (i.e. + known at compile tme), such as true and false. If the result of a test is + known at compile time, it is optimized away. If an if-command depends on an + entirely constant test, it is optimized away as well, causing only the + 'true' sub-block to be compiled. + + +M TODO +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c +M src/lib-sieve/tst-truefalse.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-result.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-action.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c +M tests/control-if.svtest +M tests/test-allof.svtest +M tests/test-anyof.svtest + +2011-06-22 22:17:28 +0200 Stephan Bosch <stephan@rename-it.nl> (249742c5) + + Sieve tools: started using mail_namespaces_init_location instead of + mail_namespaces_init_empty. + + +M src/lib-sieve-tool/sieve-tool.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite.c + +2011-06-22 19:56:29 +0200 Stephan Bosch <stephan@rename-it.nl> (939bf15e) + + lib-sieve: made sure that flags and keywords are only checked when the + mailbox is actually opened. + + +M src/lib-sieve/sieve-actions.c + +2011-06-22 19:33:49 +0200 Stephan Bosch <stephan@rename-it.nl> (273cce20) + + Finished testsuite item for the imap4flags extension. + + +M tests/extensions/imap4flags/execute.svtest + +2011-06-21 17:18:58 +0200 Stephan Bosch <stephan@rename-it.nl> (4abd9c16) + + Fixed a few minor textual problems in the manual pages. + + +M doc/man/sieve-dump.1.in +M doc/man/sieve-filter.1.in +M doc/man/sieve-test.1.in +M doc/man/sievec.1.in + +2011-06-06 16:59:39 +0200 Stephan Bosch <stephan@rename-it.nl> (59eb6248) + + Made vnd.dovecot.debug extension available to the LDA plugin instead of only + the command line tools. + + +M Makefile.am +M configure.in +M doc/man/sieve-test.1.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/vnd.dovecot/Makefile.am +R085 src/sieve-tools/debug/Makefile.am src/lib-sieve/plugins/vnd.dovecot/debug/Makefile.am +R063 src/sieve-tools/debug/cmd-debug-print.c src/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c +R051 src/sieve-tools/debug/ext-debug-common.h src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug-common.h +A src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/sieve-tools/Makefile.am +D src/sieve-tools/debug/ext-debug.c +D src/sieve-tools/debug/sieve-ext-debug.h +M src/sieve-tools/sieve-dump.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/testsuite/testsuite-log.c +A tests/extensions/vnd.dovecot/debug/execute.svtest + +2011-05-11 19:26:57 +0200 Stephan Bosch <stephan@rename-it.nl> (7f56af7a) + + Sieve Storage: improved handling of unconfigured user home directory. + + +M src/lib-sievestorage/sieve-storage.c +M src/managesieve/managesieve-client.c + +2011-05-10 21:36:47 +0200 Stephan Bosch <stephan@rename-it.nl> (0964cb6c) + + Imap4flags: previous change was inadequate. + + +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-validator.c + +2011-05-09 20:56:08 +0200 Stephan Bosch <stephan@rename-it.nl> (94aef858) + + Imap4flags: prevent forcibly enabling imap4flags when imapflags is enabled. + + +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/vacation/ext-vacation-seconds.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h + +2011-04-14 22:45:40 +0200 Stephan Bosch <stephan@rename-it.nl> (021b7f00) + + Added signature for changeset 3ab2a125e1e2 + + +M .hgsigs + +2011-04-14 22:44:05 +0200 Stephan Bosch <stephan@rename-it.nl> (cd48584b) + + Added tag 0.2.3 for changeset 3ab2a125e1e2 + + +2011-04-14 22:43:50 +0200 Stephan Bosch <stephan@rename-it.nl> (1ef3f05a) + + Released v0.2.3 for Dovecot v2.0.12. + + +M configure.in + +2011-04-14 21:32:01 +0200 Stephan Bosch <stephan@rename-it.nl> (9dea325c) + + Prepared NEWS file for next release. + + +M NEWS + +2011-04-14 21:31:34 +0200 Stephan Bosch <stephan@rename-it.nl> (4eedbc27) + + Small changes to the INSTALL file regarding configuration of vacation + extension. + + +M INSTALL + +2011-04-14 21:27:22 +0200 Stephan Bosch <stephan@rename-it.nl> (e4eb532d) + + Updated RFC for vacation-seconds extension. + + +R053 doc/rfc/draft-ietf-sieve-vacation-seconds-03.txt doc/rfc/vacation-seconds.rfc6131.txt + +2011-04-14 21:26:42 +0200 Stephan Bosch <stephan@rename-it.nl> (43706eb0) + + Restructured extension-specific install documentation. + + +M doc/spamtest-virustest.txt +M doc/vacation.txt + +2011-04-13 01:00:10 +0200 Stephan Bosch <stephan@rename-it.nl> (780eded2) + + Managesieve-login: increased dump-capability time-out from 5 to 60 s. + + +M src/managesieve-login/managesieve-login-settings-plugin.c + +2011-04-10 17:28:14 +0200 Stephan Bosch <stephan@rename-it.nl> (589fdabb) + + managsieve-login: Reduced the max. number of allowed bad commands. + + +M src/managesieve-login/client.c + +2011-03-22 22:25:11 +0100 Stephan Bosch <stephan@rename-it.nl> (2e939b67) + + Sieve tools: avoid initializing mail store (namespaces) for sievec and + sieve-dump. + + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/sieve-tools/sieve-dump.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/testsuite/testsuite.c + +2011-03-22 22:08:55 +0100 Stephan Bosch <stephan@rename-it.nl> (f433f945) + + Fixed various compile warnings related to spurious semicolons and + inappropriate variable initialization. + + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/sieve-result.c +M src/testsuite/cmd-test-message.c + +2011-03-05 14:48:20 +0100 Stephan Bosch <stephan@rename-it.nl> (d1b70d7b) + + Updated copyright notices to include year 2011. + + +M doc/man/pigeonhole.7.in +M src/lib-managesieve/managesieve-parser.c +M src/lib-managesieve/managesieve-parser.h +M src/lib-managesieve/managesieve-quote.c +M src/lib-managesieve/managesieve-quote.h +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/mail-raw.h +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/cmp-i-ascii-casemap.c +M src/lib-sieve/cmp-i-octet.c +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/copy/sieve-ext-copy.h +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/ext-date-common.h +M src/lib-sieve/plugins/date/ext-date.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify-limits.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.h +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/environment/ext-environment-common.h +M src/lib-sieve/plugins/environment/ext-environment.c +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-limits.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/mailbox/ext-mailbox-common.h +M src/lib-sieve/plugins/mailbox/ext-mailbox.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.h +M src/lib-sieve/plugins/notify/ext-notify-limits.h +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/plugins/regex/ext-regex-common.c +M src/lib-sieve/plugins/regex/ext-regex-common.h +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/lib-sieve/plugins/vacation/ext-vacation-seconds.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.h +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables-dump.h +M src/lib-sieve/plugins/variables/ext-variables-limits.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-name.c +M src/lib-sieve/plugins/variables/ext-variables-name.h +M src/lib-sieve/plugins/variables/ext-variables-namespaces.c +M src/lib-sieve/plugins/variables/ext-variables-namespaces.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/rfc2822.c +M src/lib-sieve/rfc2822.h +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary-code.c +M src/lib-sieve/sieve-binary-debug.c +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-objects.c +M src/lib-sieve/sieve-objects.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-plugins.c +M src/lib-sieve/sieve-plugins.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-runtime-trace.c +M src/lib-sieve/sieve-runtime-trace.h +M src/lib-sieve/sieve-runtime.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve-smtp.c +M src/lib-sieve/sieve-smtp.h +M src/lib-sieve/sieve-stringlist.c +M src/lib-sieve/sieve-stringlist.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c +M src/lib-sieve/tst-truefalse.c +M src/lib-sievestorage/sieve-storage-list.c +M src/lib-sievestorage/sieve-storage-list.h +M src/lib-sievestorage/sieve-storage-private.h +M src/lib-sievestorage/sieve-storage-quota.c +M src/lib-sievestorage/sieve-storage-quota.h +M src/lib-sievestorage/sieve-storage-save.c +M src/lib-sievestorage/sieve-storage-save.h +M src/lib-sievestorage/sieve-storage-script.c +M src/lib-sievestorage/sieve-storage-script.h +M src/lib-sievestorage/sieve-storage.c +M src/lib-sievestorage/sieve-storage.h +M src/managesieve-login/client-authenticate.c +M src/managesieve-login/client-authenticate.h +M src/managesieve-login/client.c +M src/managesieve-login/client.h +M src/managesieve-login/managesieve-login-settings-plugin.c +M src/managesieve-login/managesieve-login-settings-plugin.h +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve-login/managesieve-login-settings.h +M src/managesieve-login/managesieve-proxy.c +M src/managesieve-login/managesieve-proxy.h +M src/managesieve/cmd-capability.c +M src/managesieve/cmd-deletescript.c +M src/managesieve/cmd-getscript.c +M src/managesieve/cmd-havespace.c +M src/managesieve/cmd-listscripts.c +M src/managesieve/cmd-logout.c +M src/managesieve/cmd-noop.c +M src/managesieve/cmd-putscript.c +M src/managesieve/cmd-renamescript.c +M src/managesieve/cmd-setactive.c +M src/managesieve/main.c +M src/managesieve/managesieve-capabilities.c +M src/managesieve/managesieve-capabilities.h +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h +M src/managesieve/managesieve-commands.c +M src/managesieve/managesieve-commands.h +M src/managesieve/managesieve-common.h +M src/managesieve/managesieve-quota.c +M src/managesieve/managesieve-quota.h +M src/managesieve/managesieve-settings.c +M src/managesieve/managesieve-settings.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/plugins/lda-sieve/lda-sieve-plugin.h +M src/sieve-tools/debug/cmd-debug-print.c +M src/sieve-tools/debug/ext-debug-common.h +M src/sieve-tools/debug/ext-debug.c +M src/sieve-tools/debug/sieve-ext-debug.h +M src/sieve-tools/sieve-dump.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-result.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-arguments.c +M src/testsuite/testsuite-arguments.h +M src/testsuite/testsuite-binary.c +M src/testsuite/testsuite-binary.h +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-log.h +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-result.h +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-script.h +M src/testsuite/testsuite-settings.c +M src/testsuite/testsuite-settings.h +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite-substitutions.c +M src/testsuite/testsuite-substitutions.h +M src/testsuite/testsuite.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-action.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c + +2011-03-02 17:42:53 +0100 Stephan Bosch <stephan@rename-it.nl> (1d6239be) + + Fixed segfault bug in extension configuration, triggered when unknown + extension is mentioned in sieve_extensions setting. + + +M src/lib-sieve/sieve-extensions.c + +2011-02-23 22:59:40 +0100 Stephan Bosch <stephan@rename-it.nl> (508398e7) + + Sieve-filter tool: forgot to enable -u option. + + +M src/sieve-tools/sieve-filter.c + +2011-02-23 11:17:50 +0100 Stephan Bosch <stephan@rename-it.nl> (c51569ee) + + Fixed some more minor problems in the man pages (patch by Pascal Volk). + + +M doc/man/Makefile.am +M doc/man/sieve-filter.1.in + +2011-02-23 01:26:55 +0100 Stephan Bosch <stephan@rename-it.nl> (3097e3e2) + + Fixed some minor problems in the man pages (patch by Pascal Volk). + + +M doc/man/sieve-dump.1.in +M doc/man/sieve-filter.1.in +M doc/man/sieve-test.1.in +M doc/man/sievec.1.in + +2011-02-20 16:42:17 +0100 Stephan Bosch <stephan@rename-it.nl> (38fb3da0) + + Vacation extension: added test for proper From: address when replying for + Cc'd e-mail. + + +M tests/extensions/vacation/smtp.svtest + +2011-02-19 08:45:13 +0100 Stephan Bosch <stephan@rename-it.nl> (ac5245ff) + + ManageSieve: fixed problems in previous change; utf-8 was actually denied + completely. + + +M src/lib-managesieve/managesieve-parser.c +M src/lib-managesieve/managesieve-quote.c + +2011-02-18 14:03:28 +0100 Stephan Bosch <stephan@rename-it.nl> (2a321138) + + ManageSieve: now using Dovecot API for UTF-8 validity checks. + + +M src/lib-managesieve/managesieve-parser.c +M src/lib-managesieve/managesieve-parser.h +M src/lib-managesieve/managesieve-quote.c + +2011-02-18 02:58:43 +0100 Stephan Bosch <stephan@rename-it.nl> (e3d57260) + + Fixed potential segfault in extension registry. + + +M src/lib-sieve/sieve-extensions.c + +2011-02-17 21:12:44 +0100 Stephan Bosch <stephan@rename-it.nl> (5d67c89d) + + ManageSieve: fixed bug in UTF-8 checking of string values. + + +M src/lib-managesieve/managesieve-parser.c + +2011-02-13 10:27:11 +0100 Stephan Bosch <stephan@rename-it.nl> (2cbeec33) + + Sieve filter tool: finished basic functionality. + + +M TODO +M doc/man/sieve-filter.1.in +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c + +2011-02-11 09:24:12 +0100 Stephan Bosch <stephan@rename-it.nl> (015073d0) + + Fixed bug in parsing of duration settings. + + +M src/lib-sieve/sieve-settings.c + +2011-02-09 19:38:58 +0100 Stephan Bosch <stephan@rename-it.nl> (5bae97dc) + + Testsuite: fixed prefix of -E option info log output. + + +M src/testsuite/testsuite-log.c + +2011-02-09 19:32:28 +0100 Stephan Bosch <stephan@rename-it.nl> (6d3c929f) + + Vacation extension: added tests for reply filtering test suite. + + +M Makefile.am +A tests/extensions/vacation/reply.svtest + +2011-02-09 19:31:36 +0100 Stephan Bosch <stephan@rename-it.nl> (674599b9) + + Vacation extension: now inhibits replies to messages from sender listed in + :addresses. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2011-02-09 19:29:43 +0100 Stephan Bosch <stephan@rename-it.nl> (f9b1c10e) + + Testsuite: added info log output to -E command line option. + + +M src/testsuite/testsuite-log.c + +2011-01-26 00:51:55 +0100 Stephan Bosch <stephan@rename-it.nl> (bc3d93c5) + + Sieve tools: prevent automatically creating mail storage. + + +M src/lib-sieve-tool/sieve-tool.c + +2011-01-25 02:44:29 +0100 Stephan Bosch <stephan@rename-it.nl> (db97d27a) + + Vacation-seconds extension: added specification to doc/rfc. + + +A doc/rfc/draft-ietf-sieve-vacation-seconds-03.txt + +2011-01-25 02:43:25 +0100 Stephan Bosch <stephan@rename-it.nl> (0d74a9e9) + + Vacation extension: implemented the (draft) vacation-seconds extension. + + +M INSTALL +M doc/vacation.txt +M src/lib-sieve/plugins/vacation/Makefile.am +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +A src/lib-sieve/plugins/vacation/ext-vacation-seconds.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M tests/extensions/vacation/execute.svtest +A tests/extensions/vacation/execute/seconds.sieve + +2011-01-25 01:27:01 +0100 Stephan Bosch <stephan@rename-it.nl> (3817e2b0) + + Vacation extension: added default period configuration setting and fixed a + limit bug. + + +M doc/vacation.txt +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h + +2011-01-25 01:05:28 +0100 Stephan Bosch <stephan@rename-it.nl> (000ee266) + + Vacation extension: added min/max period configuration settings and changed + the internal unit from days to seconds. + + +M INSTALL +M doc/Makefile.am +A doc/vacation.txt +M src/lib-sieve/plugins/vacation/Makefile.am +M src/lib-sieve/plugins/vacation/cmd-vacation.c +A src/lib-sieve/plugins/vacation/ext-vacation-common.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h + +2011-01-24 23:39:32 +0100 Stephan Bosch <stephan@rename-it.nl> (ccceee98) + + Restructured settings parsing and added parsing support for duration + settings. + + +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h + +2011-01-23 13:44:13 +0100 Stephan Bosch <stephan@rename-it.nl> (e20025dc) + + Copy extension: previous change was incomplete and broken. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/copy/ext-copy.c + +2011-01-23 13:40:33 +0100 Stephan Bosch <stephan@rename-it.nl> (e2e385f5) + + Merged concurrent changes. + + +2011-01-23 13:39:50 +0100 Stephan Bosch <stephan@rename-it.nl> (acf7285a) + + Copy extension: added public interface for adding the :copy tag to new + commands. + + +M src/lib-sieve/plugins/copy/Makefile.am +M src/lib-sieve/plugins/copy/ext-copy.c +A src/lib-sieve/plugins/copy/sieve-ext-copy.h + +2011-01-19 17:37:43 +0100 Stephan Bosch <stephan@rename-it.nl> (b67b1843) + + Enotify: mailto: fixed inappropriate return type in URI parse function, also + fixing ARM compiler warning. + + +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c + +2011-01-18 21:46:08 +0100 Stephan Bosch <stephan@rename-it.nl> (f22c14f5) + + Notify extension: fixed duplicate variable declaration. + + +M src/lib-sieve/plugins/notify/cmd-notify.c + +2011-01-06 15:50:31 +0100 Stephan Bosch <stephan@rename-it.nl> (7f771cb4) + + ManageSieve: removed TODO status of adding ANONYMOUS SASL support, since the + RFC specification no longer describes it. + + +M README +M TODO +M src/managesieve-login/client-authenticate.c + +2011-01-04 12:51:58 +0100 Stephan Bosch <stephan@rename-it.nl> (86eb5660) + + Vacation: fixed handling of sendmail errors. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2011-01-01 15:51:21 +0100 Stephan Bosch <stephan@rename-it.nl> (2153efc9) + + Deprecated notify extension: reverted previous change as address is used for + the notification in stead of being actually parsed. + + +M src/lib-sieve/plugins/notify/ext-notify-common.c + +2011-01-01 15:21:44 +0100 Stephan Bosch <stephan@rename-it.nl> (adc6c8ce) + + Removed header MIME-decoding for other instances where addresses need to be + parsed. + + +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2011-01-01 14:10:53 +0100 Stephan Bosch <stephan@rename-it.nl> (a2d09e04) + + Address test: removed header MIME-decoding to prevent address parsing + problems. + + +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-header.c +M tests/test-address.svtest + +2010-12-07 00:05:50 +0100 Stephan Bosch <stephan@rename-it.nl> (d1b2051a) + + Added signature for changeset df8b38da248c + + +M .hgsigs + +2010-12-07 00:04:57 +0100 Stephan Bosch <stephan@rename-it.nl> (d70e7597) + + Added tag 0.2.2 for changeset df8b38da248c + + +2010-12-07 00:04:27 +0100 Stephan Bosch <stephan@rename-it.nl> (c70867fb) + + Released v0.2.2 for Dovecot v2.0.8. + + +M NEWS +M configure.in + +2010-12-03 22:24:06 +0100 Stephan Bosch <stephan@rename-it.nl> (b17db543) + + Prepared NEWS file for next release. + + +M NEWS + +2010-12-01 00:46:31 +0100 Stephan Bosch <stephan@rename-it.nl> (35cdc868) + + LDA Sieve plugin: started using Dovecot reject API. + + +M TODO +M src/lib-sieve/ext-reject.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-types.h +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2010-12-01 00:34:47 +0100 Stephan Bosch <stephan@rename-it.nl> (2f20241f) + + Fixed segfault caused by previous fix. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2010-11-30 22:49:57 +0100 Stephan Bosch <stephan@rename-it.nl> (e043367a) + + LDA Sieve plugin: fixed memory leak at deinitialization (patch by Timo + Sirainen). + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2010-11-22 17:03:28 +0100 Stephan Bosch <stephan@rename-it.nl> (6282f9cc) + + managesieve: Fixed giving any -parameters (analogoues to Dovecot fix). + + +M src/managesieve/main.c + +2010-11-16 22:09:02 +0100 Stephan Bosch <stephan@rename-it.nl> (7d1c5a0a) + + Services' default vsz_limit wasn't actually using default_vsz_limit but + rather 4 GB. + + +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve/managesieve-settings.c + +2010-11-16 22:08:10 +0100 Stephan Bosch <stephan@rename-it.nl> (1ffebb22) + + "Running standalone?" check now uses a new DOVECOT_CHILD_PROCESS environment + rather than GENERATION. The GENERATION environment was already set in some + systems for Java. + + +M src/managesieve/main.c + +2010-11-03 17:54:07 +0100 Stephan Bosch <stephan@rename-it.nl> (ad495903) + + Avoids potential problems if auth process crashes and service_count > 1 + (patch by Timo Sirainen). + + +M src/managesieve/main.c + +2010-10-17 10:21:13 +0200 Stephan Bosch <stephan@rename-it.nl> (84d7b77c) + + Sieve-filter: minor addition to the man page. + + +M doc/man/sieve-filter.1.in + +2010-10-16 21:19:51 +0200 Stephan Bosch <stephan@rename-it.nl> (600afb87) + + Sieve-filter: implemented basic filtering with source mailbox actions. + + +M doc/man/sieve-filter.1.in +M src/sieve-tools/sieve-filter.c + +2010-10-01 19:04:32 +0200 Stephan Bosch <stephan@rename-it.nl> (e56cdec7) + + Sieve-filter: fixed tool compilation and further developed tool design. + + +M TODO +M doc/man/sieve-filter.1.in +M src/sieve-tools/sieve-filter.c + +2010-10-01 19:03:08 +0200 Stephan Bosch <stephan@rename-it.nl> (af388430) + + Sieve tools: fixed help text for sieve-test command and some minor + adjustments. + + +M src/lib-sieve-tool/sieve-tool.c +M src/sieve-tools/sieve-test.c + +2010-09-30 23:21:54 +0200 Stephan Bosch <stephan@rename-it.nl> (65f870bf) + + Sieve-filter: updated man page. + + +M doc/man/sieve-filter.1.in + +2010-09-30 21:11:34 +0200 Stephan Bosch <stephan@rename-it.nl> (d751082c) + + Imap4flags: fixed segfault bug occuring in multiscript context. + + +M src/lib-sieve/plugins/imap4flags/tag-flags.c + +2010-09-28 22:50:04 +0200 Stephan Bosch <stephan@rename-it.nl> (2d23339a) + + Improved ManageSieve config example; 'sieve' is added to protocols setting + in 20-managesieve.conf now. + + +M doc/example-config/conf.d/20-managesieve.conf + +2010-09-28 22:24:35 +0200 Stephan Bosch <stephan@rename-it.nl> (623f5a9b) + + ManageSieve: added settings plugin version checking. + + +M src/managesieve-login/managesieve-login-settings-plugin.c +M src/managesieve/managesieve-settings.c + +2010-09-27 01:50:24 +0200 Stephan Bosch <stephan@rename-it.nl> (f69eeb68) + + Added signature for changeset d768f911252d + + +A .hgsigs + +2010-09-27 01:44:09 +0200 Stephan Bosch <stephan@rename-it.nl> (e545e840) + + Added tag 0.2.1 for changeset d768f911252d + + +2010-09-27 01:43:24 +0200 Stephan Bosch <stephan@rename-it.nl> (5d3a336f) + + Released v0.2.1 for Dovecot v2.0.4. + + +M NEWS +M configure.in + +2010-09-27 00:19:45 +0200 Stephan Bosch <stephan@rename-it.nl> (7c2ccf0b) + + LDA Sieve plugin: added _version symbol to enable Dovecot version checking. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2010-09-23 16:54:02 +0200 Stephan Bosch <stephan@rename-it.nl> (b339695c) + + LDA Sieve plugin: updated wiki link in error message. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2010-09-23 16:46:40 +0200 Stephan Bosch <stephan@rename-it.nl> (9374a431) + + LDA Sieve plugin: turned debug message into an error and added script path + information. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2010-09-17 23:12:05 +0200 Stephan Bosch <stephan@rename-it.nl> (36e3798d) + + Incorporated distinction between original and final envelope recipient in + Sieve interpreter, as recently introduced in Dovecot. + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-types.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-message.c + +2010-09-17 22:05:33 +0200 Stephan Bosch <stephan@rename-it.nl> (59568b9d) + + Regex: added support for variable regex keys. + + +M TODO +M src/lib-sieve/plugins/regex/mcht-regex.c +M tests/compile/errors.svtest +M tests/compile/errors/unsupported.sieve +M tests/extensions/regex/basic.svtest +M tests/extensions/regex/errors.svtest +A tests/extensions/regex/errors/runtime.sieve + +2010-09-17 21:20:37 +0200 Stephan Bosch <stephan@rename-it.nl> (52b7dd1a) + + Fixed comparator/match-type macro mixup. + + +M src/lib-sieve/tst-header.c + +2010-09-13 02:48:50 +0200 Stephan Bosch <stephan@rename-it.nl> (7b49dde4) + + Fixed unnecessary reporting of dummy extensions in ManageSieve SIEVE + capability. + + +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h + +2010-09-10 02:04:17 +0200 Stephan Bosch <stephan@rename-it.nl> (c1362376) + + Added tag 0.2.0 for changeset 7bdabe6f9757 + + +2010-09-10 02:04:11 +0200 Stephan Bosch <stephan@rename-it.nl> (7202ebb9) + + Released v0.2.0 for Dovecot v2.0.2. + + +M NEWS +M TODO +M configure.in + +2010-09-10 00:33:03 +0200 Stephan Bosch <stephan@rename-it.nl> (c275ef53) + + Updated the Compile section of the INSTALL file. + + +M INSTALL + +2010-09-10 00:16:10 +0200 Stephan Bosch <stephan@rename-it.nl> (8a0316ba) + + Fixed make distcheck to work. + + +M configure.in +M m4/dovecot.m4 + +2010-09-09 23:59:56 +0200 Stephan Bosch <stephan@rename-it.nl> (f53adf75) + + Removed --enable-header-install setting. + + +M Makefile.am +M configure.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/enotify/Makefile.am +M src/lib-sieve/plugins/environment/Makefile.am +M src/lib-sieve/plugins/variables/Makefile.am + +2010-09-09 09:24:40 +0200 Stephan Bosch <stephan@rename-it.nl> (6cc8c323) + + Fixed series of AIX compiler warnings. + + +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/sieve-plugins.c + +2010-09-08 23:27:57 +0200 Stephan Bosch <stephan@rename-it.nl> (7be6741e) + + Added a few missing NEWS items and fixed some formatting issues. + + +M NEWS + +2010-09-08 20:58:01 +0200 Stephan Bosch <stephan@rename-it.nl> (c52eebe2) + + Updated README documentation. + + +M README + +2010-09-08 20:52:38 +0200 Stephan Bosch <stephan@rename-it.nl> (b7df21ba) + + Updated INSTALL documentation. + + +M INSTALL + +2010-09-08 20:04:56 +0200 Stephan Bosch <stephan@rename-it.nl> (4467bb97) + + ManageSieve: fixed dump-capability problem occuring when using a custom + config file (patch by Timo Sirainen). + + +M src/managesieve-login/managesieve-login-settings-plugin.c + +2010-09-06 18:36:25 +0200 Stephan Bosch <stephan@rename-it.nl> (f302ee17) + + Sieve-dump: added support for producing per-block hexdump output. + + +M doc/man/sieve-dump.1.in +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/sieve-tools/sieve-dump.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/testsuite/testsuite.c + +2010-09-05 21:37:41 +0200 Stephan Bosch <stephan@rename-it.nl> (9772fd7f) + + Added support for critical runtime errors. + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h + +2010-09-05 17:57:17 +0200 Stephan Bosch <stephan@rename-it.nl> (b3f447ee) + + Error handling: don't log user message of critical error to system log. + + +M src/lib-sieve/sieve-error.c + +2010-09-05 17:53:16 +0200 Stephan Bosch <stephan@rename-it.nl> (8fe5d7a2) + + Sieve plugin: only refer to user log for compile error details when there is + actually a compile error. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2010-09-05 16:27:06 +0200 Stephan Bosch <stephan@rename-it.nl> (831fd560) + + Final preparations for 0.2 release. + + +M NEWS +M TODO + +2010-09-05 15:11:13 +0200 Stephan Bosch <stephan@rename-it.nl> (c31f7561) + + Sieve plugin: simplified system error handling. + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/plugins/lda-sieve/Makefile.am +D src/plugins/lda-sieve/lda-sieve-log.c +D src/plugins/lda-sieve/lda-sieve-log.h +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2010-09-05 14:24:19 +0200 Stephan Bosch <stephan@rename-it.nl> (87c1022c) + + Simplified error handling; in particular the changes in the preceeding + commits. + + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-script.c +M src/lib-sievestorage/sieve-storage.c +M src/plugins/lda-sieve/lda-sieve-log.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/testsuite/testsuite-log.c + +2010-09-04 14:53:35 +0200 Stephan Bosch <stephan@rename-it.nl> (ea639eaf) + + Fixed runtime error logging not to report user-caused errors to the master + log. + + +M TODO +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-validator.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2010-09-04 14:51:35 +0200 Stephan Bosch <stephan@rename-it.nl> (6eb224c4) + + Made global system error handler state part of Sieve instance. + + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/tst-size.c +M src/lib-sievestorage/sieve-storage.c +M src/managesieve/cmd-putscript.c +M src/plugins/lda-sieve/lda-sieve-log.c +M src/plugins/lda-sieve/lda-sieve-log.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-test.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-mailstore.c + +2010-09-03 17:58:23 +0200 Stephan Bosch <stephan@rename-it.nl> (cc2c8e27) + + Fixed default Sieve capability: extra extensions spamtest, spamtestplus and + virustest were also enabled by default. + + +M src/lib-sieve/sieve-extensions.c + +2010-08-30 10:34:37 +0200 Stephan Bosch <stephan@rename-it.nl> (95154243) + + Finished FIXME review. + + +M TODO + +2010-08-30 10:30:47 +0200 Stephan Bosch <stephan@rename-it.nl> (25293c5a) + + Fixed FIXME: fileinto folder name utf-8 validity is now checked at + compiletime or runtime. + + +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/sieve-actions.c + +2010-08-30 10:13:54 +0200 Stephan Bosch <stephan@rename-it.nl> (b75d2e74) + + Made sure that store action logs both UTF-8 and mUTF-7 names when + applicable. + + +M src/lib-sieve/sieve-actions.c + +2010-08-30 09:20:44 +0200 Stephan Bosch <stephan@rename-it.nl> (4897d7b0) + + Fixed FIXME: added runtime warning for erroneous :addresses item. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2010-08-30 03:15:57 +0200 Stephan Bosch <stephan@rename-it.nl> (d0d60d62) + + Removed spurious source file. + + +D src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2010-08-30 03:13:29 +0200 Stephan Bosch <stephan@rename-it.nl> (741f13eb) + + Fixed FIXME: Date test now reports warning when invalid zone argument is + encountered at runtime. + + +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h + +2010-08-30 02:52:49 +0200 Stephan Bosch <stephan@rename-it.nl> (a629c533) + + Fixed FIXME: Imap4flags extension now checks flag keyword syntax before the + message is stored. + + +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c + +2010-08-30 02:37:07 +0200 Stephan Bosch <stephan@rename-it.nl> (66f356ab) + + Modified TODO item. + + +M TODO +M src/lib-sieve/ext-reject.c + +2010-08-30 02:33:26 +0200 Stephan Bosch <stephan@rename-it.nl> (d5880b7c) + + Fixed FIXME: when redirect address is a variable, it is checked for validity + at runtime. + + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/sieve-address-parts.c +M src/managesieve/cmd-putscript.c + +2010-08-30 02:18:54 +0200 Stephan Bosch <stephan@rename-it.nl> (dda5cd20) + + Simplified runtime command script location querying. + + +M TODO +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/sieve-tools/debug/cmd-debug-print.c +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-script.c + +2010-08-29 11:34:40 +0200 Stephan Bosch <stephan@rename-it.nl> (c84b56d1) + + Testsuite: partly cleaned up test scripts (rest is post-v0.2). + + +M Makefile.am +M TODO +D tests/address.svtest +D tests/comparators/core.svtest +A tests/comparators/i-ascii-casemap.svtest +A tests/comparators/i-octet.svtest +M tests/compile/errors.svtest +M tests/compile/errors/match-type.sieve +M tests/compile/recover.svtest +M tests/compile/recover/commands-endblock.sieve +M tests/compile/recover/commands-semicolon.sieve +M tests/compile/recover/tests-endcomma.sieve +M tests/compile/warnings.svtest +M tests/compile/warnings/eof.sieve +M tests/compile/warnings/invalid-headers.sieve +A tests/control-if.svtest +A tests/control-stop.svtest +D tests/control-structures.svtest +M tests/deprecated/imapflags/execute.svtest +M tests/deprecated/notify/denotify.svtest +M tests/execute/smtp.svtest +D tests/exists.svtest +M tests/extensions/encoded-character.svtest +M tests/extensions/envelope.svtest +M tests/extensions/imap4flags/basic.svtest +M tests/extensions/imap4flags/flagstore.svtest +M tests/extensions/imap4flags/flagstring.svtest +M tests/extensions/imap4flags/multiscript.svtest +M tests/extensions/imap4flags/multiscript/group-spam.sieve +M tests/extensions/imap4flags/multiscript/sent-store.sieve +M tests/extensions/include/included/rfc-ex1-always_allow.sieve +M tests/extensions/include/included/rfc-ex1-mailing_lists.sieve +M tests/extensions/regex/match-values.svtest +M tests/extensions/relational/basic.svtest +M tests/extensions/relational/comparators.svtest +M tests/extensions/spamvirustest/virustest.svtest +M tests/extensions/subaddress/basic.svtest +M tests/extensions/subaddress/config.svtest +M tests/extensions/vacation/execute/no-handle.sieve +D tests/header.svtest +M tests/match-types/contains.svtest +M tests/multiscript/conflicts.svtest +D tests/size.svtest +A tests/test-address.svtest +A tests/test-allof.svtest +A tests/test-anyof.svtest +A tests/test-exists.svtest +A tests/test-header.svtest +A tests/test-size.svtest +M tests/testsuite.svtest + +2010-08-28 13:13:16 +0200 Stephan Bosch <stephan@rename-it.nl> (329f4c13) + + Testsuite: made command syntax more uniform. + + +M TODO +M src/testsuite/Makefile.am +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-mailbox.c +D src/testsuite/cmd-test-result-print.c +D src/testsuite/cmd-test-result-reset.c +A src/testsuite/cmd-test-result.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-common.h +R076 src/testsuite/tst-test-result.c src/testsuite/tst-test-result-action.c +M tests/deprecated/notify/execute.svtest +M tests/execute/actions.svtest +M tests/execute/errors.svtest +M tests/execute/examples.svtest +M tests/extensions/enotify/execute.svtest +M tests/extensions/imap4flags/execute.svtest +M tests/extensions/include/execute.svtest +M tests/extensions/mailbox/execute.svtest +M tests/extensions/reject/execute.svtest +M tests/extensions/spamvirustest/spamtest.svtest +M tests/extensions/spamvirustest/spamtestplus.svtest +M tests/extensions/spamvirustest/virustest.svtest +M tests/extensions/subaddress/config.svtest +M tests/extensions/vacation/execute.svtest +M tests/multiscript/basic.svtest +M tests/multiscript/conflicts.svtest + +2010-08-27 22:33:52 +0200 Stephan Bosch <stephan@rename-it.nl> (0a7d1584) + + doc/man/sievec.1.in: fixed roff error caused by unescaped '-' (patch by Mike + Abbott). + + +M doc/man/sievec.1.in + +2010-08-27 22:25:19 +0200 Stephan Bosch <stephan@rename-it.nl> (3e05feb7) + + ManageSieve: settings plugin, capability dump: argument array for execv was + too short by one element. + + +M src/managesieve-login/managesieve-login-settings-plugin.c + +2010-08-27 22:22:11 +0200 Stephan Bosch <stephan@rename-it.nl> (c03182c9) + + Forgot to add manpage preprocessor and includes to distribution. + + +M doc/man/Makefile.am + +2010-08-26 00:35:19 +0200 Stephan Bosch <stephan@rename-it.nl> (38837035) + + Removed spurious old stdio.h (top) includes; these cause compile issues on + specific systems. + + +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/mailbox/ext-mailbox.c +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve.h +M src/lib-sievestorage/sieve-storage-list.h + +2010-08-23 19:26:12 +0200 Stephan Bosch <stephan@rename-it.nl> (1cbc2470) + + Fixed Sieve script name checking to properly handle length issues and added + 0x00ff as invalid character. + + +M src/lib-sieve/sieve-script.c +M src/managesieve/cmd-putscript.c + +2010-08-23 19:21:04 +0200 Stephan Bosch <stephan@rename-it.nl> (97d88d9c) + + ManageSieve: fixed putscript error in previous commit. + + +M src/managesieve/cmd-putscript.c + +2010-08-23 18:50:58 +0200 Stephan Bosch <stephan@rename-it.nl> (b71803b2) + + Enforced ManageSieve protocol syntax better with some of the commands; some + commands still allowed spurious extra arguments. + + +M TODO +M src/managesieve/cmd-capability.c +M src/managesieve/cmd-deletescript.c +M src/managesieve/cmd-getscript.c +M src/managesieve/cmd-havespace.c +M src/managesieve/cmd-listscripts.c +M src/managesieve/cmd-logout.c +M src/managesieve/cmd-noop.c +M src/managesieve/cmd-renamescript.c +M src/managesieve/cmd-setactive.c +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h + +2010-08-23 09:10:11 +0200 Stephan Bosch <stephan@rename-it.nl> (f1e6fa4b) + + Cleaned up manpages and fixed various issues (patch by Pascal Volk). - No + longer track the generated pigeonhole.7 - Some makes don't like the 'handy' + notation that was used. - Deleted trailing spaces - Escaped some dashes - + Replaced some ' and " by \(aq and \(dq - Sorted manual pages in section 'See + also' (first list all man pages from the lowest section (1) alphabetical + sorted, then the next section …) + + +M .hgignore +M doc/man/Makefile.am +D doc/man/pigeonhole.7 +M doc/man/pigeonhole.7.in +M doc/man/sieve-dump.1.in +M doc/man/sieve-test.1.in +M doc/man/sievec.1.in + +2010-08-23 00:27:08 +0200 Stephan Bosch <stephan@rename-it.nl> (a8e800d9) + + Update man pages to match style and content of Dovecot man pages. + + +M .hgignore +M TODO +M doc/man/Makefile.am +A doc/man/pigeonhole.7 +A doc/man/pigeonhole.7.in +A doc/man/reporting-bugs.inc +A doc/man/sed.sh +D doc/man/sieve-dump.1 +A doc/man/sieve-dump.1.in +R097 doc/man/sieve-filter.1 doc/man/sieve-filter.1.in +D doc/man/sieve-test.1 +A doc/man/sieve-test.1.in +D doc/man/sievec.1 +A doc/man/sievec.1.in + +2010-08-21 23:23:35 +0200 Stephan Bosch <stephan@rename-it.nl> (26d81be2) + + Added manpage redirection for sieved. + + +A doc/man/sieved.1 + +2010-08-21 21:51:00 +0200 Stephan Bosch <stephan@rename-it.nl> (94482626) + + Renamed sieved tool to sieve-dump. + + +M .hgignore +M NEWS +M README +M doc/man/Makefile.am +R086 doc/man/sieved.1 doc/man/sieve-dump.1 +M doc/man/sieve-filter.1 +M doc/man/sieve-test.1 +M doc/man/sievec.1 +M src/sieve-tools/Makefile.am +R090 src/sieve-tools/sieved.c src/sieve-tools/sieve-dump.c + +2010-08-19 18:04:22 +0200 Stephan Bosch <stephan@rename-it.nl> (7358244b) + + Updated documentation for upcoming release. + + +M INSTALL +M NEWS +M README + +2010-08-17 19:03:36 +0200 Stephan Bosch <stephan@rename-it.nl> (cf7807b2) + + Added quota and limit configuration to config file examples. + + +M doc/example-config/conf.d/20-managesieve.conf +M doc/example-config/conf.d/90-sieve.conf + +2010-08-17 18:48:30 +0200 Stephan Bosch <stephan@rename-it.nl> (72d4847e) + + Removed superfluous text from AUTHORS file. + + +M AUTHORS + +2010-08-17 18:32:23 +0200 Stephan Bosch <stephan@rename-it.nl> (0e9baf99) + + Moved finishing the ereject extension off the pre-v0.2.0 TODO list. + + +M TODO + +2010-08-17 18:30:17 +0200 Stephan Bosch <stephan@rename-it.nl> (62c79e4b) + + Updated documentation. + + +M INSTALL +M README + +2010-08-17 17:46:12 +0200 Stephan Bosch <stephan@rename-it.nl> (ad9b5110) + + ManageSieve: changed default IMPLEMENTATION capability to 'Dovecot + Pigeonhole'. + + +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve/managesieve-settings.c + +2010-08-17 17:20:58 +0200 Stephan Bosch <stephan@rename-it.nl> (1bc1e36c) + + Renamed 'Dovecot Sieve' to 'Pigeonhole' in source file copyright headers. + + +M src/lib-managesieve/managesieve-parser.c +M src/lib-managesieve/managesieve-parser.h +M src/lib-managesieve/managesieve-quote.c +M src/lib-managesieve/managesieve-quote.h +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/mail-raw.h +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/cmp-i-ascii-casemap.c +M src/lib-sieve/cmp-i-octet.c +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/ext-date-common.h +M src/lib-sieve/plugins/date/ext-date.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify-limits.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.h +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/environment/ext-environment-common.h +M src/lib-sieve/plugins/environment/ext-environment.c +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-limits.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/mailbox/ext-mailbox-common.h +M src/lib-sieve/plugins/mailbox/ext-mailbox.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.h +M src/lib-sieve/plugins/notify/ext-notify-limits.h +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/plugins/regex/ext-regex-common.c +M src/lib-sieve/plugins/regex/ext-regex-common.h +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.h +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables-dump.h +M src/lib-sieve/plugins/variables/ext-variables-limits.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-name.c +M src/lib-sieve/plugins/variables/ext-variables-name.h +M src/lib-sieve/plugins/variables/ext-variables-namespaces.c +M src/lib-sieve/plugins/variables/ext-variables-namespaces.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/rfc2822.c +M src/lib-sieve/rfc2822.h +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary-code.c +M src/lib-sieve/sieve-binary-debug.c +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-objects.c +M src/lib-sieve/sieve-objects.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-plugins.c +M src/lib-sieve/sieve-plugins.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-runtime-trace.c +M src/lib-sieve/sieve-runtime-trace.h +M src/lib-sieve/sieve-runtime.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve-smtp.c +M src/lib-sieve/sieve-smtp.h +M src/lib-sieve/sieve-stringlist.c +M src/lib-sieve/sieve-stringlist.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c +M src/lib-sieve/tst-truefalse.c +M src/lib-sievestorage/sieve-storage-list.c +M src/lib-sievestorage/sieve-storage-list.h +M src/lib-sievestorage/sieve-storage-private.h +M src/lib-sievestorage/sieve-storage-quota.c +M src/lib-sievestorage/sieve-storage-quota.h +M src/lib-sievestorage/sieve-storage-save.c +M src/lib-sievestorage/sieve-storage-save.h +M src/lib-sievestorage/sieve-storage-script.c +M src/lib-sievestorage/sieve-storage-script.h +M src/lib-sievestorage/sieve-storage.c +M src/lib-sievestorage/sieve-storage.h +M src/managesieve-login/client-authenticate.c +M src/managesieve-login/client-authenticate.h +M src/managesieve-login/client.c +M src/managesieve-login/client.h +M src/managesieve-login/managesieve-login-settings-plugin.c +M src/managesieve-login/managesieve-login-settings-plugin.h +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve-login/managesieve-login-settings.h +M src/managesieve-login/managesieve-proxy.c +M src/managesieve-login/managesieve-proxy.h +M src/managesieve/cmd-capability.c +M src/managesieve/cmd-deletescript.c +M src/managesieve/cmd-getscript.c +M src/managesieve/cmd-havespace.c +M src/managesieve/cmd-listscripts.c +M src/managesieve/cmd-logout.c +M src/managesieve/cmd-noop.c +M src/managesieve/cmd-putscript.c +M src/managesieve/cmd-renamescript.c +M src/managesieve/cmd-setactive.c +M src/managesieve/main.c +M src/managesieve/managesieve-capabilities.c +M src/managesieve/managesieve-capabilities.h +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h +M src/managesieve/managesieve-commands.c +M src/managesieve/managesieve-commands.h +M src/managesieve/managesieve-common.h +M src/managesieve/managesieve-quota.c +M src/managesieve/managesieve-quota.h +M src/managesieve/managesieve-settings.c +M src/managesieve/managesieve-settings.h +M src/plugins/lda-sieve/lda-sieve-log.c +M src/plugins/lda-sieve/lda-sieve-log.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/plugins/lda-sieve/lda-sieve-plugin.h +M src/sieve-tools/debug/cmd-debug-print.c +M src/sieve-tools/debug/ext-debug-common.h +M src/sieve-tools/debug/ext-debug.c +M src/sieve-tools/debug/sieve-ext-debug.h +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/sieve-tools/sieved.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-result-print.c +M src/testsuite/cmd-test-result-reset.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-arguments.c +M src/testsuite/testsuite-arguments.h +M src/testsuite/testsuite-binary.c +M src/testsuite/testsuite-binary.h +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-log.h +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-result.h +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-script.h +M src/testsuite/testsuite-settings.c +M src/testsuite/testsuite-settings.h +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite-substitutions.c +M src/testsuite/testsuite-substitutions.h +M src/testsuite/testsuite.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-result.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c + +2010-08-14 00:57:32 +0200 Stephan Bosch <stephan@rename-it.nl> (4d24bfe0) + + Fixed source file header comments. + + +M src/lib-sieve/sieve-runtime-trace.c +M src/lib-sieve/sieve-runtime-trace.h +M src/lib-sieve/sieve-stringlist.c +M src/lib-sieve/sieve-stringlist.h + +2010-08-14 00:42:24 +0200 Stephan Bosch <stephan@rename-it.nl> (dddd17ee) + + Testsuite: added a few test for the regex extension. + + +M tests/extensions/regex/basic.svtest + +2010-08-14 00:25:44 +0200 Stephan Bosch <stephan@rename-it.nl> (448b8065) + + Fixed Valgrind error. + + +M src/lib-sieve-tool/sieve-tool.c + +2010-08-14 00:06:22 +0200 Stephan Bosch <stephan@rename-it.nl> (8f90c58c) + + Improved runtime error handing. + + - Changed operand read functions to prove exec status return codes in stead + of boolean. + - Restructured optional-operand, stringlist and string-match APIs to provide + execution status (error code) upon failure. + - Corruption errors are only produced when the binary is actually corrupt. + Normal failures should never cause a recompile attempt anymore. + - Simplified optional-operand API. + - Cleaned up test command implementations that use the string-match API. + +M TODO +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-namespaces.c +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-objects.c +M src/lib-sieve/sieve-runtime-trace.c +M src/lib-sieve/sieve-runtime-trace.h +M src/lib-sieve/sieve-stringlist.c +M src/lib-sieve/sieve-stringlist.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c +M src/managesieve/cmd-putscript.c +M src/sieve-tools/debug/cmd-debug-print.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-substitutions.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c + +2010-08-12 16:28:02 +0200 Stephan Bosch <stephan@rename-it.nl> (4022e5af) + + Produce a nicer error message when trying to load with non-lda/lmtp binary + (patch by Timo Sirainen). + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2010-08-12 14:43:04 +0200 Stephan Bosch <stephan@rename-it.nl> (a9dc6837) + + Regex match: fixed segfault at deinitialization. + + +M src/lib-sieve/plugins/regex/mcht-regex.c + +2010-08-12 14:41:46 +0200 Stephan Bosch <stephan@rename-it.nl> (471e91b2) + + Updated TODO + + +M TODO + +2010-08-12 00:56:33 +0200 Stephan Bosch <stephan@rename-it.nl> (4f8c4dbc) + + Fixed compile on Solaris 10 with SunStudio 12.1 (patch by Willi Burmeister). + + +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-stringlist.h + +2010-08-11 18:20:41 +0200 Stephan Bosch <stephan@rename-it.nl> (6f0cf81a) + + Improved and simplified file error handling + + - Administrators now get properly notified about uncompiled global scripts + and the inability of the sieve plugin to store global binaries. + - Improved binary load/save error handling and fixed a few smal bugs. + - Simplified ManageSieve error handling. + +M TODO +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/sieve-binary-file.c +M src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sievestorage/Makefile.am +D src/lib-sievestorage/sieve-storage-error.h +M src/lib-sievestorage/sieve-storage-list.c +M src/lib-sievestorage/sieve-storage-private.h +M src/lib-sievestorage/sieve-storage-quota.c +M src/lib-sievestorage/sieve-storage-save.c +M src/lib-sievestorage/sieve-storage-script.c +M src/lib-sievestorage/sieve-storage-script.h +M src/lib-sievestorage/sieve-storage.c +M src/lib-sievestorage/sieve-storage.h +M src/managesieve/cmd-deletescript.c +M src/managesieve/cmd-getscript.c +M src/managesieve/cmd-putscript.c +M src/managesieve/cmd-renamescript.c +M src/managesieve/cmd-setactive.c +M src/managesieve/managesieve-client.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/sieve-tools/sieved.c +M src/testsuite/testsuite-binary.c +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite.c + +2010-08-11 18:10:46 +0200 Stephan Bosch <stephan@rename-it.nl> (36ef3b4d) + + ManageSieve/Sieve storag: fixed error handling of PUTSCRIPT commmand; save + commit errors would not make the command fail. + + +M src/lib-sievestorage/sieve-storage-save.c + +2010-08-11 17:25:48 +0200 Stephan Bosch <stephan@rename-it.nl> (56ef5958) + + Fixed segfault occuring when loaded binary block turns out to be corrupt. + + +M src/lib-sieve/sieve-interpreter.c + +2010-08-11 16:55:11 +0200 Stephan Bosch <stephan@rename-it.nl> (285f36d4) + + Multiscript: fixed duplicate implicit keep caused by erroneous execution + state update. + + +M src/lib-sieve/sieve.c + +2010-08-11 14:27:09 +0200 Stephan Bosch <stephan@rename-it.nl> (9bbcb23f) + + Prevent assertion failure due to currupt binary string representation + (missing \0). + + +M src/lib-sieve/sieve-binary-code.c + +2010-08-11 13:52:59 +0200 Stephan Bosch <stephan@rename-it.nl> (27dc72bd) + + LDA Sieve plugin: fixed sieve_global_path setting; it was not recognized. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2010-08-08 11:21:04 +0200 Stephan Bosch <stephan@rename-it.nl> (9b0b57fa) + + Fixed segfault in tools and testsuite occuring when no username can be + determined. + + +M src/lib-sieve-tool/sieve-tool.c + +2010-08-06 16:17:31 +0200 Stephan Bosch <stephan@rename-it.nl> (555a749a) + + ManageSieve: fixed SASL negotiation; mechanisms that need a roundtrip were + broken. + + +M src/managesieve-login/client-authenticate.c + +2010-08-04 18:19:59 +0200 Stephan Bosch <stephan@rename-it.nl> (9cb8afb7) + + Fixed compiler warnings in tst-size.c + + +M src/lib-sieve/tst-size.c + +2010-08-03 18:58:36 +0200 Stephan Bosch <stephan@rename-it.nl> (5551ad02) + + Improved runtime trace debugging towards something more intuitively + readable. + + +M TODO +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-runtime-trace.c +M src/lib-sieve/sieve-runtime-trace.h +M src/lib-sieve/sieve-runtime.h +M src/lib-sieve/sieve-stringlist.h +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-size.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-result-print.c +M src/testsuite/cmd-test-result-reset.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-script.h +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-result.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c + +2010-08-03 18:30:14 +0200 Stephan Bosch <stephan@rename-it.nl> (41c3ef6a) + + Imap4flags: fixed bug in setflag command; when parameter was a stringlist, + only the last item was actually set. + + +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M tests/extensions/imap4flags/basic.svtest + +2010-08-03 15:58:36 +0200 Stephan Bosch <stephan@rename-it.nl> (2faf5329) + + Fixed bug in error handling of store action. + + +M src/lib-sieve/sieve-actions.c +M tests/execute/errors.svtest +A tests/execute/errors/fileinto-invalid-name.sieve + +2010-08-03 12:29:46 +0200 Stephan Bosch <stephan@rename-it.nl> (2c57e513) + + Testsuite: prevented warning messages from showing up by default. + + +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-log.h +M src/testsuite/testsuite.c + +2010-08-03 03:10:22 +0200 Stephan Bosch <stephan@rename-it.nl> (00194238) + + Testsuite: fixed segfault problem. + + +M src/lib-sieve-tool/sieve-tool.c + +2010-08-02 16:14:10 +0200 Stephan Bosch <stephan@rename-it.nl> (a5ceb7e0) + + Testsuite: added missing test case for the size test. + + +M Makefile.am +A tests/size.svtest + +2010-08-02 15:19:05 +0200 Stephan Bosch <stephan@rename-it.nl> (1245cf0c) + + Testsuite: minor cleanups. + + +M src/testsuite/testsuite.c + +2010-08-02 15:18:51 +0200 Stephan Bosch <stephan@rename-it.nl> (fd849304) + + Sieve tools: don't try to close stdout. + + +M src/lib-sieve-tool/sieve-tool.c + +2010-08-02 15:00:00 +0200 Stephan Bosch <stephan@rename-it.nl> (1753c207) + + Sieve-test tool: accidentally disabled -d option. + + +M src/sieve-tools/sieve-test.c + +2010-08-02 14:59:06 +0200 Stephan Bosch <stephan@rename-it.nl> (025065a9) + + Improved byte code encoding implementation of integers and offsets. + + +M src/lib-sieve/sieve-binary-code.c + +2010-07-30 19:03:30 +0200 Stephan Bosch <stephan@rename-it.nl> (b9be8e38) + + Sieve binary: now using better defined integer types for byte-coded data + + +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/sieve-binary-code.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-interpreter.c +M src/testsuite/cmd-test-fail.c + +2010-07-30 17:07:56 +0200 Stephan Bosch <stephan@rename-it.nl> (9e63fecd) + + Updated TODO. + + +M TODO + +2010-07-30 16:32:19 +0200 Stephan Bosch <stephan@rename-it.nl> (a7849cad) + + Variables extension: fixed :length set modifier to recognize utf8 characters + in stead of octets. + + +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M tests/extensions/variables/modifiers.svtest + +2010-07-30 14:53:14 +0200 Stephan Bosch <stephan@rename-it.nl> (169dd8d4) + + Implemented generic string list interface and simplified matching API. + + +M TODO +M src/lib-sieve/Makefile.am +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/ext-date-common.h +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +A src/lib-sieve/sieve-stringlist.c +A src/lib-sieve/sieve-stringlist.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-log.h +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-result.h +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result.c +M tests/extensions/envelope.svtest + +2010-07-30 09:16:13 +0200 Stephan Bosch <stephan@rename-it.nl> (67db254e) + + Fixed sieve-test not to start in trace mode by default. + + +M src/sieve-tools/sieve-test.c + +2010-07-29 11:53:26 +0200 Stephan Bosch <stephan@rename-it.nl> (a83e91bc) + + Updated extension status information. + + +M README +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/date/ext-date.c +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/environment/ext-environment.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/mailbox/ext-mailbox.c +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/ext-variables.c +M src/sieve-tools/debug/ext-debug.c +M src/testsuite/ext-testsuite.c + +2010-07-28 15:01:26 +0200 Stephan Bosch <stephan@rename-it.nl> (d7f19d39) + + ManageSieve: fixed deinitialization problem in dump-capability plugin. + + +M src/managesieve-login/managesieve-login-settings-plugin.c + +2010-07-21 21:15:12 +0200 Stephan Bosch <stephan@rename-it.nl> (9f99c4ca) + + ManageSieve: fixed dump-capability hang. + + +M src/managesieve-login/managesieve-login-settings-plugin.c + +2010-07-21 17:43:16 +0200 Stephan Bosch <stephan@rename-it.nl> (a5f3a29c) + + Further developed new runtime trace debugging; test suite is also now + included. + + +M Makefile.am +M doc/man/sieve-test.1 +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-runtime-trace.c +M src/lib-sieve/sieve-runtime-trace.h +M src/sieve-tools/sieve-test.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test.c +M src/testsuite/testsuite.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-execute.c + +2010-07-20 13:29:46 +0200 Stephan Bosch <stephan@rename-it.nl> (23ac203c) + + Makefile fix: rhel5 still has too old automake that doesn't define + $builddir. + + +M src/lib-sieve/Makefile.am +M src/sieve-tools/Makefile.am + +2010-07-17 19:57:25 +0200 Stephan Bosch <stephan@rename-it.nl> (a539090e) + + First changes towards making `make distcheck' work. + + +M Makefile.am +M configure.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/body/Makefile.am +M src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.am +M src/lib-sieve/plugins/copy/Makefile.am +M src/lib-sieve/plugins/date/Makefile.am +M src/lib-sieve/plugins/enotify/Makefile.am +M src/lib-sieve/plugins/enotify/mailto/Makefile.am +M src/lib-sieve/plugins/environment/Makefile.am +M src/lib-sieve/plugins/imap4flags/Makefile.am +M src/lib-sieve/plugins/include/Makefile.am +M src/lib-sieve/plugins/mailbox/Makefile.am +M src/lib-sieve/plugins/notify/Makefile.am +M src/lib-sieve/plugins/regex/Makefile.am +M src/lib-sieve/plugins/relational/Makefile.am +M src/lib-sieve/plugins/spamvirustest/Makefile.am +M src/lib-sieve/plugins/subaddress/Makefile.am +M src/lib-sieve/plugins/vacation/Makefile.am +M src/lib-sieve/plugins/variables/Makefile.am +M src/managesieve-login/Makefile.am +M src/managesieve/Makefile.am +M src/plugins/lda-sieve/Makefile.am +M src/sieve-tools/Makefile.am +M src/testsuite/Makefile.am + +2010-07-17 12:11:58 +0200 Stephan Bosch <stephan@rename-it.nl> (4dcd092f) + + Improved runtime trace debugging output for core Sieve language. + + +M TODO +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-runtime-trace.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/sieve-tools/sieve-test.c + +2010-07-16 21:31:46 +0200 Stephan Bosch <stephan@rename-it.nl> (d7b179a8) + + Adjusted to Dovecot LDA API changes; implicitly fixing segfault (patch by + Timo Sirainen). + + +M src/lib-sieve/sieve-actions.c + +2010-07-16 21:11:25 +0200 Stephan Bosch <stephan@rename-it.nl> (21a326f0) + + Updated dovecot.m4. + + +M m4/dovecot.m4 + +2010-07-16 10:02:20 +0200 Stephan Bosch <stephan@rename-it.nl> (3806f628) + + Removed unused code that caused compile failure due to Dovecot API change. + + +M src/lib-sieve-tool/mail-raw.c +M src/managesieve/managesieve-capabilities.c + +2010-07-15 00:45:37 +0200 Stephan Bosch <stephan@rename-it.nl> (969dec8b) + + Implemented simple runtime trace of string value matching. + + +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-match.c + +2010-07-14 23:55:21 +0200 Stephan Bosch <stephan@rename-it.nl> (7da1cc6e) + + Adjusted string matching API tu use runtime environment. + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-header.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-result.c + +2010-07-13 20:08:24 +0200 Stephan Bosch <stephan@rename-it.nl> (8582f2af) + + Updated ManageSieve specification. + + +R057 doc/rfc/draft-ietf-sieve-managesieve-09.txt doc/rfc/managesieve.rfc5804.txt + +2010-07-13 18:15:44 +0200 Stephan Bosch <stephan@rename-it.nl> (a86e0043) + + Updated TODO list. + + +M TODO + +2010-07-13 18:09:32 +0200 Stephan Bosch <stephan@rename-it.nl> (e7d75edc) + + Testsuite: inappropriately removed initialization of dummy MAIL environment. + + +M src/testsuite/testsuite.c + +2010-07-11 17:06:31 +0200 Stephan Bosch <stephan@rename-it.nl> (ed9c1bae) + + Sieve tools: added support for extended trace debugging and updated man + pages. + + +M doc/man/sieve-filter.1 +M doc/man/sieve-test.1 +M doc/man/sievec.1 +M doc/man/sieved.1 +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-runtime-trace.h +M src/lib-sieve/sieve-runtime.h +M src/lib-sieve/sieve-types.h +M src/sieve-tools/sieve-test.c +M src/testsuite/cmd-test.c +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite.c + +2010-07-11 12:40:00 +0200 Stephan Bosch <stephan@rename-it.nl> (68a275be) + + Updated documentation: Sieve tools are now using Dovecot configuration by + default. + + +M TODO +M doc/man/sieve-filter.1 +M doc/man/sieve-test.1 +M doc/man/sievec.1 +M doc/man/sieved.1 + +2010-07-10 18:53:40 +0200 Stephan Bosch <stephan@rename-it.nl> (3322ab5a) + + Sieve-tools: use 'mail' as module name in stead of the name of the command. + + +M src/lib-sieve-tool/sieve-tool.c + +2010-07-10 18:06:28 +0200 Stephan Bosch <stephan@rename-it.nl> (421de7a5) + + Sieve-tools: was using wrong mail_user variable for settings acquisition. + + +M src/lib-sieve-tool/sieve-tool.c + +2010-07-10 13:21:14 +0200 Stephan Bosch <stephan@rename-it.nl> (002cae7e) + + Increased initial pool sieve for Sieve logfile and varexpand error handlers. + + +M src/lib-sieve/sieve-error.c + +2010-07-10 13:14:53 +0200 Stephan Bosch <stephan@rename-it.nl> (4702320d) + + Restructured and cleaned up the Sieve tools and the Sieve tool library. + + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/mail-raw.h +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/sieve-tools/sieved.c +M src/testsuite/testsuite-binary.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-settings.c +M src/testsuite/testsuite-settings.h +M src/testsuite/testsuite.c + +2010-07-08 00:47:26 +0200 Stephan Bosch <stephan@rename-it.nl> (ed89527b) + + Testsuite: improved test for fileinto with non-existent mailbox. + + +M tests/execute/errors.svtest + +2010-07-08 00:06:42 +0200 Stephan Bosch <stephan@rename-it.nl> (6b0c7726) + + Fixed assertion failure in the keep/fileinto store actions and added + testsuite item. + + +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/sieve-actions.c +M tests/execute/errors.svtest +A tests/execute/errors/fileinto.sieve + +2010-07-05 17:18:23 +0200 Stephan Bosch <stephan@rename-it.nl> (b2be9010) + + Fixed small discrepancy in example configuration. + + +M doc/example-config/conf.d/90-sieve.conf + +2010-07-05 16:45:12 +0200 Stephan Bosch <stephan@rename-it.nl> (156f4a7c) + + ManageSieve: fixed fd leak caused by DUMP_CAPABILITY execution. + + +M src/managesieve/main.c + +2010-07-05 14:32:17 +0200 Stephan Bosch <stephan@rename-it.nl> (33e76f80) + + Updated documentation. + + +M INSTALL +M doc/example-config/conf.d/20-managesieve.conf + +2010-07-04 01:22:40 +0200 Stephan Bosch <stephan@rename-it.nl> (89b9268f) + + Sieve-tools: removed KEEP_CONFIG_OPEN service flag. + + +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/sieve-tools/sieved.c + +2010-07-04 00:22:09 +0200 Stephan Bosch <stephan@rename-it.nl> (98e994ca) + + Fixed compiler warning caused by previous change. + + +M src/managesieve/managesieve-capabilities.c + +2010-07-03 23:32:28 +0200 Stephan Bosch <stephan@rename-it.nl> (91f29b82) + + Moved parsing of sieve_extensions setting to sieve engine initialization. + + +M src/lib-sieve/sieve-extensions.c +M src/managesieve/managesieve-capabilities.c +M src/managesieve/managesieve-client.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2010-07-03 22:49:21 +0200 Stephan Bosch <stephan@rename-it.nl> (ca60b0da) + + Fixed compiler warnings in previous change. + + +M src/sieve-tools/sievec.c +M src/sieve-tools/sieved.c + +2010-07-03 22:44:49 +0200 Stephan Bosch <stephan@rename-it.nl> (cc9d3eb3) + + Sieve-Tools: fully use Dovecot service and settings API. + + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/sieve-script.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/sieve-tools/sieved.c +M src/testsuite/testsuite.c + +2010-07-03 19:07:52 +0200 Stephan Bosch <stephan@rename-it.nl> (80dd4bc6) + + Updated TODO list. + + +M TODO + +2010-07-03 18:32:09 +0200 Stephan Bosch <stephan@rename-it.nl> (4f487241) + + ManageSieve: reactivated reporting of NOTIFY capability. + + +M src/managesieve-login/client.c +M src/managesieve-login/managesieve-login-settings.c + +2010-07-03 18:07:30 +0200 Stephan Bosch <stephan@rename-it.nl> (88b1d0dc) + + ManageSieve: removed service/managesieve-login from dynamically assinged + settings. + + +M src/managesieve-login/managesieve-login-settings-plugin.c + +2010-07-03 17:37:49 +0200 Stephan Bosch <stephan@rename-it.nl> (fda83b69) + + ManageSieve: added -k to dump capability invocation of managesieve binary. + + +M src/managesieve-login/managesieve-login-settings-plugin.c + +2010-07-03 17:04:06 +0200 Stephan Bosch <stephan@rename-it.nl> (ca5e55cb) + + ManageSieve: check for DUMP_CAPABILITY=1 before executing dump capability to + prevent infinite recursion. + + +M src/managesieve-login/managesieve-login-settings-plugin.c + +2010-07-03 16:27:33 +0200 Stephan Bosch <stephan@rename-it.nl> (3451298d) + + ManageSieve: forgot to include settings in doveconf plugin. + + +M src/managesieve-login/Makefile.am +M src/managesieve-login/managesieve-login-settings-plugin.c + +2010-07-03 15:09:57 +0200 Stephan Bosch <stephan@rename-it.nl> (7a383a98) + + ManageSieve: doveconf went berserk with last change. + + +M src/managesieve-login/managesieve-login-settings-plugin.c + +2010-07-03 14:21:38 +0200 Stephan Bosch <stephan@rename-it.nl> (03c8bfc7) + + ManageSieve: enabled dynamic capability inference. + + +M m4/dovecot.m4 +M src/managesieve-login/Makefile.am +A src/managesieve-login/managesieve-login-settings-plugin.c +A src/managesieve-login/managesieve-login-settings-plugin.h +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve-login/managesieve-login-settings.h + +2010-07-01 11:16:45 +0200 Stephan Bosch <stephan@rename-it.nl> (21b4e147) + + managesieve: Added an assert to client_connected(). + + +M src/managesieve/main.c + +2010-06-28 14:35:07 +0200 Stephan Bosch <stephan@rename-it.nl> (19d0fd3f) + + Updated TODO list. + + +M TODO + +2010-06-26 00:51:33 +0200 Stephan Bosch <stephan@rename-it.nl> (f1659db4) + + ManageSieve: forgot to change login unix socket name. + + +M src/managesieve/managesieve-settings.c + +2010-06-26 00:27:34 +0200 Stephan Bosch <stephan@rename-it.nl> (8fc82ea2) + + Use new LDA deliver save API (patch by Timo Sirainen). + + +M src/lib-sieve/sieve-actions.c + +2010-06-26 00:05:02 +0200 Stephan Bosch <stephan@rename-it.nl> (b5fe7d25) + + ManageSieve: small patch to service settings. + + +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve/managesieve-settings.c + +2010-06-24 17:04:41 +0200 Stephan Bosch <stephan@rename-it.nl> (93034e37) + + ManageSieve: forgot to change protocol name to 'sieve' in login_binary + struct. + + +M src/managesieve-login/client.c + +2010-06-19 17:36:18 +0200 Stephan Bosch <stephan@rename-it.nl> (b36c68bf) + + Variables extension: added proper trace support. + + +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/sieve-runtime-trace.h + +2010-06-19 13:07:10 +0200 Stephan Bosch <stephan@rename-it.nl> (14e91a15) + + Cleaned up mail storage-related code (modified patch by Timo Sirainen). + + +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-types.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite.c + +2010-06-19 11:32:00 +0200 Stephan Bosch <stephan@rename-it.nl> (744b97ab) + + Updated documentation. + + +M INSTALL +M doc/example-config/conf.d/90-sieve.conf + +2010-06-19 11:00:37 +0200 Stephan Bosch <stephan@rename-it.nl> (008b424c) + + Fixed error handling of failed mailbox creation (patch by Timo Sirainen). + + +M src/lib-sieve/sieve-actions.c + +2010-06-19 10:57:23 +0200 Stephan Bosch <stephan@rename-it.nl> (fe8fbf1f) + + Changed ManageSieve protocol name to 'sieve'. + + +M doc/example-config/conf.d/20-managesieve.conf +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve/managesieve-settings.c + +2010-05-30 09:39:19 +0200 Stephan Bosch <stephan@rename-it.nl> (d853dbb0) + + Forgot an active TODO item on the list. + + +M TODO + +2010-05-30 09:37:28 +0200 Stephan Bosch <stephan@rename-it.nl> (d6df4c06) + + Updated to changes in Dovecot service API. + + +M src/managesieve/main.c + +2010-05-19 17:04:42 +0200 Stephan Bosch <stephan@rename-it.nl> (e0afdfc6) + + Include extension: accidentally committed debug printf. + + +M src/lib-sieve/plugins/include/ext-include-binary.c + +2010-05-19 17:00:44 +0200 Stephan Bosch <stephan@rename-it.nl> (d6babbda) + + Explicitly set AC_CONFIG_AUX_DIR to prevent issues when compiling Pigeonhole + in a sub-directory of the Dovecot tree. + + +M configure.in + +2010-05-16 18:12:56 +0200 Stephan Bosch <stephan@rename-it.nl> (d609cc7c) + + Updated TODO. + + +M TODO + +2010-05-16 14:43:43 +0200 Stephan Bosch <stephan@rename-it.nl> (c0c60be5) + + Restructured and cleaned up trace debugging and optional operand fetching. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +A src/lib-sieve/sieve-runtime-trace.c +A src/lib-sieve/sieve-runtime-trace.h +A src/lib-sieve/sieve-runtime.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c +M src/sieve-tools/debug/cmd-debug-print.c +M src/sieve-tools/sieve-test.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-result.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c + +2010-05-14 22:57:06 +0200 Stephan Bosch <stephan@rename-it.nl> (60f2c55f) + + Added debug mode to the Sieve engine. + + +M doc/man/sieve-test.1 +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/managesieve/managesieve-capabilities.c +M src/managesieve/managesieve-client.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/sieve-tools/sieved.c +M src/testsuite/testsuite.c + +2010-05-14 14:35:19 +0200 Stephan Bosch <stephan@rename-it.nl> (9ca03cee) + + Testsuite: forgot to add -P plugin parameter to executable. + + +M src/testsuite/testsuite.c + +2010-05-14 14:03:09 +0200 Stephan Bosch <stephan@rename-it.nl> (282701a9) + + Updated TODO. + + +M TODO + +2010-05-14 14:02:48 +0200 Stephan Bosch <stephan@rename-it.nl> (7e6c0d49) + + Made action commands use new lineinfo facility. + + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h + +2010-05-14 13:08:14 +0200 Stephan Bosch <stephan@rename-it.nl> (691db805) + + Restructured binary implementation and added lineinfo debug blocks to the + binary. + + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-namespaces.c +M src/lib-sieve/plugins/variables/ext-variables-namespaces.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +A src/lib-sieve/sieve-binary-code.c +A src/lib-sieve/sieve-binary-debug.c +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-dumper.h +A src/lib-sieve/sieve-binary-file.c +A src/lib-sieve/sieve-binary-private.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-objects.c +M src/lib-sieve/sieve-objects.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c +M src/lib-sieve/tst-truefalse.c +M src/sieve-tools/debug/cmd-debug-print.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-config.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-result-print.c +M src/testsuite/cmd-test-result-reset.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h +M src/testsuite/testsuite-substitutions.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-result.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c + +2010-05-14 12:34:59 +0200 Stephan Bosch <stephan@rename-it.nl> (278b251d) + + Lexer: made sure source code positions are recorded at start of token. + + +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-parser.c + +2010-05-14 12:16:52 +0200 Stephan Bosch <stephan@rename-it.nl> (93c1be50) + + Spamtest/Virustest extensions: forgot to call extension unload handler. + + +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c + +2010-05-14 11:25:25 +0200 Stephan Bosch <stephan@rename-it.nl> (8706f5b1) + + Fixed potential deinitialization problem in interpreter. + + +M src/lib-sieve/sieve-interpreter.c + +2010-05-14 11:23:55 +0200 Stephan Bosch <stephan@rename-it.nl> (a915ee9b) + + Fixed potential memory leak in generator. + + +M src/lib-sieve/sieve-generator.c + +2010-05-14 12:37:39 +0200 Stephan Bosch <stephan@rename-it.nl> (1169fe8a) + + Updated TODO. + + +M TODO + +2010-05-05 21:11:18 +0200 Stephan Bosch <stephan@rename-it.nl> (ba056452) + + ManageSieve: disabled dynamic capability determination for now. + + +M src/managesieve-login/managesieve-login-settings.c + +2010-05-05 20:21:50 +0200 Stephan Bosch <stephan@rename-it.nl> (b969c57e) + + ManageSieve: dump_capability: simplified settings acquisition. + + +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve/managesieve-capabilities.c + +2010-05-05 19:39:26 +0200 Stephan Bosch <stephan@rename-it.nl> (137551e9) + + ManageSieve: implemented user-independent capability dumping (untested). + + +M src/managesieve/Makefile.am +M src/managesieve/main.c +A src/managesieve/managesieve-capabilities.c +A src/managesieve/managesieve-capabilities.h +M src/managesieve/managesieve-client.c + +2010-05-05 17:28:13 +0200 Stephan Bosch <stephan@rename-it.nl> (164c2465) + + ManageSieve: don't use i_fatal() in doveconf plugin. + + +M src/managesieve-login/managesieve-login-settings.c + +2010-05-05 16:56:12 +0200 Stephan Bosch <stephan@rename-it.nl> (fc08f6b6) + + ManageSieve: fixed segfault bug in doveconf plugin and fixed compiler + warnings. + + +M src/managesieve-login/managesieve-login-settings.c + +2010-05-05 16:04:31 +0200 Stephan Bosch <stephan@rename-it.nl> (28f2359f) + + ManageSieve: implemented dynamic capability determination at login. + + +M src/managesieve-login/Makefile.am +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve-login/managesieve-login-settings.h +M src/managesieve/main.c +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h + +2010-05-05 15:43:54 +0200 Stephan Bosch <stephan@rename-it.nl> (f5df2f66) + + ManageSieve: fixed compile error in previous change. + + +M src/managesieve/managesieve-client.c + +2010-05-05 15:42:44 +0200 Stephan Bosch <stephan@rename-it.nl> (1403221c) + + ManageSieve: forgot to initialize Sieve extensions. + + +M src/managesieve/managesieve-client.c + +2010-05-03 20:02:55 +0200 Stephan Bosch <stephan@rename-it.nl> (eab3d162) + + Made command line tools return proper exit status upon failure. + + +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/sieve-tools/sieved.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite.c + +2010-05-02 10:23:14 +0200 Stephan Bosch <stephan@rename-it.nl> (5fe046cf) + + managesieve: updated to changes in Dovecot (IMAP/POP3). + + +M src/managesieve/main.c +M src/managesieve/managesieve-client.c +M src/managesieve/managesieve-client.h +M src/managesieve/managesieve-commands.c + +2010-05-02 09:30:37 +0200 Stephan Bosch <stephan@rename-it.nl> (1298095c) + + sieve-storage: made auto-creation code match implementation of maildir + storage from Dovecot. + + +M src/lib-sievestorage/sieve-storage-private.h +M src/lib-sievestorage/sieve-storage.c + +2010-05-02 09:29:54 +0200 Stephan Bosch <stephan@rename-it.nl> (327f0c28) + + managesieve: changed static IMAP error massage in main.c to ManageSieve + protocol. + + +M src/managesieve/main.c + +2010-04-29 00:34:31 +0200 Stephan Bosch <stephan@rename-it.nl> (16e692f0) + + Compiler warning fix. + + +M src/managesieve/main.c + +2010-04-28 16:31:03 +0200 Stephan Bosch <stephan@rename-it.nl> (e5306691) + + Changed result execution logging to use a var_expand_table created by liblda + to avoid code duplication (patch by Timo Sirainen). + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/sieve-result.c +M src/managesieve/Makefile.am +M src/sieve-tools/Makefile.am +M src/testsuite/Makefile.am + +2010-04-28 16:26:14 +0200 Stephan Bosch <stephan@rename-it.nl> (7c8fc2b1) + + Updated dovecot.m4. + + +M m4/dovecot.m4 + +2010-04-28 16:21:57 +0200 Stephan Bosch <stephan@rename-it.nl> (11b7e197) + + Made var_expand_table argument of sieve_varexpand_ehandler_create const + (patch by Timo Sirainen). + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h + +2010-04-28 16:16:50 +0200 Stephan Bosch <stephan@rename-it.nl> (d0555478) + + Fix CFLAGS and LIBS defines (patch by Timo Sirainen). + + +M configure.in + +2010-04-20 01:16:18 +0200 Stephan Bosch <stephan@rename-it.nl> (3478bfb5) + + Testsuite: avoid using existing e-mail addresses and domains in tests. + + +M tests/address.svtest +M tests/comparators/core.svtest +M tests/compile/errors/address-part.sieve +M tests/compile/errors/envelope.sieve +M tests/compile/errors/match-type.sieve +M tests/compile/errors/out-address.sieve +M tests/compile/errors/unsupported.sieve +M tests/compile/recover/commands-semicolon.sieve +M tests/compile/redirect.sieve +M tests/compile/warnings/invalid-headers.sieve +M tests/control-structures.svtest +M tests/deprecated/notify/basic.svtest +M tests/deprecated/notify/denotify.svtest +M tests/deprecated/notify/errors/options.sieve +M tests/deprecated/notify/execute/duplicates.sieve +M tests/deprecated/notify/mailto.svtest +M tests/execute/actions.svtest +M tests/execute/actions/fileinto.sieve +M tests/execute/actions/redirect.sieve +M tests/execute/mailstore.svtest +M tests/execute/smtp.svtest +M tests/exists.svtest +M tests/extensions/body/basic.svtest +M tests/extensions/body/match-values.svtest +M tests/extensions/date/basic.svtest +M tests/extensions/date/date-parts.svtest +M tests/extensions/date/zones.svtest +M tests/extensions/enotify/basic.svtest +M tests/extensions/enotify/errors/from-mailto.sieve +M tests/extensions/enotify/errors/options.sieve +M tests/extensions/enotify/errors/uri-mailto.sieve +M tests/extensions/enotify/errors/uri.sieve +M tests/extensions/enotify/execute/duplicates.sieve +M tests/extensions/enotify/mailto.svtest +M tests/extensions/enotify/notify_method_capability.svtest +M tests/extensions/enotify/valid_notify_method.svtest +M tests/extensions/envelope.svtest +M tests/extensions/include/execute.svtest +M tests/extensions/include/included/rfc-ex1-mailing_lists.sieve +M tests/extensions/mailbox/execute.svtest +M tests/extensions/regex/basic.svtest +M tests/extensions/regex/errors/compile.sieve +M tests/extensions/regex/match-values.svtest +M tests/extensions/reject/execute.svtest +M tests/extensions/reject/execute/basic.sieve +M tests/extensions/reject/smtp.svtest +M tests/extensions/relational/basic.svtest +M tests/extensions/spamvirustest/spamtest.svtest +M tests/extensions/spamvirustest/spamtestplus.svtest +M tests/extensions/spamvirustest/virustest.svtest +M tests/extensions/subaddress/basic.svtest +M tests/extensions/subaddress/config.svtest +M tests/extensions/subaddress/rfc.svtest +M tests/extensions/vacation/execute/action.sieve +M tests/extensions/vacation/execute/no-handle.sieve +M tests/extensions/vacation/message.svtest +M tests/extensions/vacation/smtp.svtest +M tests/extensions/vacation/utf-8.svtest +M tests/extensions/variables/basic.svtest +M tests/extensions/variables/match.svtest +M tests/header.svtest +M tests/match-types/contains.svtest +M tests/match-types/is.svtest +M tests/match-types/matches.svtest +M tests/multiscript/basic.svtest +M tests/multiscript/conflicts.svtest +M tests/multiscript/notify.sieve +M tests/testsuite.svtest + +2010-04-19 23:38:54 +0200 Stephan Bosch <stephan@rename-it.nl> (76f0f1f4) + + Vacation extension: from address of reply is now by default equal to + whatever known recipient alias matched the headers of the message. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M tests/extensions/vacation/smtp.svtest + +2010-04-19 14:18:17 +0200 Stephan Bosch <stephan@rename-it.nl> (0b1d5db1) + + Removed --install flag from ACLOCAL_AMFLAGS; RHEL uses automake 1.9 and + won't compile. + + +M Makefile.am + +2010-04-14 23:38:44 +0200 Stephan Bosch <stephan@rename-it.nl> (1f8e87b4) + + Added --with-docs configure option. + + +M Makefile.am +M configure.in +M doc/Makefile.am + +2010-04-14 22:05:15 +0200 Stephan Bosch <stephan@rename-it.nl> (35729065) + + Started using dovecot.m4 for linking against Dovecot (patch by Timo + Sirainen). + + +M .hgignore +M Makefile.am +M configure.in +A m4/dovecot.m4 + +2010-04-14 21:48:01 +0200 Stephan Bosch <stephan@rename-it.nl> (2559a3c0) + + Switched to cleaner way to create a raw storage. + + +M src/lib-sieve-tool/mail-raw.c + +2010-04-14 21:45:54 +0200 Stephan Bosch <stephan@rename-it.nl> (2395912f) + + ManageSieve: adjusted to Dovecot login API change. + + +M src/managesieve-login/client.c + +2010-04-14 17:34:30 +0200 Stephan Bosch <stephan@rename-it.nl> (fdce3523) + + Started using tar-ustar for release packaging to prevent crossing path + length limits. + + +M configure.in + +2010-04-14 17:06:33 +0200 Stephan Bosch <stephan@rename-it.nl> (237d092b) + + Assigned temporary version number to avoid confusion with releases for + Dovecot v1.2. + + +M configure.in + +2010-04-14 16:47:05 +0200 Stephan Bosch <stephan@rename-it.nl> (d4031724) + + Changed config file names to match Dovecot numeric config file names. + + +R100 doc/example-config/conf.d/managesieve.conf doc/example-config/conf.d/20-managesieve.conf +R100 doc/example-config/conf.d/sieve.conf doc/example-config/conf.d/90-sieve.conf +M doc/example-config/conf.d/Makefile.am + +2010-04-08 09:13:54 +0200 Stephan Bosch <stephan@rename-it.nl> (ecab4fa1) + + Mailbox extension: fixed memory leak in the mailboxexists test. + + +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c + +2010-04-01 09:41:37 +0200 Stephan Bosch <stephan@rename-it.nl> (408ec9fa) + + ManageSieve: adjusted to changes in service API; added login failure + handler. + + +M src/managesieve/main.c + +2010-03-28 18:16:21 +0200 Stephan Bosch <stephan@rename-it.nl> (f7ed659b) + + Updated TODO list. + + +M TODO + +2010-03-28 18:39:56 +0200 Stephan Bosch <stephan@rename-it.nl> (7928627d) + + Spamtest and virustest: added documentation to the distribution. + + +M doc/Makefile.am + +2010-03-28 18:21:55 +0200 Stephan Bosch <stephan@rename-it.nl> (ad9206ec) + + Spamtest and virustest extensions: added documentation. + + +M INSTALL +A doc/spamtest-virustest.txt + +2010-03-14 17:13:49 +0100 Stephan Bosch <stephan@rename-it.nl> (6a9ad97d) + + Spamtest and virustest extensions: changed setting names. + + +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M tests/extensions/spamvirustest/spamtest.svtest +M tests/extensions/spamvirustest/spamtestplus.svtest + +2010-03-14 12:34:13 +0100 Stephan Bosch <stephan@rename-it.nl> (b98e08cc) + + Spamtest and virustest extensions: now not available by default. + + +M src/lib-sieve/sieve-extensions.c + +2010-03-14 12:19:51 +0100 Stephan Bosch <stephan@rename-it.nl> (9f020ec3) + + Spamtest and virustest extensions: discarded whitespace at beginning of + regexp and added syntax testsuite tests. + + +M Makefile.am +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +A tests/extensions/spamvirustest/errors.svtest +A tests/extensions/spamvirustest/errors/syntax-errors.sieve +M tests/extensions/spamvirustest/spamtest.svtest + +2010-03-27 19:11:09 +0100 Stephan Bosch <stephan@rename-it.nl> (fc22abee) + + Changed ManageSieve client limit to match IMAP/POP3. + + +M src/managesieve/managesieve-settings.c + +2010-03-08 18:48:54 +0100 Stephan Bosch <stephan@rename-it.nl> (beea3d8f) + + Fixed memset argument mixup in enotify extension. + + +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c + +2010-02-28 21:50:04 +0100 Stephan Bosch <stephan@rename-it.nl> (e80633e4) + + Fixed ManageSieve login crash at startup (patch by Timo Sirainen). + + +M src/managesieve-login/client.c + +2010-02-13 12:48:32 +0100 Stephan Bosch <stephan@rename-it.nl> (140dca54) + + ManageSieve: changed default login user to '' substitution. + + +M src/managesieve-login/managesieve-login-settings.c + +2010-02-13 11:48:02 +0100 Stephan Bosch <stephan@rename-it.nl> (52750c58) + + Adjusted to changes in Dovecot mailbox API. + + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/sieve-actions.c +M src/sieve-tools/sieve-filter.c +M src/testsuite/testsuite-mailstore.c + +2010-02-10 17:15:41 +0100 Stephan Bosch <stephan@rename-it.nl> (cb2c985d) + + Adjusted to changes in dovecot-config (patch by Timo Sirainen). + + +M configure.in +M src/lib-sieve-tool/Makefile.am +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/enotify/mailto/Makefile.am +M src/managesieve-login/Makefile.am +M src/managesieve/Makefile.am +M src/plugins/lda-sieve/Makefile.am +M src/sieve-tools/Makefile.am +M src/testsuite/Makefile.am + +2010-02-07 17:45:55 +0100 Stephan Bosch <stephan@rename-it.nl> (b02faa15) + + Adjusted to change in Dovecot Storage API. + + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/sieve-actions.c +M src/testsuite/testsuite-mailstore.c + +2010-01-31 17:06:24 +0100 Stephan Bosch <stephan@rename-it.nl> (c5b63ec5) + + Let configure automatically infer path to installed Dovecot and don't rely + on installed libtool .la files anymore (patch by Timo Sirainen). + + +M configure.in +M src/managesieve-login/Makefile.am +M src/managesieve/Makefile.am +M src/sieve-tools/Makefile.am +M src/testsuite/Makefile.am + +2010-01-31 16:12:46 +0100 Stephan Bosch <stephan@rename-it.nl> (c6805328) + + Deprecated notify extension: fixed compiler warning. + + +M src/lib-sieve/plugins/notify/ext-notify-common.c + +2010-01-31 16:31:49 +0100 Stephan Bosch <stephan@rename-it.nl> (909e7e83) + + Simplified package configuration with respect to linking against Dovecot + (patch by Timo Sirainen). + + +M configure.in +M src/lib-sieve/plugins/enotify/mailto/Makefile.am +M src/sieve-tools/Makefile.am +M src/testsuite/Makefile.am + +2010-01-31 12:37:46 +0100 Stephan Bosch <stephan@rename-it.nl> (7cb7df25) + + Restructured and optimized lexical scanner. + + +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-parser.c + +2010-01-28 22:15:00 +0100 Stephan Bosch <stephan@rename-it.nl> (bb309113) + + Fixed spelling of 'existent' in various testsuite scripts. + + +M tests/exists.svtest +M tests/extensions/body/basic.svtest +M tests/extensions/environment/rfc.svtest +M tests/extensions/include/errors/generic.sieve +M tests/extensions/subaddress/basic.svtest +M tests/header.svtest + +2010-01-28 22:09:07 +0100 Stephan Bosch <stephan@rename-it.nl> (29bbcb7b) + + Fixed copy-paste error in previous change regarding inet_listener. + + +M src/managesieve-login/managesieve-login-settings.c + +2010-01-28 11:00:41 +0100 Stephan Bosch <stephan@rename-it.nl> (c64b646f) + + Added default inet_listener for managesieve-login. + + +M doc/example-config/conf.d/managesieve.conf +M src/managesieve-login/managesieve-login-settings.c + +2010-01-28 09:38:36 +0100 Stephan Bosch <stephan@rename-it.nl> (d10c177e) + + Reverted ManageSieve protocol name back from 'sieve' to 'managesieve'. + + +M INSTALL +M doc/example-config/conf.d/managesieve.conf +M src/managesieve-login/client.c +M src/managesieve-login/managesieve-login-settings.c +M src/managesieve/main.c +M src/managesieve/managesieve-settings.c + +2010-01-27 19:59:34 +0100 Stephan Bosch <stephan@rename-it.nl> (701339a0) + + Deprecated imapflags extension: added proper tests to the test suite. + + +M Makefile.am +R100 tests/extensions/imap4flags/errors.svtest tests/deprecated/imapflags/errors.svtest +R100 tests/extensions/imap4flags/errors/imapflags.sieve tests/deprecated/imapflags/errors/imapflags.sieve +A tests/deprecated/imapflags/execute.svtest +A tests/deprecated/imapflags/execute/flags.sieve +A tests/deprecated/imapflags/execute/mark.sieve +D tests/extensions/imap4flags/execute/imapflags.sieve + +2010-01-27 19:02:12 +0100 Stephan Bosch <stephan@rename-it.nl> (7de56e84) + + Deprecated imapflags extension: fixed implicit assignment of flags. + + +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c + +2010-01-28 09:20:28 +0100 Stephan Bosch <stephan@rename-it.nl> (86149cdf) + + Updated TODO list. + + +M TODO + +2010-01-25 21:03:46 +0100 Stephan Bosch <stephan@rename-it.nl> (c4f8cf92) + + Omitted 'extern' in two declarations of global variables in header files, + causing compile failures on certain systems. + + +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/plugins/notify/ext-notify-common.h + +2010-01-25 18:42:30 +0100 Stephan Bosch <stephan@rename-it.nl> (600adae0) + + Added spamtest and virustest extensions to the default build. + + +M Makefile.am +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c +M src/lib-sieve/sieve-extensions.c + +2010-01-25 18:22:07 +0100 Stephan Bosch <stephan@rename-it.nl> (ee4e1271) + + Spamtest and virustest extensions: finished configuration. + + +M Makefile.am +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c +M tests/extensions/spamvirustest/spamtest.svtest +A tests/extensions/spamvirustest/spamtestplus.svtest +A tests/extensions/spamvirustest/virustest.svtest + +2010-01-25 10:02:36 +0100 Stephan Bosch <stephan@rename-it.nl> (47796d77) + + Enotify extension: removed location from action log messages. + + +M src/lib-sieve/plugins/enotify/cmd-notify.c + +2010-01-25 01:57:54 +0100 Stephan Bosch <stephan@rename-it.nl> (b08dc028) + + Fixed newly introduced compiler warning. + + +M src/lib-sieve/sieve-settings.c + +2010-01-24 22:01:07 +0100 Stephan Bosch <stephan@rename-it.nl> (160ac4c0) + + Added boolean settings parser. + + +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h + +2010-01-24 11:15:38 +0100 Stephan Bosch <stephan@rename-it.nl> (ba49af27) + + Testsuite: added a few more tests for the i;ascii-numeric comparator (patch + by Julian Cowley). + + +M tests/extensions/relational/comparators.svtest + +2010-01-23 00:37:21 +0100 Stephan Bosch <stephan@rename-it.nl> (766303db) + + Fixed bugs in parser recovery and added corresponding tests in the test + suite. + + +M Makefile.am +M src/lib-sieve/sieve-parser.c +A tests/compile/recover.svtest +A tests/compile/recover/commands-endblock.sieve +A tests/compile/recover/commands-semicolon.sieve +A tests/compile/recover/tests-endcomma.sieve + +2010-01-22 15:28:07 +0100 Stephan Bosch <stephan@rename-it.nl> (e93a5fee) + + Enotify extension: set default importance to normal as required. + + +M src/lib-sieve/plugins/enotify/cmd-notify.c +M tests/extensions/enotify/mailto.svtest + +2010-01-23 00:45:11 +0100 Stephan Bosch <stephan@rename-it.nl> (a0b5c2fc) + + Fixed '-' in man pages. + + +M doc/man/sieve-filter.1 +M doc/man/sieve-test.1 +M doc/man/sievec.1 +M doc/man/sieved.1 + +2010-01-19 16:32:48 +0100 Stephan Bosch <stephan@rename-it.nl> (f94b9f6a) + + Fixed small bug in the i;ascii-numeric comparator and added extensive + relational tests to the testsuite. + + +M Makefile.am +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +A tests/extensions/relational/comparators.svtest + +2010-01-19 10:12:00 +0100 Stephan Bosch <stephan@rename-it.nl> (a1117a11) + + Fixed spelling mistake in error messages. + + +M src/lib-sieve/sieve-message.c + +2010-01-19 10:11:42 +0100 Stephan Bosch <stephan@rename-it.nl> (b55dc255) + + Envelope paths with only a mailbox part are now allowed. + + +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address.c +M tests/extensions/envelope.svtest + +2010-01-18 01:35:16 +0100 Stephan Bosch <stephan@rename-it.nl> (21e7f1e0) + + Added TODO list item. + + +M TODO + +2010-01-18 00:51:46 +0100 Stephan Bosch <stephan@rename-it.nl> (7d12af2a) + + Fixed small bug in plugin support. + + +M src/lib-sieve/sieve-plugins.c + +2010-01-15 22:56:52 +0100 Stephan Bosch <stephan@rename-it.nl> (11338868) + + Slightly improved error messages during binary save. + + +M src/lib-sieve/sieve-binary.c + +2010-01-15 18:36:43 +0100 Stephan Bosch <stephan@rename-it.nl> (b6f0a3a1) + + Error handling: now only the topmost parent error handler will copy to the + master log. + + +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c + +2010-01-15 16:58:53 +0100 Stephan Bosch <stephan@rename-it.nl> (ce498a00) + + Fixed compile problem in previous change. + + +M src/lib-sieve/sieve-error.c + +2010-01-15 16:46:45 +0100 Stephan Bosch <stephan@rename-it.nl> (2b9f718c) + + Made child error handlers inherit master_log status from parent. + + +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c + +2010-01-14 10:21:34 +0100 Stephan Bosch <stephan@rename-it.nl> (37aab05f) + + Fixed bug in the logging of action results. The new varexpand error handler + was not properly tested. + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-result.c + +2010-01-13 21:07:26 +0100 Stephan Bosch <stephan@rename-it.nl> (d369700c) + + Merged Sieve and ManageSieve for Dovecot v2.0 into one Pigeonhole package. + + +M .hgignore +M AUTHORS +M INSTALL +M Makefile.am +M NEWS +M README +M TODO +M configure.in +M doc/example-config/conf.d/Makefile.am +A doc/example-config/conf.d/managesieve.conf +M doc/man/sieve-filter.1 +M doc/man/sieve-test.1 +M doc/man/sievec.1 +M doc/man/sieved.1 +A doc/rfc/draft-ietf-sieve-managesieve-09.txt +D dsieve-config.h.in +A pigeonhole-config.h.in +M src/Makefile.am +A src/lib-managesieve/Makefile.am +A src/lib-managesieve/managesieve-parser.c +A src/lib-managesieve/managesieve-parser.h +A src/lib-managesieve/managesieve-quote.c +A src/lib-managesieve/managesieve-quote.h +M src/lib-sieve-tool/Makefile.am +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-plugins.c +A src/lib-sievestorage/Makefile.am +A src/lib-sievestorage/sieve-storage-error.h +A src/lib-sievestorage/sieve-storage-list.c +A src/lib-sievestorage/sieve-storage-list.h +A src/lib-sievestorage/sieve-storage-private.h +A src/lib-sievestorage/sieve-storage-quota.c +A src/lib-sievestorage/sieve-storage-quota.h +A src/lib-sievestorage/sieve-storage-save.c +A src/lib-sievestorage/sieve-storage-save.h +A src/lib-sievestorage/sieve-storage-script.c +A src/lib-sievestorage/sieve-storage-script.h +A src/lib-sievestorage/sieve-storage.c +A src/lib-sievestorage/sieve-storage.h +A src/managesieve-login/Makefile.am +A src/managesieve-login/client-authenticate.c +A src/managesieve-login/client-authenticate.h +A src/managesieve-login/client.c +A src/managesieve-login/client.h +A src/managesieve-login/managesieve-login-settings.c +A src/managesieve-login/managesieve-login-settings.h +A src/managesieve-login/managesieve-proxy.c +A src/managesieve-login/managesieve-proxy.h +A src/managesieve/Makefile.am +A src/managesieve/cmd-capability.c +A src/managesieve/cmd-deletescript.c +A src/managesieve/cmd-getscript.c +A src/managesieve/cmd-havespace.c +A src/managesieve/cmd-listscripts.c +A src/managesieve/cmd-logout.c +A src/managesieve/cmd-noop.c +A src/managesieve/cmd-putscript.c +A src/managesieve/cmd-renamescript.c +A src/managesieve/cmd-setactive.c +A src/managesieve/main.c +A src/managesieve/managesieve-client.c +A src/managesieve/managesieve-client.h +A src/managesieve/managesieve-commands.c +A src/managesieve/managesieve-commands.h +A src/managesieve/managesieve-common.h +A src/managesieve/managesieve-quota.c +A src/managesieve/managesieve-quota.h +A src/managesieve/managesieve-settings.c +A src/managesieve/managesieve-settings.h +M src/sieve-tools/Makefile.am +M src/testsuite/Makefile.am +M tests/extensions/environment/basic.svtest + +2010-01-13 09:16:04 +0100 Stephan Bosch <stephan@rename-it.nl> (0649733b) + + Fixed off-by-one bug in extension reloading. + + +M src/lib-sieve/sieve-extensions.c + +2010-01-13 08:57:10 +0100 Stephan Bosch <stephan@rename-it.nl> (d08c5d27) + + Improved extension unloading. + + +M src/lib-sieve/sieve-extensions.c + +2010-01-13 01:16:20 +0100 Stephan Bosch <stephan@rename-it.nl> (81942d5b) + + Fixed segfault bug caused by previous change, occuring when a plugin is + unloaded. + + +M src/lib-sieve/sieve-extensions.c + +2010-01-13 09:02:53 +0100 Stephan Bosch <stephan@rename-it.nl> (ba8fb890) + + Improved various aspects of the plugin-related extension API. + + +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-plugins.c +M src/lib-sieve/sieve.c + +2010-01-12 16:55:12 +0100 Stephan Bosch <stephan@rename-it.nl> (fd7746d6) + + Forgot to add dsieve-config.h to installed headers. + + +M Makefile.am + +2010-01-12 11:47:18 +0100 Stephan Bosch <stephan@rename-it.nl> (43e1519c) + + Variables extension: removed public dependency on ext-variables-limits.h. + + +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-limits.h +M src/lib-sieve/plugins/variables/ext-variables-name.c +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2010-01-11 19:03:37 +0100 Stephan Bosch <stephan@rename-it.nl> (e756f4c5) + + Fixed a few memleaks caused by previous changes in error handling. + + +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/sieve-result.c + +2010-01-10 03:00:42 +0100 Stephan Bosch <stephan@rename-it.nl> (0ed8aab4) + + Enotify extension: mailto method: fixed small uri validation glitch. + + +M src/lib-sieve/plugins/enotify/mailto/uri-mailto.c + +2010-01-10 02:39:19 +0100 Stephan Bosch <stephan@rename-it.nl> (3c42f48c) + + Enotify extension: cleaned up notify method API (part is in previous + change). + + +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h + +2010-01-12 00:23:08 +0100 Stephan Bosch <stephan@rename-it.nl> (d2ef2e6d) + + Reworked error handler implementation and cleaned up enotify extension + implementation. + + +M configure.in +M src/lib-sieve/plugins/enotify/Makefile.am +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +A src/lib-sieve/plugins/enotify/mailto/Makefile.am +A src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +A src/lib-sieve/plugins/enotify/mailto/uri-mailto.c +A src/lib-sieve/plugins/enotify/mailto/uri-mailto.h +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2010-01-08 12:18:20 +0100 Stephan Bosch <stephan@rename-it.nl> (f32da22a) + + Vacation extension: subject is now only MIME-encoded when it contains 8bit + characters. + + +M Makefile.am +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M tests/extensions/vacation/utf-8.svtest + +2010-01-08 01:27:00 +0100 Stephan Bosch <stephan@rename-it.nl> (fa3e26d0) + + Fixed compile problems on systems with older autotools installed. + + +M configure.in + +2010-01-07 23:57:16 +0100 Stephan Bosch <stephan@rename-it.nl> (ea83a088) + + Sieve-filter: made tool compile with Dovecot v2.0 (not working). + + +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c + +2010-01-07 23:04:23 +0100 Stephan Bosch <stephan@rename-it.nl> (0b46c130) + + Plugin support: added -P parameter to all sieve tools and enabled dict + support. + + +M configure.in +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/plugins/lda-sieve/Makefile.am +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/sieve-tools/sieved.c +M src/testsuite/testsuite.c + +2010-01-07 22:26:29 +0100 Stephan Bosch <stephan@rename-it.nl> (0127ed29) + + Plugin support: fixed unloading problem. + + +M src/lib-sieve/sieve.c + +2010-01-07 02:56:11 +0100 Stephan Bosch <stephan@rename-it.nl> (f7a3ced7) + + Variables extension: finished namespaces support. + + +M src/lib-sieve/plugins/variables/ext-variables-namespaces.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2010-01-03 23:25:25 +0100 Stephan Bosch <stephan@rename-it.nl> (d1c9ee43) + + Spamtest extension: added yesno-type header matching tests to the testsuite. + + +M tests/extensions/spamvirustest/spamtest.svtest + +2010-01-03 23:22:25 +0100 Stephan Bosch <stephan@rename-it.nl> (4583ec5f) + + Spamtest extension: fixed small bug in yesno-type spam header matching. + + +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c + +2010-01-03 23:08:21 +0100 Stephan Bosch <stephan@rename-it.nl> (bbf50be8) + + Testsuite: fixed panic occuring when unsetting an unknown configuration + setting. + + +M src/testsuite/testsuite-settings.c + +2010-01-03 22:29:04 +0100 Stephan Bosch <stephan@rename-it.nl> (0cb3a96d) + + Spamtest extension: added tests for strlen values to the testsuite. + + +M tests/extensions/spamvirustest/spamtest.svtest + +2010-01-03 22:28:33 +0100 Stephan Bosch <stephan@rename-it.nl> (d0f9c920) + + Spamtest extension: fixed bugs in extension unloading and in strlen value + extraction. + + +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c + +2010-01-03 22:24:33 +0100 Stephan Bosch <stephan@rename-it.nl> (ae507162) + + Testsuite: added support for removed settings. + + +M src/testsuite/cmd-test-config.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-settings.c +M src/testsuite/testsuite-settings.h + +2010-01-03 21:41:45 +0100 Stephan Bosch <stephan@rename-it.nl> (7b36cdba) + + Spamtest extension: added various value tests to the testsuite. + + +M tests/extensions/spamvirustest/spamtest.svtest + +2010-01-03 21:41:21 +0100 Stephan Bosch <stephan@rename-it.nl> (446ee0cb) + + Spamtest extension: fixed result when over the maximum score. + + +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c + +2010-01-03 19:26:23 +0100 Stephan Bosch <stephan@rename-it.nl> (46c23635) + + Spamtest extension: further developed configuration loading and testing. + + +M Makefile.am +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h +A tests/extensions/spamvirustest/spamtest.svtest + +2010-01-03 17:09:01 +0100 Stephan Bosch <stephan@rename-it.nl> (a9078e5b) + + Testsuite: enabled warnings in testsuite error handler. + + +M src/testsuite/testsuite-log.c + +2010-01-07 22:22:08 +0100 Stephan Bosch <stephan@rename-it.nl> (f6930c08) + + Testsuite: added command line parameter for copying errors to stderr. + + +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-log.h +M src/testsuite/testsuite.c + +2010-01-03 13:33:45 +0100 Stephan Bosch <stephan@rename-it.nl> (648cb538) + + Testsuite: added support for changing and testing an extension's + configuration. + + +M Makefile.am +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/testsuite/Makefile.am +A src/testsuite/cmd-test-config.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-common.h +A tests/extensions/subaddress/config.svtest + +2010-01-02 19:06:03 +0100 Stephan Bosch <stephan@rename-it.nl> (13bca4d5) + + Adjusted tag parameter validation API. + + +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/testsuite/cmd-test-message.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-result.c + +2010-01-02 16:16:24 +0100 Stephan Bosch <stephan@rename-it.nl> (14a3169a) + + Restructured handling of Dovecot includes in makefiles. + + +M configure.in +M src/lib-sieve-tool/Makefile.am +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/body/Makefile.am +M src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.am +M src/lib-sieve/plugins/copy/Makefile.am +M src/lib-sieve/plugins/date/Makefile.am +M src/lib-sieve/plugins/enotify/Makefile.am +M src/lib-sieve/plugins/environment/Makefile.am +M src/lib-sieve/plugins/imap4flags/Makefile.am +M src/lib-sieve/plugins/include/Makefile.am +M src/lib-sieve/plugins/mailbox/Makefile.am +M src/lib-sieve/plugins/notify/Makefile.am +M src/lib-sieve/plugins/regex/Makefile.am +M src/lib-sieve/plugins/relational/Makefile.am +M src/lib-sieve/plugins/spamvirustest/Makefile.am +M src/lib-sieve/plugins/subaddress/Makefile.am +M src/lib-sieve/plugins/vacation/Makefile.am +M src/lib-sieve/plugins/variables/Makefile.am +M src/plugins/lda-sieve/Makefile.am +M src/sieve-tools/Makefile.am +M src/sieve-tools/debug/Makefile.am +M src/testsuite/Makefile.am + +2010-01-02 13:56:11 +0100 Stephan Bosch <stephan@rename-it.nl> (2e1a06c2) + + Forgot to update two makefiles. + + +M src/lib-sieve/plugins/imap4flags/Makefile.am +M src/sieve-tools/debug/Makefile.am + +2010-01-02 13:50:52 +0100 Stephan Bosch <stephan@rename-it.nl> (d3c2735b) + + Set default dovecot directory to ../dovecot-2.0 + + +M configure.in + +2010-01-02 13:39:38 +0100 Stephan Bosch <stephan@rename-it.nl> (f07845fc) + + Added support for fully compiling against installed Dovecot libraries. + + +M Makefile.am +M configure.in +M src/Makefile.am +M src/lib-sieve-tool/Makefile.am +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/body/Makefile.am +M src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.am +M src/lib-sieve/plugins/copy/Makefile.am +M src/lib-sieve/plugins/date/Makefile.am +M src/lib-sieve/plugins/enotify/Makefile.am +M src/lib-sieve/plugins/environment/Makefile.am +M src/lib-sieve/plugins/include/Makefile.am +M src/lib-sieve/plugins/mailbox/Makefile.am +M src/lib-sieve/plugins/notify/Makefile.am +M src/lib-sieve/plugins/regex/Makefile.am +M src/lib-sieve/plugins/relational/Makefile.am +M src/lib-sieve/plugins/spamvirustest/Makefile.am +M src/lib-sieve/plugins/subaddress/Makefile.am +M src/lib-sieve/plugins/vacation/Makefile.am +M src/lib-sieve/plugins/variables/Makefile.am +M src/plugins/lda-sieve/Makefile.am +M src/sieve-tools/Makefile.am +M src/testsuite/Makefile.am + +2010-01-02 02:56:45 +0100 Stephan Bosch <stephan@rename-it.nl> (5309cd46) + + Updated all copyright messages to the new year. + + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/mail-raw.h +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/cmp-i-ascii-casemap.c +M src/lib-sieve/cmp-i-octet.c +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/ext-date-common.h +M src/lib-sieve/plugins/date/ext-date.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify-limits.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/environment/ext-environment-common.h +M src/lib-sieve/plugins/environment/ext-environment.c +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-limits.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/mailbox/ext-mailbox-common.h +M src/lib-sieve/plugins/mailbox/ext-mailbox.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.h +M src/lib-sieve/plugins/notify/ext-notify-limits.h +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/plugins/regex/ext-regex-common.c +M src/lib-sieve/plugins/regex/ext-regex-common.h +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h +M src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c +M src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.h +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables-dump.h +M src/lib-sieve/plugins/variables/ext-variables-limits.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-name.c +M src/lib-sieve/plugins/variables/ext-variables-name.h +M src/lib-sieve/plugins/variables/ext-variables-namespaces.c +M src/lib-sieve/plugins/variables/ext-variables-namespaces.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/rfc2822.c +M src/lib-sieve/rfc2822.h +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-objects.c +M src/lib-sieve/sieve-objects.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-plugins.c +M src/lib-sieve/sieve-plugins.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve-smtp.c +M src/lib-sieve/sieve-smtp.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c +M src/lib-sieve/tst-truefalse.c +M src/plugins/lda-sieve/lda-sieve-log.c +M src/plugins/lda-sieve/lda-sieve-log.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/plugins/lda-sieve/lda-sieve-plugin.h +M src/sieve-tools/debug/cmd-debug-print.c +M src/sieve-tools/debug/ext-debug-common.h +M src/sieve-tools/debug/ext-debug.c +M src/sieve-tools/debug/sieve-ext-debug.h +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/sieve-tools/sieved.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-result-print.c +M src/testsuite/cmd-test-result-reset.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-arguments.c +M src/testsuite/testsuite-arguments.h +M src/testsuite/testsuite-binary.c +M src/testsuite/testsuite-binary.h +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-log.h +M src/testsuite/testsuite-mailstore.c +M src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-result.h +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-script.h +M src/testsuite/testsuite-settings.c +M src/testsuite/testsuite-settings.h +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite-substitutions.c +M src/testsuite/testsuite-substitutions.h +M src/testsuite/testsuite.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-result.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c + +2010-01-01 14:22:13 +0100 Stephan Bosch <stephan@rename-it.nl> (75647f79) + + Plugin support: removed ability to have duplicate plugins in different + directories. + + +M src/lib-sieve/sieve-plugins.c + +2009-12-31 20:02:40 +0100 Stephan Bosch <stephan@rename-it.nl> (04ac8bb0) + + Fixed yet another small textual error in the README file. + + +M README + +2009-12-31 19:57:09 +0100 Stephan Bosch <stephan@rename-it.nl> (6cc56d70) + + Fixed small textual error in the README file. + + +M README + +2009-12-31 19:47:01 +0100 Stephan Bosch <stephan@rename-it.nl> (02ea6992) + + Further developed support for Sieve engine plugins. + + +M src/lib-sieve/sieve-plugins.c + +2009-12-31 18:10:46 +0100 Stephan Bosch <stephan@rename-it.nl> (65920901) + + Further developed support for Sieve engine plugins. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/sieve-common.h +A src/lib-sieve/sieve-plugins.c +A src/lib-sieve/sieve-plugins.h +M src/lib-sieve/sieve.c + +2009-12-31 18:42:36 +0100 Stephan Bosch <stephan@rename-it.nl> (8c92c80e) + + dded preliminary support for plugins. + + +M configure.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/sieve.c + +2009-12-31 04:40:09 +0100 Stephan Bosch <stephan@rename-it.nl> (31e40815) + + Enotify extension: adjusted notify method registration API. + + +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h + +2009-12-30 04:44:27 +0100 Stephan Bosch <stephan@rename-it.nl> (b05726fc) + + Imap4flags extension: added tests to verify removeflag behavior. + + +M tests/extensions/imap4flags/basic.svtest + +2009-12-30 04:43:02 +0100 Stephan Bosch <stephan@rename-it.nl> (dbcfa2e7) + + Imap4flags extension: fixed bug in removeflag: removing a single flag failed + due to off-by-one error. + + +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c + +2009-12-30 04:40:04 +0100 Stephan Bosch <stephan@rename-it.nl> (59cf3adf) + + Imap4flags extension: added tests for flag string management. + + +M Makefile.am +A tests/extensions/imap4flags/flagstring.svtest + +2009-12-31 18:16:03 +0100 Stephan Bosch <stephan@rename-it.nl> (cc4f65c4) + + Updated README file. + + +M README + +2009-12-30 00:16:30 +0100 Stephan Bosch <stephan@rename-it.nl> (2a541e80) + + Built basic implementation of the spamtest, spamtestplus and virustest + extensions (unfinished). + + +M TODO +M configure.in +A doc/rfc/spamvirustest.rfc5235.txt +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/spamvirustest/Makefile.am +A src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +A src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h +A src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c +A src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h + +2009-12-29 23:49:27 +0100 Stephan Bosch <stephan@rename-it.nl> (e9e6a82c) + + Improved EACCES error messages for stat() and lstat() syscalls. + + +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-12-29 23:24:15 +0100 Stephan Bosch <stephan@rename-it.nl> (9c8a25f0) + + Renamed sieve_callbacks to sieve_environment and restructured settings API. + + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/testsuite/testsuite.c + +2009-12-29 23:14:28 +0100 Stephan Bosch <stephan@rename-it.nl> (641e1c06) + + Deprecated notify extension: implemented denotify command. + + +M Makefile.am +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/ext-notify-common.h +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +A tests/deprecated/notify/denotify.svtest + +2009-12-26 20:39:53 +0100 Stephan Bosch <stephan@rename-it.nl> (99b455a0) + + Moved size limit enforcement to script compilation (lexer) in stead of + during opening the stream. + + +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h + +2009-12-25 15:30:51 +0100 Stephan Bosch <stephan@rename-it.nl> (23147756) + + LDA Sieve plugin: log messages now include the lda session ID; forgot to set + master error handler. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-12-25 14:38:27 +0100 Stephan Bosch <stephan@rename-it.nl> (cf5516e0) + + Previous commit was broken. + + +M src/plugins/lda-sieve/Makefile.am +M src/plugins/lda-sieve/lda-sieve-log.c + +2009-12-25 14:11:38 +0100 Stephan Bosch <stephan@rename-it.nl> (e72e053d) + + Added LDA session ID to log messages produced by the Sieve plugin. + + +A src/plugins/lda-sieve/lda-sieve-log.c +A src/plugins/lda-sieve/lda-sieve-log.h +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-12-25 10:38:30 +0100 Stephan Bosch <stephan@rename-it.nl> (4f877644) + + Fixed compiler warning. + + +M src/lib-sieve/sieve-script.c + +2009-12-23 15:12:37 +0100 Stephan Bosch <stephan@rename-it.nl> (76dfa64d) + + Include extension: global command may now appear anywhere in a script. + + +M TODO +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/ext-include-variables.c +M tests/extensions/include/errors.svtest +M tests/extensions/include/errors/variables.sieve +M tests/extensions/include/variables.svtest + +2009-12-23 14:17:53 +0100 Stephan Bosch <stephan@rename-it.nl> (ca5912f2) + + Vacation extension: fixed typo in runtime log message (patch by Julian + Cowley). + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2009-12-23 14:12:59 +0100 Stephan Bosch <stephan@rename-it.nl> (d0aefe8a) + + Testsuite: added tests for new features of the include extension. + + +M tests/extensions/include/errors.svtest +A tests/extensions/include/errors/global-namespace.sieve +A tests/extensions/include/errors/scriptname.sieve +M tests/extensions/include/included/variables-included1.sieve +M tests/extensions/include/included/variables-included2.sieve + +2009-12-23 12:28:03 +0100 Stephan Bosch <stephan@rename-it.nl> (e86e039c) + + Updated specification of include extension to latest version. + + +R068 doc/rfc/draft-ietf-sieve-include-01.txt doc/rfc/draft-ietf-sieve-include-03.txt + +2009-12-23 12:27:38 +0100 Stephan Bosch <stephan@rename-it.nl> (5523de35) + + Include extension: implemented global variables namespace. + + +M TODO +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/ext-include.c + +2009-12-23 12:26:04 +0100 Stephan Bosch <stephan@rename-it.nl> (1670193a) + + Variables extension: added basic namespace support. + + +M TODO +M src/lib-sieve/plugins/variables/Makefile.am +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-name.c +M src/lib-sieve/plugins/variables/ext-variables-name.h +A src/lib-sieve/plugins/variables/ext-variables-namespaces.c +A src/lib-sieve/plugins/variables/ext-variables-namespaces.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2009-12-22 11:21:34 +0100 Stephan Bosch <stephan@rename-it.nl> (4ebf931a) + + Variables extension: improved source code comment. + + +M src/lib-sieve/plugins/variables/ext-variables-name.c +M src/lib-sieve/plugins/variables/ext-variables-name.h + +2009-12-24 11:03:14 +0100 Stephan Bosch <stephan@rename-it.nl> (7726ed36) + + Added configurable script size limit. + + +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h + +2009-12-20 10:25:08 +0100 Stephan Bosch <stephan@rename-it.nl> (12a317ad) + + Implemented script name checking using the requirements specified in the + ManageSieve draft. + + +M TODO +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h + +2009-12-17 11:17:18 +0100 Stephan Bosch <stephan@rename-it.nl> (d61ff631) + + Another Dovecot lib-storage API change (patch by Timo Sirainen). + + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/sieve-actions.c +M src/sieve-tools/sieve-filter.c +M src/testsuite/testsuite-mailstore.c + +2009-12-13 21:16:10 +0100 Stephan Bosch <stephan@rename-it.nl> (1d3a73aa) + + Adjusted to changes in Dovecot buffer API (patch by Pascal Volk). + + +M src/lib-sieve/sieve-binary.c + +2009-11-19 21:22:56 +0100 Stephan Bosch <stephan@rename-it.nl> (545ba98e) + + Made homedir aquisition a callback. + + +M TODO +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve-types.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/testsuite/testsuite.c + +2009-11-19 18:03:19 +0100 Stephan Bosch <stephan@rename-it.nl> (924f83b7) + + A warning is now produced when parsing invalid integer settings. + + +M src/lib-sieve/sieve-settings.c + +2009-11-19 18:13:41 +0100 Stephan Bosch <stephan@rename-it.nl> (a2ae237a) + + Made limits on the number of redirects and the number of actions in general + configurable. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/sieve-common.h +D src/lib-sieve/sieve-limits.c +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-result.c +A src/lib-sieve/sieve-settings.c +A src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve.c + +2009-11-18 23:27:12 +0100 Stephan Bosch <stephan@rename-it.nl> (90d420e1) + + Fixed homedir expansion bug in the include extension. + + +M src/lib-sieve/plugins/include/ext-include-common.c + +2009-11-17 14:46:04 +0100 Stephan Bosch <stephan@rename-it.nl> (191c465d) + + Made sure that scripts are only recompiled when the script file - or the + symlink pointing to it - is strictly newer. + + +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h + +2009-11-16 00:34:13 +0100 Stephan Bosch <stephan@rename-it.nl> (45a3462d) + + Fixed comment errors in date extension. + + +M src/lib-sieve/plugins/date/tst-date.c + +2009-11-11 18:51:13 +0100 Stephan Bosch <stephan@rename-it.nl> (fd46aec5) + + LDA Sieve plugin: small cosmetic changes in the sources. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-11-11 17:38:29 +0100 Stephan Bosch <stephan@rename-it.nl> (66d90e53) + + Subaddress extension: now uses Dovecot's recipient_delimiter setting in + stead of its own sieve_subaddress_sep setting. + + +M src/lib-sieve/plugins/subaddress/ext-subaddress.c + +2009-11-08 23:35:48 +0100 Stephan Bosch <stephan@rename-it.nl> (aeca3e5b) + + (Hopefully) fixed home expansion in LDA Sieve plugin. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-11-08 23:35:16 +0100 Stephan Bosch <stephan@rename-it.nl> (ea1e83d8) + + Fixed dovecot doc dir. + + +M configure.in + +2009-11-08 22:43:01 +0100 Stephan Bosch <stephan@rename-it.nl> (35bc88d6) + + Forgot to add sieve_debug after porting logging change from v1.2. + + +M src/lib-sieve/sieve-error.c + +2009-11-08 21:43:28 +0100 Stephan Bosch <stephan@rename-it.nl> (b49c5731) + + Fixed install location of example config. + + +M configure.in +M doc/example-config/conf.d/Makefile.am + +2009-11-08 21:23:55 +0100 Stephan Bosch <stephan@rename-it.nl> (1e1b251b) + + Made LDA Sieve plugin recognize the deliver_log_format setting. + + +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-types.h +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-11-08 21:03:30 +0100 Stephan Bosch <stephan@rename-it.nl> (fb5b443c) + + Added i_debug support. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-11-08 19:50:46 +0100 Stephan Bosch <stephan@rename-it.nl> (3535f14e) + + Fixed a bug in configure.in. + + +M configure.in + +2009-11-08 18:49:37 +0100 Stephan Bosch <stephan@rename-it.nl> (67957b91) + + Corrected install directories for headers and libraries. + + +M configure.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/enotify/Makefile.am +M src/lib-sieve/plugins/environment/Makefile.am +M src/lib-sieve/plugins/variables/Makefile.am +M src/sieve-tools/Makefile.am + +2009-11-08 16:02:59 +0100 Stephan Bosch <stephan@rename-it.nl> (cf4cfd97) + + Made Sieve library a shared library. + + +M configure.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/enotify/Makefile.am +M src/lib-sieve/plugins/environment/Makefile.am +M src/lib-sieve/plugins/variables/Makefile.am +M src/plugins/lda-sieve/Makefile.am +M src/sieve-tools/Makefile.am +M src/testsuite/Makefile.am + +2009-10-31 22:36:41 +0100 Stephan Bosch <stephan@rename-it.nl> (4ef0c80a) + + Fixed bug in result printing (untroduced in large rework). + + +M src/lib-sieve/sieve-result.c + +2009-10-31 22:36:14 +0100 Stephan Bosch <stephan@rename-it.nl> (c72834e9) + + Fixed bug in the extensions configuration (untroduced in large rework). + + +M src/lib-sieve/sieve-extensions.c + +2009-11-05 16:42:28 +0100 Stephan Bosch <stephan@rename-it.nl> (a9a234f3) + + Fixed logging of mailbox names. It logged the converted mUTF7 version in + stead of the original UTF8. + + +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h + +2009-10-31 01:01:58 +0100 Stephan Bosch <stephan@rename-it.nl> (1b257ba4) + + Fixed minor memory leak in the multiscript support. + + +M src/lib-sieve/sieve.c + +2009-11-05 16:13:37 +0100 Stephan Bosch <stephan@rename-it.nl> (7d0e3eb1) + + Adjusted to changes in Dovecot v2.0's LDA duplicate checking API. + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-types.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-test.c + +2009-11-05 15:47:24 +0100 Stephan Bosch <stephan@rename-it.nl> (852f7bf1) + + Fixed v2.0-specific settings-related bugs remaining in the port from v1.2. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/testsuite/Makefile.am +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-settings.c +M src/testsuite/testsuite-settings.h +M src/testsuite/testsuite.c + +2009-11-05 15:46:48 +0100 Stephan Bosch <stephan@rename-it.nl> (e455b1d6) + + Adjusted to API changes in Dovecot v2.0. + + +M src/lib-sieve-tool/mail-raw.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-mailstore.c + +2009-11-05 15:29:42 +0100 Stephan Bosch <stephan@rename-it.nl> (3368ba14) + + Merged concurrent changes. + + +2009-11-05 15:29:20 +0100 Stephan Bosch <stephan@rename-it.nl> (0bbc0790) + + Properly implemented settings retrieval API. + + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/sieve-common.h +D src/lib-sieve/sieve-settings.c +D src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sievec.c +M src/testsuite/Makefile.am +M src/testsuite/testsuite.c + +2009-11-05 15:28:26 +0100 Stephan Bosch <stephan@rename-it.nl> (e8d9d151) + + Fixed compiler warning in imap4flags extension. + + +M src/lib-sieve/plugins/imap4flags/tag-flags.c + +2009-11-02 01:01:08 +0100 Stephan Bosch <stephan@rename-it.nl> (65583101) + + Major rework of extension handling, making sure that no global state is + maintained. + + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/cmp-i-ascii-casemap.c +M src/lib-sieve/cmp-i-octet.c +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/Makefile.am +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/ext-date-common.h +M src/lib-sieve/plugins/date/ext-date.c +M src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/environment/ext-environment-common.h +M src/lib-sieve/plugins/environment/ext-environment.c +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/mailbox/ext-mailbox-common.h +M src/lib-sieve/plugins/mailbox/ext-mailbox.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.h +M src/lib-sieve/plugins/notify/ext-notify.c +M src/lib-sieve/plugins/regex/ext-regex-common.c +M src/lib-sieve/plugins/regex/ext-regex-common.h +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.h +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables-dump.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-objects.c +M src/lib-sieve/sieve-objects.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c +M src/lib-sieve/tst-truefalse.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/debug/cmd-debug-print.c +M src/sieve-tools/debug/ext-debug-common.h +M src/sieve-tools/debug/ext-debug.c +M src/sieve-tools/debug/sieve-ext-debug.h +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/sieve-tools/sieved.c +M src/testsuite/cmd-test-binary.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-mailbox.c +M src/testsuite/cmd-test-message.c +M src/testsuite/cmd-test-result-print.c +M src/testsuite/cmd-test-result-reset.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-arguments.c +M src/testsuite/testsuite-arguments.h +M src/testsuite/testsuite-binary.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-substitutions.c +M src/testsuite/testsuite-substitutions.h +M src/testsuite/testsuite.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-multiscript.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-result.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c +M tests/compile/errors/typos.sieve +M tests/extensions/environment/basic.svtest +M tests/extensions/imap4flags/multiscript.svtest + +2009-10-28 12:23:05 +0100 Stephan Bosch <stephan@rename-it.nl> (b3bb899f) + + Message headers produced from user-supplied data are now RFC2047-encoded if + necessary for outgoing messages. + + +M TODO +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/rfc2822.c +M src/lib-sieve/rfc2822.h +A tests/extensions/vacation/utf-8.svtest + +2009-10-23 00:17:34 +0200 Stephan Bosch <stephan@rename-it.nl> (6a2dbda5) + + Adjusted to changes in the Dovecot service API. + + +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite.c + +2009-10-22 23:12:04 +0200 Stephan Bosch <stephan@rename-it.nl> (7eba6db1) + + Set Dovecot version to v2.0 in configure.in. + + +M configure.in + +2009-10-22 23:11:25 +0200 Stephan Bosch <stephan@rename-it.nl> (212a4172) + + Added example configuration. + + +M Makefile.am +M configure.in +A doc/Makefile.am +A doc/example-config/Makefile.am +A doc/example-config/conf.d/Makefile.am +A doc/example-config/conf.d/sieve.conf +A doc/man/Makefile.am + +2009-10-21 22:39:31 +0200 Stephan Bosch <stephan@rename-it.nl> (5a7a227e) + + Moved Sieve plugin installation from modules/lda to modules. + + +M src/plugins/lda-sieve/Makefile.am + +2009-10-20 22:54:11 +0200 Stephan Bosch <stephan@rename-it.nl> (f2a167f7) + + Notify (deprecated): added support for the $text$ substitution. + + +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.h +M tests/deprecated/notify/mailto.svtest + +2009-10-20 20:25:49 +0200 Stephan Bosch <stephan@rename-it.nl> (58b43b15) + + Fixed indentation problems in obsolete notify extension. + + +M src/lib-sieve/plugins/notify/cmd-notify.c + +2009-10-21 12:52:53 +0200 Stephan Bosch <stephan@rename-it.nl> (f2d1d0a6) + + Adjusted to master service changes in the Dovecot API. + + +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite.c + +2009-10-21 11:52:52 +0200 Stephan Bosch <stephan@rename-it.nl> (8410ec51) + + Adjusted to changes in Dovecot Master Service API. + + +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite.c + +2009-10-19 11:58:11 +0200 Stephan Bosch <stephan@rename-it.nl> (a781e577) + + Finished new settings handling, including debugging support. + + +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/sieve-settings.c +M src/lib-sieve/sieve-settings.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/sieve-tools/sieved.c +M src/testsuite/Makefile.am +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-script.c +A src/testsuite/testsuite-settings.c +A src/testsuite/testsuite-settings.h +M src/testsuite/testsuite.c + +2009-10-18 23:22:51 +0200 Stephan Bosch <stephan@rename-it.nl> (273f6b4c) + + Implemented Sieve settings handling (debug not working yet). + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +A src/lib-sieve/sieve-settings.c +A src/lib-sieve/sieve-settings.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite.c + +2009-10-18 18:17:42 +0200 Stephan Bosch <stephan@rename-it.nl> (ec74124a) + + Cleaned up TODO file. + + +M TODO + +2009-10-18 16:44:23 +0200 Stephan Bosch <stephan@rename-it.nl> (58fb9103) + + Testsuite: added multiscript flag tests for the imap4flags extension. + + +M src/testsuite/cmd-test-message.c +M src/testsuite/testsuite-script.c +M tests/extensions/imap4flags/multiscript.svtest +A tests/extensions/imap4flags/multiscript/fileinto.sieve +A tests/extensions/imap4flags/multiscript/setflag.sieve + +2009-10-17 23:05:03 +0200 Stephan Bosch <stephan@rename-it.nl> (9cd8ef59) + + Test suite: added multiscript support and added some new tests with the new + feature. + + +M Makefile.am +M TODO +M src/testsuite/Makefile.am +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-script.h +A src/testsuite/tst-test-multiscript.c +A tests/extensions/imap4flags/multiscript.svtest +A tests/extensions/imap4flags/multiscript/group-spam.sieve +A tests/extensions/imap4flags/multiscript/sent-store.sieve +A tests/extensions/imap4flags/multiscript/spam.sieve + +2009-10-17 19:40:18 +0200 Stephan Bosch <stephan@rename-it.nl> (793f4f7a) + + Updated TODO. + + +M TODO + +2009-10-17 16:35:32 +0200 Stephan Bosch <stephan@rename-it.nl> (c2d28f3a) + + Updated TODO. + + +M TODO + +2009-10-17 16:15:22 +0200 Stephan Bosch <stephan@rename-it.nl> (851d9d64) + + Fixed race condition occuring when multiple instances are saving the same + binary (patch by Timo Sirainen). + + +M src/lib-sieve/sieve-binary.c + +2009-10-11 15:51:54 +0200 Stephan Bosch <stephan@rename-it.nl> (17f472f2) + + Test suite: added tests for not yet working body extension features. + + +M tests/extensions/body/content.svtest + +2009-10-11 15:51:52 +0200 Stephan Bosch <stephan@rename-it.nl> (cf2d54d5) + + Body extension: minor code cleanups. + + +M src/lib-sieve/plugins/body/ext-body-common.c + +2009-10-11 12:20:38 +0200 Stephan Bosch <stephan@rename-it.nl> (43ebae99) + + Body extension: fixed minor comment error. + + +M src/lib-sieve/plugins/body/ext-body-common.c + +2009-10-11 12:08:02 +0200 Stephan Bosch <stephan@rename-it.nl> (45d8d199) + + Test suite: restructured tests for body extension. + + +M tests/extensions/body/basic.svtest +M tests/extensions/body/content.svtest + +2009-10-11 12:07:45 +0200 Stephan Bosch <stephan@rename-it.nl> (9520455c) + + Body extension: made parsing of content-type header more robust. + + +M src/lib-sieve/plugins/body/ext-body-common.c + +2009-10-11 10:46:06 +0200 Stephan Bosch <stephan@rename-it.nl> (ecf0634c) + + Test suite: added tests for basic use of :content with body test. + + +M Makefile.am +A tests/extensions/body/content.svtest + +2009-10-10 11:16:08 +0200 Stephan Bosch <stephan@rename-it.nl> (08255724) + + Added TODO item. + + +M TODO + +2009-10-10 11:14:58 +0200 Stephan Bosch <stephan@rename-it.nl> (c4b07aac) + + Body extension: implemented proper handling of the :raw transform. + + +M Makefile.am +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/body/tst-body.c +M tests/extensions/body/basic.svtest +A tests/extensions/body/raw.svtest + +2009-10-04 23:18:16 +0200 Stephan Bosch <stephan@rename-it.nl> (7c77a9bd) + + Made compiler more lenient towars missing CRLF at the end of the script in a + hash comment. + + +M Makefile.am +M src/lib-sieve/sieve-lexer.c +A tests/compile/warnings.svtest +A tests/compile/warnings/eof.sieve + +2009-09-02 23:17:50 +0200 Stephan Bosch <stephan@rename-it.nl> (8d6882e2) + + Body extension: don't give SKIP_BODY_BLOCK flag to message parser, we want + the body! (patch by Timo Sirainen). + + +M src/lib-sieve/plugins/body/ext-body-common.c + +2009-09-02 23:38:57 +0200 Stephan Bosch <stephan@rename-it.nl> (726146c1) + + Added TODO item. + + +M TODO + +2009-09-02 23:10:59 +0200 Stephan Bosch <stephan@rename-it.nl> (53221b6d) + + Fixed handling of implicit side effects for multiscript execution. + + +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2009-09-02 21:57:48 +0200 Stephan Bosch <stephan@rename-it.nl> (c861ba46) + + Fixed bug in multiscript support; subsequent keep actions were not always + merged correctly. + + +M src/lib-sieve/sieve-result.c + +2009-09-02 20:48:53 +0200 Stephan Bosch <stephan@rename-it.nl> (646b649e) + + Fixed segfault bug in the sieve-test tool. + + +M src/sieve-tools/sieve-test.c + +2009-09-02 20:36:19 +0200 Stephan Bosch <stephan@rename-it.nl> (30b8858d) + + Fixed segfault bug triggered by merging side effects in duplicate actions. + + +M src/lib-sieve/sieve-result.c + +2009-10-13 20:34:41 +0200 Stephan Bosch <stephan@rename-it.nl> (9a91c518) + + Sieve plugin: don't try stat the user's personal script if it is not + specified (NULL). + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-10-13 20:32:25 +0200 Stephan Bosch <stephan@rename-it.nl> (8c91dc7d) + + Mailbox extension: mailboxexists source file had wrong name; it is a test + and not a command. + + +M src/lib-sieve/plugins/mailbox/Makefile.am +R100 src/lib-sieve/plugins/mailbox/cmd-mailboxexists.c src/lib-sieve/plugins/mailbox/tst-mailboxexists.c + +2009-08-21 16:30:49 +0200 Stephan Bosch <stephan@rename-it.nl> (33d248f6) + + Enotify: removed spurious extern declaration of notify_extension. + + +M src/lib-sieve/plugins/enotify/ext-enotify-common.h + +2009-08-21 16:24:07 +0200 Stephan Bosch <stephan@rename-it.nl> (34076558) + + Notify (deprecated): removed spurious source file. + + +D src/lib-sieve/plugins/notify/ext-enotify.c + +2009-08-21 01:29:32 +0200 Stephan Bosch <stephan@rename-it.nl> (11e752a0) + + Fixed compile warnings in test suite. + + +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-script.c + +2009-08-16 01:34:37 +0200 Stephan Bosch <stephan@rename-it.nl> (495c8fe7) + + Updated TODO. + + +M TODO + +2009-08-16 01:34:09 +0200 Stephan Bosch <stephan@rename-it.nl> (ebefaf9f) + + Testsuite: added action execution test for the include extension with stored + binaries. + + +M Makefile.am +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite.c +A tests/extensions/include/execute.svtest +A tests/extensions/include/execute/actions-fileinto.sieve +A tests/extensions/include/execute/included/actions-fileinto1.sieve +A tests/extensions/include/execute/included/actions-fileinto2.sieve +A tests/extensions/include/execute/included/actions-fileinto3.sieve + +2009-08-16 01:33:32 +0200 Stephan Bosch <stephan@rename-it.nl> (5a6f9c5b) + + Made sure script can be compared to NULL. + + +M src/lib-sieve/sieve-script.c + +2009-08-16 00:59:56 +0200 Stephan Bosch <stephan@rename-it.nl> (5e20f16e) + + Fixed bug in error reporting when binary-related script object is not set. + + +M src/lib-sieve/sieve-error.c + +2009-08-16 01:00:41 +0200 Stephan Bosch <stephan@rename-it.nl> (21697375) + + Testsuite: added support for testing binaries stored on disk. + + +M Makefile.am +M src/testsuite/Makefile.am +A src/testsuite/cmd-test-binary.c +M src/testsuite/ext-testsuite.c +A src/testsuite/testsuite-binary.c +A src/testsuite/testsuite-binary.h +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-script.h +R056 tests/compile/examples.svtest tests/execute/examples.svtest + +2009-08-15 19:55:58 +0200 Stephan Bosch <stephan@rename-it.nl> (bf2b918d) + + Updated TODO list. + + +M TODO + +2009-10-13 20:22:40 +0200 Stephan Bosch <stephan@rename-it.nl> (a60edb07) + + Updated documentation. + + +M README + +2009-08-15 19:54:56 +0200 Stephan Bosch <stephan@rename-it.nl> (76be3c64) + + Testsuite: added tests for the new date extension. + + +M Makefile.am +A tests/extensions/date/basic.svtest +A tests/extensions/date/date-parts.svtest +A tests/extensions/date/zones.svtest + +2009-08-15 19:54:34 +0200 Stephan Bosch <stephan@rename-it.nl> (2cbfffad) + + Date extension: now included in default compile. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +M src/lib-sieve/plugins/date/ext-date.c +M src/lib-sieve/sieve-extensions.c + +2009-08-15 19:36:02 +0200 Stephan Bosch <stephan@rename-it.nl> (4aec8d11) + + Date extension: accidentally committed debug printf. + + +M src/lib-sieve/plugins/date/tst-date.c + +2009-08-15 19:30:33 +0200 Stephan Bosch <stephan@rename-it.nl> (afd82d40) + + Date extension: fixed problems in time zone handling. + + +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/tst-date.c + +2009-08-15 19:29:39 +0200 Stephan Bosch <stephan@rename-it.nl> (eee29780) + + Testsuite: added some debug code.\n + + +M src/testsuite/testsuite-message.c + +2009-08-15 16:55:29 +0200 Stephan Bosch <stephan@rename-it.nl> (bbe06f29) + + Date extension: fixed bug in julian date calculation. + + +M src/lib-sieve/plugins/date/ext-date-common.c + +2009-08-15 16:40:28 +0200 Stephan Bosch <stephan@rename-it.nl> (b3b6c0e4) + + Date extension: fixed a few bugs related to date part extraction. + + +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/tst-date.c + +2009-08-15 14:43:28 +0200 Stephan Bosch <stephan@rename-it.nl> (418bd097) + + Date extension: fixed errorhandling of gmtime() call. + + +M src/lib-sieve/plugins/date/tst-date.c + +2009-08-15 14:34:21 +0200 Stephan Bosch <stephan@rename-it.nl> (2a84d7ca) + + Date extension: completed implementation. + + +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/tst-date.c + +2009-08-15 14:13:03 +0200 Stephan Bosch <stephan@rename-it.nl> (d88c5f03) + + Date extension: all simple integer date parts are fixed-length strings. + + +M src/lib-sieve/plugins/date/ext-date-common.c + +2009-08-15 14:09:23 +0200 Stephan Bosch <stephan@rename-it.nl> (1f89a586) + + Date extension: implemented time zone handling. + + +M src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/ext-date-common.h +M src/lib-sieve/plugins/date/tst-date.c + +2009-08-15 13:37:24 +0200 Stephan Bosch <stephan@rename-it.nl> (b6d41c88) + + Date extension: implemented iso8601 date part. + + +M src/lib-sieve/plugins/date/ext-date-common.c + +2009-08-15 13:17:59 +0200 Stephan Bosch <stephan@rename-it.nl> (89db87d7) + + Date extension: implemented a few more date parts. + + +M src/lib-sieve/plugins/date/ext-date-common.c + +2009-10-13 20:10:57 +0200 Stephan Bosch <stephan@rename-it.nl> (47f917af) + + Adjusted to changes in smtp_client API in Dovecot. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-08-12 23:20:43 +0200 Stephan Bosch <stephan@rename-it.nl> (15296322) + + Fixed segfault occuring when message was stored. Namespace was not properly + initialized. + + +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-mailstore.c + +2009-08-10 09:55:36 +0200 Stephan Bosch <stephan@rename-it.nl> (103ea620) + + Fixed distribution of unfinished features. + + +M Makefile.am + +2009-08-09 18:47:13 +0200 Stephan Bosch <stephan@rename-it.nl> (3765cf1c) + + Date extension: built infrastructure for date part testing. + + +M src/lib-sieve/plugins/date/Makefile.am +A src/lib-sieve/plugins/date/ext-date-common.c +M src/lib-sieve/plugins/date/ext-date-common.h +M src/lib-sieve/plugins/date/ext-date.c +M src/lib-sieve/plugins/date/tst-date.c + +2009-08-07 21:50:32 +0200 Stephan Bosch <stephan@rename-it.nl> (43271274) + + Sieve-filter: created man-page a design for the command line options. + + +M Makefile.am +A doc/man/sieve-filter.1 + +2009-08-07 17:42:48 +0200 Stephan Bosch <stephan@rename-it.nl> (2e57e896) + + Include: compare execution result to SIEVE_EXEC_OK and not to zero. + + +M src/lib-sieve/plugins/include/ext-include-common.c + +2009-08-07 17:24:28 +0200 Stephan Bosch <stephan@rename-it.nl> (0ca5d58b) + + Include: fixed return type of execution function. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h + +2009-08-07 17:10:30 +0200 Stephan Bosch <stephan@rename-it.nl> (6c9046de) + + Fixed erroneous comment in binary implementation. + + +M src/lib-sieve/plugins/include/ext-include-binary.c + +2009-08-06 21:46:10 +0200 Stephan Bosch <stephan@rename-it.nl> (951ed92e) + + Fixed typo in TODO file. + + +M TODO + +2009-08-05 23:40:35 +0200 Stephan Bosch <stephan@rename-it.nl> (7097f58c) + + Updated TODO. + + +M TODO + +2009-08-05 23:38:20 +0200 Stephan Bosch <stephan@rename-it.nl> (f0166f99) + + Built skeleton implementation for the date extension (RFC 5260). + + +M configure.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/date/Makefile.am +A src/lib-sieve/plugins/date/ext-date-common.h +A src/lib-sieve/plugins/date/ext-date.c +A src/lib-sieve/plugins/date/tst-date.c +M src/lib-sieve/sieve-extensions.c + +2009-08-05 23:28:21 +0200 Stephan Bosch <stephan@rename-it.nl> (0a245504) + + Body: fixed erroneous return code for invalid optional operand. + + +M src/lib-sieve/plugins/body/tst-body.c + +2009-08-05 13:18:08 +0200 Stephan Bosch <stephan@rename-it.nl> (51cf7daa) + + Be explicit about signedness of data in binary code representation. Some + architectures, like ARM, differ in this respect. + + +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-interpreter.c + +2009-08-05 12:47:27 +0200 Stephan Bosch <stephan@rename-it.nl> (68f65845) + + Side-effect argumennt registrations were not using the SIEVE_OPT_SIDE_EFFECT + constant. + + +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/mailbox/ext-mailbox.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-code.h + +2009-08-05 09:07:14 +0200 Stephan Bosch <stephan@rename-it.nl> (cd4d36c3) + + Removed direct stdint.h includes to prevent portability issues. + + +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-common.h + +2009-08-04 22:18:53 +0200 Stephan Bosch <stephan@rename-it.nl> (d317639a) + + Reprioritized and reformatted TODO file. + + +M TODO + +2009-08-04 19:35:11 +0200 Stephan Bosch <stephan@rename-it.nl> (729452a5) + + Fixed segfault bug in the handling of script open failures. + + +M src/lib-sieve/sieve.c + +2009-08-04 19:34:18 +0200 Stephan Bosch <stephan@rename-it.nl> (4d9f374d) + + Include: further adjusted log and user messages. + + +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-common.c + +2009-08-11 18:13:18 +0200 Stephan Bosch <stephan@rename-it.nl> (88ff726c) + + Mailbox extension: ported mailboxexists test to Dovecot v2.0. + + +M src/lib-sieve/plugins/mailbox/cmd-mailboxexists.c + +2009-08-04 18:53:50 +0200 Stephan Bosch <stephan@rename-it.nl> (0c230819) + + LDA-Sieve plugin: fixed copy-paste mixup between sieve_after and + sieve_before. If only a sieve_after script was active, nothing would have + been executed. Patch by Mike Abbott. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-08-04 18:45:02 +0200 Stephan Bosch <stephan@rename-it.nl> (22c1bca7) + + Include: fixed bug in /home/stephan substitution in sieve_dir path. + + +M src/lib-sieve/plugins/include/ext-include-common.c + +2009-08-04 17:46:30 +0200 Stephan Bosch <stephan@rename-it.nl> (3f844674) + + Include: improved error messages for include failures. + + +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-common.h + +2009-08-04 17:13:50 +0200 Stephan Bosch <stephan@rename-it.nl> (2fcf65a7) + + Include: removed variables-related FIXME and substituted a permanent error + message. + + +M src/lib-sieve/plugins/include/cmd-include.c + +2009-08-03 17:48:11 +0200 Stephan Bosch <stephan@rename-it.nl> (d636abe1) + + Forgot to add header in Makefile.am for testsuite. + + +M src/testsuite/Makefile.am + +2009-08-03 16:43:55 +0200 Stephan Bosch <stephan@rename-it.nl> (9512ce58) + + Fixed automake bug in new maibox extension sources. + + +M src/lib-sieve/plugins/mailbox/Makefile.am + +2009-08-02 16:34:35 +0200 Stephan Bosch <stephan@rename-it.nl> (b07bf640) + + Testsuite: made valgrind report all allocated blocks that remain at program + end. + + +M Makefile.am + +2009-08-02 16:03:13 +0200 Stephan Bosch <stephan@rename-it.nl> (7d7ce23e) + + Testsuite: properly deallocated test name string buffer upon close. + + +M src/testsuite/testsuite-common.c + +2009-08-02 15:41:08 +0200 Stephan Bosch <stephan@rename-it.nl> (3bf779b0) + + Fixed memory leak in matching code caused by earlier fix. + + +M src/lib-sieve/sieve-match.c + +2009-08-02 15:26:33 +0200 Stephan Bosch <stephan@rename-it.nl> (a611b483) + + Made proper API for loading a binary directly. + + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/sieve-tools/sieved.c + +2009-08-02 14:40:46 +0200 Stephan Bosch <stephan@rename-it.nl> (2c2926aa) + + Testsuite: added an important test for the imap4flags extension. + + +M tests/extensions/imap4flags/flagstore.svtest + +2009-08-02 11:00:24 +0200 Stephan Bosch <stephan@rename-it.nl> (d03211b9) + + Imap4flags: added flag storage tests using mailbox loopback. + + +M Makefile.am +M TODO +A tests/extensions/imap4flags/flagstore.svtest + +2009-08-02 10:42:58 +0200 Stephan Bosch <stephan@rename-it.nl> (e78f1905) + + Imap4flags: now reads initial flags and keywords from supplied mail. Upon + delivery this is empty, which still matches the specification. + + +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M tests/extensions/imap4flags/basic.svtest + +2009-08-02 10:40:12 +0200 Stephan Bosch <stephan@rename-it.nl> (a61fb923) + + Added access methods for message data en script environment to result + object. + + +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2009-08-02 00:58:47 +0200 Stephan Bosch <stephan@rename-it.nl> (055ade7b) + + Testsuite: added support for testing delivered messages by looping these + back as the evaluated message. Added tests for the fileinto command. + + +M Makefile.am +M TODO +M src/testsuite/cmd-test-message.c +M src/testsuite/testsuite-mailstore.c +A tests/execute/mailstore.svtest +M tests/extensions/mailbox/execute.svtest + +2009-08-11 18:00:47 +0200 Stephan Bosch <stephan@rename-it.nl> (092ac281) + + Updated README. + + +M README + +2009-08-01 22:40:21 +0200 Stephan Bosch <stephan@rename-it.nl> (45e64f2c) + + Updated TODO and added a FIXME to the mailbox extension (no ACL support yet, + but required by RFC). + + +M TODO +M src/lib-sieve/plugins/mailbox/cmd-mailboxexists.c +M src/lib-sieve/plugins/mailbox/ext-mailbox.c + +2009-08-01 22:33:37 +0200 Stephan Bosch <stephan@rename-it.nl> (322597a8) + + Testsuite: added tests for the mailbox extension. + + +M Makefile.am +A tests/extensions/mailbox/execute.svtest + +2009-08-01 22:28:50 +0200 Stephan Bosch <stephan@rename-it.nl> (742c8bf0) + + Mailbox extension: finished implementation. + + +M src/lib-sieve/plugins/mailbox/cmd-mailboxexists.c +M src/lib-sieve/plugins/mailbox/ext-mailbox.c + +2009-08-01 19:37:24 +0200 Stephan Bosch <stephan@rename-it.nl> (dd677db8) + + Small code cleanup in the lexer code. + + +M src/lib-sieve/sieve-lexer.c + +2009-08-01 13:33:35 +0200 Stephan Bosch <stephan@rename-it.nl> (a594d8f1) + + Updated man pages. + + +M doc/man/sieve-test.1 +M doc/man/sievec.1 +M doc/man/sieved.1 + +2009-07-31 17:35:51 +0200 Stephan Bosch <stephan@rename-it.nl> (f99a83f1) + + Fixed bug in the derivation of the binary path from the script path. A bare + filename would yield a path relative to root. + + +M src/lib-sieve/sieve-script.c + +2009-08-11 17:56:48 +0200 Stephan Bosch <stephan@rename-it.nl> (fc41bc1a) + + Testsuite: added support for testing mailbox operations. + + +M src/testsuite/Makefile.am +A src/testsuite/cmd-test-mailbox.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-common.h +A src/testsuite/testsuite-mailstore.c +A src/testsuite/testsuite-mailstore.h +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite.c +M tests/execute/actions.svtest +M tests/extensions/imap4flags/execute.svtest + +2009-08-11 17:56:02 +0200 Stephan Bosch <stephan@rename-it.nl> (456fd6e0) + + Fixed indent problems. + + +M src/lib-sieve/sieve-actions.c +M src/sieve-tools/sieve-test.c + +2009-07-31 00:13:03 +0200 Stephan Bosch <stephan@rename-it.nl> (4b749557) + + Use foreign automake option so it doesn't complain about missing ChangeLog. + + +M autogen.sh +M configure.in + +2009-07-30 01:15:00 +0200 Stephan Bosch <stephan@rename-it.nl> (033a28eb) + + Regex: documented source code a little better. + + +M src/lib-sieve/plugins/regex/mcht-regex.c + +2009-07-30 01:00:14 +0200 Stephan Bosch <stephan@rename-it.nl> (7c2116f7) + + Made sieve_match_context use a proper pool in stead of the datastack. + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-header.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-result.c + +2009-07-29 02:24:34 +0200 Stephan Bosch <stephan@rename-it.nl> (c72624bc) + + Added TODO item. + + +M TODO + +2009-07-29 01:56:09 +0200 Stephan Bosch <stephan@rename-it.nl> (36963417) + + Include: fixed assertion fail caused by missing initialization (bug surfaces + only for stored binaries). + + +M src/lib-sieve/plugins/include/ext-include.c + +2009-07-29 01:04:09 +0200 Stephan Bosch <stephan@rename-it.nl> (1d8fb774) + + Include: include error message for failed :global include. + + +M src/lib-sieve/plugins/include/ext-include-common.c + +2009-07-27 17:51:13 +0200 Stephan Bosch <stephan@rename-it.nl> (b24b7269) + + Sieve-filter: removed unnecessary MAILBOX_TRANSACTION_FLAG_REFRESH flag for + mailbox_transaction_begin(). + + +M src/sieve-tools/sieve-filter.c + +2009-07-27 00:28:31 +0200 Stephan Bosch <stephan@rename-it.nl> (89ec2c30) + + Reprioritized TODO. + + +M TODO + +2009-08-07 23:57:52 +0200 Stephan Bosch <stephan@rename-it.nl> (71197d41) + + Fixed compile warnings introduced by porting from v1.2. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h + +2009-08-07 23:50:27 +0200 Stephan Bosch <stephan@rename-it.nl> (dd70d665) + + Mailbox extension: implemented the :create tagged argument for the fileinto + command. + + +M src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h + +2009-08-07 23:23:33 +0200 Stephan Bosch <stephan@rename-it.nl> (2b6dacc5) + + Fixed compile error introduced by porting from v1.2. + + +M src/lib-sieve/sieve-actions.c + +2009-08-07 23:21:07 +0200 Stephan Bosch <stephan@rename-it.nl> (99cf7d64) + + Sieve-filter: added support for setting flags on message in the source + folder. + + +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h + +2009-07-26 14:23:02 +0200 Stephan Bosch <stephan@rename-it.nl> (e1f2abc0) + + Sieve-filter: corrected and optimized mail filter loop. + + +M src/sieve-tools/sieve-filter.c + +2009-08-07 23:19:51 +0200 Stephan Bosch <stephan@rename-it.nl> (f002157d) + + Fixed broken wiki reference in error message. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-07-26 02:37:58 +0200 Stephan Bosch <stephan@rename-it.nl> (81a4e22d) + + Implemented skeleton of the mailbox extension. + + +M configure.in +M src/lib-sieve/Makefile.am +A src/lib-sieve/plugins/mailbox/Makefile.am +A src/lib-sieve/plugins/mailbox/cmd-mailboxexists.c +A src/lib-sieve/plugins/mailbox/ext-mailbox-common.h +A src/lib-sieve/plugins/mailbox/ext-mailbox.c +A src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +M src/lib-sieve/sieve-extensions.c + +2009-07-26 02:37:46 +0200 Stephan Bosch <stephan@rename-it.nl> (f83b6345) + + Notify (deprecated): fixed compiler warnings. + + +M src/lib-sieve/plugins/Makefile.am +M src/lib-sieve/plugins/notify/cmd-denotify.c + +2009-07-25 22:44:49 +0200 Stephan Bosch <stephan@rename-it.nl> (a8af380a) + + Sieve-filter: implemented alternative discard actions. + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-types.h +M src/sieve-tools/sieve-filter.c + +2009-07-25 20:12:18 +0200 Stephan Bosch <stephan@rename-it.nl> (a8c1aca0) + + Sieve-filter: implemented expunging filtered messages in the source folder + (move). + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-types.h +M src/sieve-tools/sieve-filter.c + +2009-07-25 01:42:50 +0200 Stephan Bosch <stephan@rename-it.nl> (a584bec0) + + Added means to get keep status from sieve execution through main Sieve + library API. + + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c + +2009-07-25 00:39:35 +0200 Stephan Bosch <stephan@rename-it.nl> (565eb918) + + Minor changes to the sieve-filter tool. + + +M src/sieve-tools/sieve-filter.c + +2009-08-07 23:17:00 +0200 Stephan Bosch <stephan@rename-it.nl> (b5f343d8) + + Restructured store action implementation to properly handle an attempt to + store (keep) a message in the folder it originates from. + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h + +2009-08-07 23:11:14 +0200 Stephan Bosch <stephan@rename-it.nl> (ace3f5a4) + + Notify (deprecated): implemented skeleton of the denotify command. + + +M src/lib-sieve/plugins/notify/Makefile.am +M src/lib-sieve/plugins/notify/cmd-denotify.c +M src/lib-sieve/plugins/notify/cmd-notify.c +A src/lib-sieve/plugins/notify/ext-notify-common.c +M src/lib-sieve/plugins/notify/ext-notify-common.h +M src/lib-sieve/plugins/notify/ext-notify.c + +2009-07-24 12:36:17 +0200 Stephan Bosch <stephan@rename-it.nl> (aebf3eee) + + Fallback to INBOX when storing into a namespace prefix used wrong storage. + + +M src/lib-sieve/sieve-actions.c + +2009-07-24 04:19:44 +0200 Stephan Bosch <stephan@rename-it.nl> (580a1330) + + Separated source and destination mail store for sieve-filter tool. + + +M src/sieve-tools/sieve-filter.c + +2009-08-07 23:07:35 +0200 Stephan Bosch <stephan@rename-it.nl> (1ee0aea6) + + Showed wrong folder name upon INBOX fallback. + + +M src/lib-sieve/sieve-actions.c + +2009-08-07 23:05:25 +0200 Stephan Bosch <stephan@rename-it.nl> (633c5a18) + + Fixed some code indent problems. + + +M src/lib-sieve/sieve-actions.c + +2009-08-07 23:04:06 +0200 Stephan Bosch <stephan@rename-it.nl> (12b28e57) + + Made attempt to store in a namespace prefix fall back into INBOX. + + +M src/lib-sieve/sieve-actions.c + +2009-08-07 23:01:03 +0200 Stephan Bosch <stephan@rename-it.nl> (e4c6a900) + + Fixed logging of folder namespace prefix in store action. + + +M src/lib-sieve/sieve-actions.c + +2009-07-22 00:51:36 +0200 Stephan Bosch <stephan@rename-it.nl> (59c13056) + + Fixed potential segfault argument parameter validation. + + +M src/lib-sieve/sieve-validator.c + +2009-07-21 13:09:06 +0200 Stephan Bosch <stephan@rename-it.nl> (4ad98f80) + + Testsuite: added tests on the envelope of outgoing messages produced by + redirect, enotify:mailto, reject and vacation. + + +M Makefile.am +M src/testsuite/testsuite.c +A tests/execute/smtp.svtest +M tests/extensions/enotify/mailto.svtest +A tests/extensions/reject/smtp.svtest +A tests/extensions/vacation/smtp.svtest + +2009-08-07 22:48:19 +0200 Stephan Bosch <stephan@rename-it.nl> (66cddf8e) + + Major rework of envelope address handling: a normalized version of the + envelope addresses is maintained in the message context and message context + is now also available during action execution. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite.c + +2009-08-07 22:36:04 +0200 Stephan Bosch <stephan@rename-it.nl> (085cad82) + + Fixed segfault bug: made sure return_path is never used without checking for + NULL first. + + +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/notify/cmd-notify.c +M src/lib-sieve/sieve-address.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-smtp.c + +2009-08-07 22:33:35 +0200 Stephan Bosch <stephan@rename-it.nl> (72d3a452) + + Removed the sieve-filter tool from the default build. Need to specify + --with-unfinished-features to get this tool built. + + +M src/sieve-tools/Makefile.am + +2009-07-19 23:18:34 +0200 Stephan Bosch <stephan@rename-it.nl> (d88b39dc) + + Added compilation support for ereject extension. It is unfinished right now + and performs exactly the same action as reject. + + +M src/lib-sieve/ext-reject.c +M src/lib-sieve/sieve-extensions.c + +2009-07-19 23:17:46 +0200 Stephan Bosch <stephan@rename-it.nl> (d1763395) + + Fixed bugs in the autoconf structure regarding enabling/disabling unfinished + features. + + +M configure.in +M dsieve-config.h.in + +2009-07-19 21:57:13 +0200 Stephan Bosch <stephan@rename-it.nl> (1d3c285b) + + Downloaded RFC for reject and ereject extensions. + + +D doc/rfc/draft-ietf-sieve-refuse-reject-07.txt +A doc/rfc/reject-ereject.rfc5429.txt + +2009-07-19 16:59:47 +0200 Stephan Bosch <stephan@rename-it.nl> (18d4325f) + + Improved file manipulation error messages regarding EACCES error. + + +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-script.c + +2009-07-18 11:35:46 +0200 Stephan Bosch <stephan@rename-it.nl> (4ce148eb) + + Testsuite: added tests for envelope/address test behavior with non-existant + subaddress :detail part. + + +M tests/extensions/subaddress/basic.svtest + +2009-07-18 11:34:52 +0200 Stephan Bosch <stephan@rename-it.nl> (5542d373) + + Envelope: fixed bug in application of address parts; failure to obtain the + part would cause inappropriate match success (bug reported by Ron Lee) + + +M src/lib-sieve/ext-envelope.c + +2009-07-18 11:14:18 +0200 Stephan Bosch <stephan@rename-it.nl> (aeaec526) + + Added additional headers to the list of allowed headers for the address + test. + + +M src/lib-sieve/tst-address.c + +2009-07-17 21:52:13 +0200 Stephan Bosch <stephan@rename-it.nl> (2310bf8d) + + Notify (deprecated): added FIXME notice with missing compatibility features. + + +M src/lib-sieve/plugins/notify/ext-notify.c + +2009-07-17 21:46:00 +0200 Stephan Bosch <stephan@rename-it.nl> (fb59caa7) + + Testsuite: added tests for deprecated notify extension. + + +M Makefile.am +A tests/deprecated/notify/basic.svtest +A tests/deprecated/notify/errors.svtest +A tests/deprecated/notify/errors/options.sieve +A tests/deprecated/notify/execute.svtest +A tests/deprecated/notify/execute/duplicates.sieve +A tests/deprecated/notify/mailto.svtest + +2009-07-19 17:20:17 +0200 Stephan Bosch <stephan@rename-it.nl> (3451d5e6) + + Notify (deprecated): fixed compile error due to inappropriate use of SMTP + API. + + +M src/lib-sieve/plugins/notify/cmd-notify.c + +2009-07-19 17:19:25 +0200 Stephan Bosch <stephan@rename-it.nl> (cb2dddc6) + + Testsuite: added support for specifying the available extensions at the + commandline. + + +M src/testsuite/testsuite.c + +2009-07-17 21:38:40 +0200 Stephan Bosch <stephan@rename-it.nl> (23a5f9c8) + + Testsuite: Notify: added test with empty :from argument for notify command. + + +M tests/extensions/enotify/errors.svtest +M tests/extensions/enotify/errors/from-mailto.sieve + +2009-07-17 21:37:23 +0200 Stephan Bosch <stephan@rename-it.nl> (96090a84) + + Notify (deprecated): fixed segfault bug in the :options argument validation. + + +M src/lib-sieve/plugins/notify/cmd-notify.c + +2009-07-17 21:01:03 +0200 Stephan Bosch <stephan@rename-it.nl> (7bf26c2a) + + Notify (deprecated): added runtime check for recipient limit. + + +M src/lib-sieve/plugins/notify/cmd-notify.c + +2009-07-17 20:47:22 +0200 Stephan Bosch <stephan@rename-it.nl> (e6586cb7) + + Notify (deprecated): added runtime check for duplicate recipients. + + +M src/lib-sieve/plugins/notify/cmd-notify.c + +2009-07-17 20:32:39 +0200 Stephan Bosch <stephan@rename-it.nl> (445934a2) + + Notify (deprecated): added support for substitutions in the notification + message. + + +M src/lib-sieve/plugins/notify/cmd-notify.c + +2009-07-17 03:28:04 +0200 Stephan Bosch <stephan@rename-it.nl> (f5268a9c) + + Made deprecated notify extension implementation compatible with cmusieve, + except for the denotify command. + + +M configure.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +M src/lib-sieve/plugins/enotify/Makefile.am +D src/lib-sieve/plugins/enotify/ext-notify.c +A src/lib-sieve/plugins/notify/Makefile.am +A src/lib-sieve/plugins/notify/cmd-denotify.c +A src/lib-sieve/plugins/notify/cmd-notify.c +A src/lib-sieve/plugins/notify/ext-enotify.c +A src/lib-sieve/plugins/notify/ext-notify-common.h +A src/lib-sieve/plugins/notify/ext-notify-limits.h +A src/lib-sieve/plugins/notify/ext-notify.c + +2009-07-08 19:37:24 +0200 Stephan Bosch <stephan@rename-it.nl> (dd412acb) + + Added partial support for the depricated notify extension. + + +M src/lib-sieve/plugins/enotify/Makefile.am +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +A src/lib-sieve/plugins/enotify/ext-notify.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-extensions.c + +2009-07-17 03:14:45 +0200 Stephan Bosch <stephan@rename-it.nl> (1c8106f0) + + Fixed validator extension validation. It validated the first non-require + command before validating the extensions, which produced useless error + messages. + + +M src/lib-sieve/sieve-validator.c + +2009-07-17 01:04:19 +0200 Stephan Bosch <stephan@rename-it.nl> (a11b7ade) + + Made discard action log a message to avoid confusion about disappearing + messages. + + +M src/lib-sieve/cmd-discard.c + +2009-07-15 19:36:17 +0200 Stephan Bosch <stephan@rename-it.nl> (e7a1f2e1) + + Inappropriately ignored return value from fwrite in outgoing message + construction. + + +M src/lib-sieve/rfc2822.c +M src/lib-sieve/rfc2822.h + +2009-07-14 23:08:09 +0200 Stephan Bosch <stephan@rename-it.nl> (8c55bae5) + + Adjusted to Dovecot mail API changes. + + +M src/lib-sieve/sieve-actions.c + +2009-07-08 17:08:23 +0200 Stephan Bosch <stephan@rename-it.nl> (646cd2c1) + + Apparently, deprecated is spelled with an 'e'. + + +M src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/sieve-extensions.c + +2009-07-06 15:05:25 +0200 Stephan Bosch <stephan@rename-it.nl> (9621cd92) + + Fixed AIX compile problem provisionally. + + +M src/lib-sieve/sieve-ast.c + +2009-07-05 09:45:48 +0200 Stephan Bosch <stephan@rename-it.nl> (31b9138b) + + Updated TODO. + + +M TODO + +2009-07-05 10:12:52 +0200 Stephan Bosch <stephan@rename-it.nl> (125bacfe) + + Added item to .hgignore. + + +M .hgignore + +2009-07-05 10:11:13 +0200 Stephan Bosch <stephan@rename-it.nl> (7ec4862e) + + Improved consistency of sieve tool documentation. + + +M doc/man/sieve-test.1 +M doc/man/sievec.1 +M doc/man/sieved.1 +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/sieve-tools/sieved.c + +2009-07-04 14:08:39 +0200 Stephan Bosch <stephan@rename-it.nl> (591ba090) + + Enhanced extensions configuration, allowing to specify the enabled + extensions relatively to the default. + + +M src/lib-sieve/sieve-extensions.c + +2009-07-04 11:26:01 +0200 Stephan Bosch <stephan@rename-it.nl> (242ee570) + + Sieve plugin: forgot to initialize script execution status. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-07-05 10:05:32 +0200 Stephan Bosch <stephan@rename-it.nl> (532f630e) + + Sieve plugin: fixed logging for execution of default main script (went to + STDERR). + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-06-28 15:57:09 +0200 Stephan Bosch <stephan@rename-it.nl> (e7905807) + + Added support for CRLF line breaks in strbuf error handler (ManageSieve + fix). + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h + +2009-06-21 13:35:00 +0200 Stephan Bosch <stephan@rename-it.nl> (05cfe989) + + Adjusted to mailbox API changes in Dovecot. + + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/mail-raw.h +M src/lib-sieve/sieve-actions.c + +2009-06-01 10:20:14 +0200 Stephan Bosch <stephan@rename-it.nl> (7d664b76) + + Body: fixed potential problems wil NUL characters in body parts. + + +M src/lib-sieve/plugins/body/ext-body-common.c + +2009-06-01 10:00:07 +0200 Stephan Bosch <stephan@rename-it.nl> (16372f50) + + Body: fixed assert failure caused by ugly code and a change in dovecot. + + +M src/lib-sieve/plugins/body/ext-body-common.c + +2009-05-29 23:50:53 +0200 Stephan Bosch <stephan@rename-it.nl> (6d5c81d5) + + Body: fixed part of the assert fail problems (Dovecot change). + + +M src/lib-sieve/plugins/body/ext-body-common.c + +2009-05-29 23:49:30 +0200 Stephan Bosch <stephan@rename-it.nl> (8d04eab3) + + Adjusted to changes in Dovecot regarding opening a raw stream. + + +M src/lib-sieve-tool/mail-raw.c +M src/sieve-tools/sieve-test.c + +2009-05-24 18:48:44 +0200 Stephan Bosch <stephan@rename-it.nl> (e701fa64) + + Started using v2.0 settings interface to get plugin settings. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-05-23 13:11:17 +0200 Stephan Bosch <stephan@rename-it.nl> (e5648819) + + Migrated Dovecot Sieve to Dovecot v2.0. + + +M .hgignore +M src/lib-sieve-tool/Makefile.am +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/mail-raw.h +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +A src/lib-sieve/sieve-smtp.c +A src/lib-sieve/sieve-smtp.h +M src/lib-sieve/sieve-types.h +M src/plugins/lda-sieve/Makefile.am +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/Makefile.am +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/sieve-tools/sieved.c +M src/testsuite/Makefile.am +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite.c + +2009-05-18 08:54:26 +0200 Stephan Bosch <stephan@rename-it.nl> (f639cbb5) + + Fixed compiler warning. + + +M src/lib-sieve/plugins/include/ext-include-common.c + +2009-05-17 20:05:44 +0200 Stephan Bosch <stephan@rename-it.nl> (fe48395e) + + Made default of sieve_dir setting match the ManageSieve implementation. + + +M src/lib-sieve/plugins/include/ext-include-common.c + +2009-05-17 19:54:10 +0200 Stephan Bosch <stephan@rename-it.nl> (72aa0c23) + + Fixed indent problems. + + +M src/lib-sieve/plugins/include/ext-include-common.c + +2009-04-18 19:54:33 +0200 Stephan Bosch <stephan@rename-it.nl> (798f2181) + + Released v0.1.5 for Dovecot v1.2.rc3. + + +M NEWS +M configure.in + +2009-04-18 10:15:24 +0200 Stephan Bosch <stephan@rename-it.nl> (55414588) + + Increased binary version number. + + +M src/lib-sieve/sieve-binary.c + +2009-04-18 10:10:21 +0200 Stephan Bosch <stephan@rename-it.nl> (d76b84ac) + + Improved error message for unknown Sieve extension to account for core + commands included as an extension. + + +M src/lib-sieve/cmd-require.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M tests/compile/errors.svtest +M tests/compile/errors/require.sieve + +2009-04-14 18:54:17 +0200 Stephan Bosch <stephan@rename-it.nl> (35608790) + + Fixed bug in the Sieve plugin's return value that caused omission of + delivery when no Sieve scripts are present. Bug spotted by Matthijs + Kooijman. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-04-13 23:18:11 +0200 Stephan Bosch <stephan@rename-it.nl> (abe5e27a) + + Environment: fixed compiler warning. + + +M src/lib-sieve/plugins/environment/ext-environment-common.c + +2009-04-13 21:31:39 +0200 Stephan Bosch <stephan@rename-it.nl> (27dc5d4c) + + Updated NEWS file for upcoming v1.2 release. + + +M NEWS + +2009-04-13 21:30:00 +0200 Stephan Bosch <stephan@rename-it.nl> (b6ee35f9) + + Testsuite: forgot to add new testcase file. + + +A tests/extensions/environment/rfc.svtest + +2009-04-12 15:01:45 +0200 Stephan Bosch <stephan@rename-it.nl> (27317986) + + Environment: fixed segfault and fixed some rfc deviations. + + +M Makefile.am +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/environment/tst-environment.c + +2009-04-12 14:10:40 +0200 Stephan Bosch <stephan@rename-it.nl> (a87632e2) + + Environment: activated host environment item. + + +M src/lib-sieve/plugins/environment/ext-environment-common.c +M src/lib-sieve/plugins/environment/sieve-ext-environment.h +M src/testsuite/testsuite.c +M tests/extensions/environment/basic.svtest + +2009-04-12 12:09:18 +0200 Stephan Bosch <stephan@rename-it.nl> (dfc1ce09) + + Implemented core support for the environment extension. + + +M Makefile.am +M TODO +M configure.in +A doc/rfc/environment.rfc5183.txt +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/environment/Makefile.am +A src/lib-sieve/plugins/environment/ext-environment-common.c +A src/lib-sieve/plugins/environment/ext-environment-common.h +A src/lib-sieve/plugins/environment/ext-environment.c +A src/lib-sieve/plugins/environment/sieve-ext-environment.h +A src/lib-sieve/plugins/environment/tst-environment.c +M src/lib-sieve/sieve-extensions.c +A tests/extensions/environment/basic.svtest + +2009-04-11 00:10:37 +0200 Stephan Bosch <stephan@rename-it.nl> (a8380918) + + Include: added various tests to the testsuite. + + +M Makefile.am +A tests/extensions/include/included-global/rfc-ex1-spam_tests.sieve +A tests/extensions/include/included/rfc-ex1-always_allow.sieve +A tests/extensions/include/included/rfc-ex1-mailing_lists.sieve +A tests/extensions/include/included/rfc-ex1-spam_tests.sieve +A tests/extensions/include/included/rfc-ex2-spam_filter_script.sieve +A tests/extensions/include/included/twice-1.sieve +A tests/extensions/include/included/twice-2.sieve +A tests/extensions/include/rfc-ex1-default.sieve +A tests/extensions/include/rfc-ex2-default.sieve +A tests/extensions/include/rfc.svtest +A tests/extensions/include/twice.svtest + +2009-04-11 00:10:00 +0200 Stephan Bosch <stephan@rename-it.nl> (89baff27) + + Include: fixed bug in binary save of global variable scope. + + +M src/lib-sieve/plugins/include/ext-include-variables.c + +2009-04-10 23:30:15 +0200 Stephan Bosch <stephan@rename-it.nl> (538adede) + + Include: implemented :once modifier for the include command. + + +M Makefile.am +M README +M TODO +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include.c +M tests/extensions/include/included/once-2.sieve +A tests/extensions/include/included/once-3.sieve +A tests/extensions/include/included/once-4.sieve +M tests/extensions/include/once.svtest + +2009-04-10 23:15:51 +0200 Stephan Bosch <stephan@rename-it.nl> (d8d0f6f6) + + Testsuite: fixed minor result passing problem in test code generation. + + +M src/testsuite/cmd-test.c + +2009-04-10 20:27:18 +0200 Stephan Bosch <stephan@rename-it.nl> (f91b1ee6) + + Include: improved runtime script handling. + + +M src/lib-sieve/plugins/include/ext-include-common.c + +2009-04-10 19:30:01 +0200 Stephan Bosch <stephan@rename-it.nl> (fa900dea) + + Include: added runtime check for circular include. + + +M src/lib-sieve/plugins/include/ext-include-common.c + +2009-04-10 19:19:46 +0200 Stephan Bosch <stephan@rename-it.nl> (59192a4e) + + Fixed a few small indent problems. + + +M src/lib-sieve/plugins/include/ext-include-common.c + +2009-04-10 19:16:07 +0200 Stephan Bosch <stephan@rename-it.nl> (47ce4d8c) + + Include: added skeleton :once modifier. + + +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/sieve-binary-dumper.c +A tests/extensions/include/included/once-1.sieve +A tests/extensions/include/included/once-2.sieve +A tests/extensions/include/once.svtest + +2009-04-10 19:11:54 +0200 Stephan Bosch <stephan@rename-it.nl> (0c984f4c) + + Include: fixed bug in sub-sub include. + + +M src/lib-sieve/plugins/include/ext-include-common.c + +2009-04-10 19:10:25 +0200 Stephan Bosch <stephan@rename-it.nl> (768bc087) + + Fixed warnings in revised plugin code. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-04-10 17:39:10 +0200 Stephan Bosch <stephan@rename-it.nl> (0b247829) + + Minor update to the sieve-test manpage + + +M doc/man/sieve-test.1 + +2009-04-10 15:29:01 +0200 Stephan Bosch <stephan@rename-it.nl> (f7de6816) + + Include: updated implementation status. + + +M README +M src/lib-sieve/plugins/include/ext-include.c + +2009-04-10 15:26:01 +0200 Stephan Bosch <stephan@rename-it.nl> (e8eb2131) + + Replaced include specification with latest draft. + + +D doc/rfc/draft-daboo-sieve-include-05.txt +A doc/rfc/draft-ietf-sieve-include-01.txt + +2009-04-10 15:24:48 +0200 Stephan Bosch <stephan@rename-it.nl> (528faeeb) + + Include: replaced import/export commands with global command as specified in + latest draft. Import/export are now DEPRICATED. + + +M src/lib-sieve/plugins/include/Makefile.am +R067 src/lib-sieve/plugins/include/cmd-import.c src/lib-sieve/plugins/include/cmd-global.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/ext-include.c +M tests/extensions/include/errors.svtest +D tests/extensions/include/errors/import-runtime.sieve +M tests/extensions/include/errors/variables-inactive.sieve +M tests/extensions/include/errors/variables.sieve +M tests/extensions/include/included/variables-included1.sieve +M tests/extensions/include/included/variables-included2.sieve +M tests/extensions/include/included/variables-included3.sieve +M tests/extensions/include/variables.svtest + +2009-04-10 14:13:35 +0200 Stephan Bosch <stephan@rename-it.nl> (bece6db9) + + Definitively fixed handling group specifications in mailbox lists of address + headers. + + +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/sieve-address-parts.c +M tests/address.svtest +M tests/extensions/subaddress/basic.svtest + +2009-04-10 02:37:34 +0200 Stephan Bosch <stephan@rename-it.nl> (1a998318) + + Fixed minor typo in sieve-test man page. + + +M doc/man/sieve-test.1 + +2009-04-10 01:27:22 +0200 Stephan Bosch <stephan@rename-it.nl> (50a63dd8) + + Updated TODO. + + +M TODO + +2009-04-10 00:56:15 +0200 Stephan Bosch <stephan@rename-it.nl> (e6379fcc) + + Major rework of the multiscript support for better error handling. + + +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-test.c + +2009-04-09 01:14:42 +0200 Stephan Bosch <stephan@rename-it.nl> (a7d63599) + + Improved plugin debug message. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-04-08 18:56:40 +0200 Stephan Bosch <stephan@rename-it.nl> (c61d3920) + + Fixed problem of unexecuted before/after global scripts when user script is + missing. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-04-07 00:05:55 +0200 Stephan Bosch <stephan@rename-it.nl> (72d99bb2) + + Adjusted to signal handler API changes in Dovecot. + + +M src/lib-sieve-tool/sieve-tool.c + +2009-04-06 00:40:03 +0200 Stephan Bosch <stephan@rename-it.nl> (4a46ebdb) + + Fixed segfault bug caused by undisclosed-recipients:; when fed to the + subaddress extension. + + +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/sieve-address-parts.c + +2009-03-21 15:56:27 +0100 Stephan Bosch <stephan@rename-it.nl> (77282a29) + + Added tag 0.1.4 for changeset b7eb19f14fa7 + + +2009-03-21 15:56:15 +0100 Stephan Bosch <stephan@rename-it.nl> (1dd42d50) + + Released v0.1.4 for Dovecot v1.2.beta3. + + +M NEWS +M configure.in + +2009-03-20 20:00:38 +0100 Stephan Bosch <stephan@rename-it.nl> (f8e708b6) + + Documented vnd.dovecot.debug in the sieve-test man page. + + +M doc/man/sieve-test.1 + +2009-03-20 19:47:38 +0100 Stephan Bosch <stephan@rename-it.nl> (67e76294) + + Updated NEWS file. + + +M NEWS + +2009-03-20 19:30:37 +0100 Stephan Bosch <stephan@rename-it.nl> (3d4541e6) + + Improved error handling and added debug extension to all applicable Sieve + tools. + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/sieve-tools/sieve-filter.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/sieve-tools/sieved.c + +2009-03-14 19:21:21 +0100 Stephan Bosch <stephan@rename-it.nl> (3f6045df) + + Created replaceable error handler for system errors. + + +M NEWS +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h + +2009-03-14 18:15:39 +0100 Stephan Bosch <stephan@rename-it.nl> (720ef3aa) + + Added Dovecot-specific debug extension to the sieve-test tool. + + +M TODO +M configure.in +M src/sieve-tools/Makefile.am +A src/sieve-tools/debug/Makefile.am +A src/sieve-tools/debug/cmd-debug-print.c +A src/sieve-tools/debug/ext-debug-common.h +A src/sieve-tools/debug/ext-debug.c +A src/sieve-tools/debug/sieve-ext-debug.h +M src/sieve-tools/sieve-test.c + +2009-03-14 17:07:27 +0100 Stephan Bosch <stephan@rename-it.nl> (b9cd2210) + + Sieve-filter: implemented basic filtering. + + +M TODO +M src/sieve-tools/sieve-filter.c + +2009-03-05 20:39:56 +0100 Stephan Bosch <stephan@rename-it.nl> (8ed87679) + + Removed unnecessary linker flags that break Solaris compilation. + + +M src/sieve-tools/Makefile.am +M src/testsuite/Makefile.am + +2009-02-24 13:56:46 +0100 Stephan Bosch <stephan@rename-it.nl> (d8696f98) + + Fixed MAC OSX compile problems: forgot extern modifier at various places. + + +M src/lib-sieve/plugins/regex/ext-regex-common.h +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h + +2009-02-23 22:06:58 +0100 Stephan Bosch <stephan@rename-it.nl> (27eff17b) + + Fixed issue with opening relative paths as a mail file. + + +M src/lib-sieve-tool/mail-raw.c + +2009-02-23 18:41:34 +0100 Stephan Bosch <stephan@rename-it.nl> (77844c3f) + + Fixed tmp file name for raw storage used for sieve tools. + + +M src/lib-sieve-tool/mail-raw.c + +2009-02-19 19:35:32 +0100 Stephan Bosch <stephan@rename-it.nl> (8a946c8a) + + Updated TODO. + + +M TODO + +2009-02-19 19:31:32 +0100 Stephan Bosch <stephan@rename-it.nl> (8a09768f) + + Removed inappropriate ACAP rfc for i;ascii-numeric comparator and + substituted rfc4790 in stead. + + +A doc/rfc/collation.rfc4790.txt +D doc/rfc/i-ascii-numeric.rfc2244.txt + +2009-02-15 14:10:55 +0100 Stephan Bosch <stephan@rename-it.nl> (32456894) + + Sieve-filter: developed listing messages in a folder a little further. + + +M src/sieve-tools/sieve-filter.c + +2009-02-15 13:17:52 +0100 Stephan Bosch <stephan@rename-it.nl> (280b3158) + + Started work on sieve-filter tool. + + +M .hgignore +M src/sieve-tools/Makefile.am +A src/sieve-tools/sieve-filter.c + +2009-02-14 10:10:56 +0100 Stephan Bosch <stephan@rename-it.nl> (31e29a26) + + Testsuite: added a few final important tests for the enotify extension. + + +M TODO +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-validator.c +M src/testsuite/cmd-test-message.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h +M tests/extensions/enotify/mailto.svtest + +2009-02-13 00:19:43 +0100 Stephan Bosch <stephan@rename-it.nl> (a877a6b5) + + Added tag 0.1.3 for changeset 8bdff47ab3f0 + + +2009-02-13 00:19:36 +0100 Stephan Bosch <stephan@rename-it.nl> (d6e7b70f) + + Released v0.1.3 for Dovecot v1.2.beta1. + + +M configure.in + +2009-02-12 22:19:39 +0100 Stephan Bosch <stephan@rename-it.nl> (d3afdf0c) + + Added items to the TODO list. + + +M TODO + +2009-02-12 22:02:27 +0100 Stephan Bosch <stephan@rename-it.nl> (54155f42) + + Minor changes to the sievec man page. + + +M doc/man/sievec.1 + +2009-02-12 21:07:58 +0100 Stephan Bosch <stephan@rename-it.nl> (49fd5448) + + Saved binary now has at most the same permissions as the script file itself. + + +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h + +2009-02-12 01:14:52 +0100 Stephan Bosch <stephan@rename-it.nl> (882e35b3) + + Fixed bug the code generation of extensions. + + +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-extensions.c + +2009-02-12 01:14:14 +0100 Stephan Bosch <stephan@rename-it.nl> (8da93e37) + + Added -x parameter to sieved tool. + + +M doc/man/sieved.1 +M src/sieve-tools/sieved.c + +2009-02-11 23:22:34 +0100 Stephan Bosch <stephan@rename-it.nl> (f42e9d1b) + + Fixed small bug in the extension validation. + + +M src/lib-sieve/sieve-validator.c + +2009-02-11 22:39:48 +0100 Stephan Bosch <stephan@rename-it.nl> (79ea9888) + + Imapflags: marked as depricated and disabled by default. + + +M src/lib-sieve/sieve-extensions.c + +2009-02-11 22:35:59 +0100 Stephan Bosch <stephan@rename-it.nl> (9b109792) + + Properly implemented verification of loaded extensions after last require + command is validated. + + +M src/lib-sieve/sieve-validator.c + +2009-02-11 22:35:24 +0100 Stephan Bosch <stephan@rename-it.nl> (7455ba6b) + + Testsuite: added small test for ?* match values. + + +M tests/extensions/variables/match.svtest + +2009-02-11 22:10:14 +0100 Stephan Bosch <stephan@rename-it.nl> (f915a0c9) + + Updated NEWS file for next release. + + +M NEWS + +2009-02-08 18:21:26 +0100 Stephan Bosch <stephan@rename-it.nl> (1fa1740c) + + Testsuite: added message tests for the vacation extension. + + +M Makefile.am +A tests/extensions/vacation/message.svtest +D tests/extensions/vacation/references.svtest + +2009-02-08 18:06:46 +0100 Stephan Bosch <stephan@rename-it.nl> (2aad47e4) + + Testsuite: added support for resetting the result. + + +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/testsuite/Makefile.am +A src/testsuite/cmd-test-result-reset.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-result.h +M src/testsuite/tst-test-script-run.c +M tests/extensions/enotify/mailto.svtest + +2009-02-08 00:32:47 +0100 Stephan Bosch <stephan@rename-it.nl> (8488591c) + + Testsuite: added tests for enotify with multiple recipients. + + +M tests/extensions/enotify/mailto.svtest + +2009-02-08 00:10:26 +0100 Stephan Bosch <stephan@rename-it.nl> (a6a59602) + + Testsuite: added support for looping back outgoing SMTP messages back into + the test. + + +M Makefile.am +M TODO +M src/lib-sieve/plugins/include/cmd-import.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/tst-size.c +M src/testsuite/Makefile.am +A src/testsuite/cmd-test-message.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-message.c +M src/testsuite/testsuite-message.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-smtp.c +M src/testsuite/testsuite-smtp.h +M src/testsuite/tst-test-result-execute.c +A tests/extensions/enotify/mailto.svtest + +2009-02-07 18:26:50 +0100 Stephan Bosch <stephan@rename-it.nl> (3f573f87) + + Defined very basic function for address comparison. + + +M TODO +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h + +2009-02-07 00:44:59 +0100 Stephan Bosch <stephan@rename-it.nl> (acb82aab) + + Adjusted store action to API changes in Dovecot. + + +M src/lib-sieve/sieve-actions.c + +2009-02-06 18:28:47 +0100 Stephan Bosch <stephan@rename-it.nl> (31bc8a9f) + + Vacation: made addresses comparison case-insensitive. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-address.c +M tests/extensions/vacation/execute/action.sieve + +2009-02-05 00:24:29 +0100 Stephan Bosch <stephan@rename-it.nl> (741b295b) + + Updated documentation. + + +M README + +2009-02-05 00:21:29 +0100 Stephan Bosch <stephan@rename-it.nl> (214d41be) + + Imap4flags: fixed dumping of \flagged flag in flags side effect. + + +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M tests/extensions/imap4flags/execute/imapflags.sieve + +2009-02-05 00:17:28 +0100 Stephan Bosch <stephan@rename-it.nl> (87c64daf) + + Imap4flags: added support for obsolete imapflags extension for backwards + compatibility with CMUSieve. + + +M Makefile.am +M src/lib-sieve/plugins/imap4flags/Makefile.am +A src/lib-sieve/plugins/imap4flags/ext-imapflags.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-validator.c +M src/testsuite/testsuite.c +A tests/extensions/imap4flags/errors.svtest +A tests/extensions/imap4flags/errors/imapflags.sieve +A tests/extensions/imap4flags/execute/imapflags.sieve + +2009-02-04 22:43:33 +0100 Stephan Bosch <stephan@rename-it.nl> (a4176570) + + Validator: added support for checking loaded extensions. + + +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h + +2009-02-04 22:13:48 +0100 Stephan Bosch <stephan@rename-it.nl> (06949d2b) + + Added facilities for requiring extensions and making extensions mutually + exclusive. + + +M src/lib-sieve/cmd-require.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h + +2009-02-04 21:32:17 +0100 Stephan Bosch <stephan@rename-it.nl> (542e9489) + + Imap4flags: gave testsuite directory proper name. + + +M Makefile.am +R100 tests/extensions/imapflags/basic.svtest tests/extensions/imap4flags/basic.svtest +R100 tests/extensions/imapflags/execute.svtest tests/extensions/imap4flags/execute.svtest +R100 tests/extensions/imapflags/execute/flags-side-effect.sieve tests/extensions/imap4flags/execute/flags-side-effect.sieve +R100 tests/extensions/imapflags/hasflag.svtest tests/extensions/imap4flags/hasflag.svtest + +2009-02-04 20:24:43 +0100 Stephan Bosch <stephan@rename-it.nl> (0e048ed6) + + Imap4flags: properly named extension objects. + + +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c +M src/lib-sieve/sieve-extensions.c + +2009-02-04 20:18:13 +0100 Stephan Bosch <stephan@rename-it.nl> (aa8eb737) + + Imap4flags: properly named functions. + + +M src/lib-sieve/plugins/imap4flags/cmd-flag.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +M src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +M src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +M src/lib-sieve/plugins/imap4flags/tag-flags.c +M src/lib-sieve/plugins/imap4flags/tst-hasflag.c + +2009-02-04 19:59:56 +0100 Stephan Bosch <stephan@rename-it.nl> (c051208b) + + Imap4flags: properly named extension directory and source files. + + +M configure.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +R066 src/lib-sieve/plugins/imapflags/Makefile.am src/lib-sieve/plugins/imap4flags/Makefile.am +R099 src/lib-sieve/plugins/imapflags/cmd-flag.c src/lib-sieve/plugins/imap4flags/cmd-flag.c +R099 src/lib-sieve/plugins/imapflags/ext-imapflags-common.c src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +R097 src/lib-sieve/plugins/imapflags/ext-imapflags-common.h src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +R098 src/lib-sieve/plugins/imapflags/ext-imapflags.c src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +R099 src/lib-sieve/plugins/imapflags/tag-flags.c src/lib-sieve/plugins/imap4flags/tag-flags.c +R099 src/lib-sieve/plugins/imapflags/tst-hasflag.c src/lib-sieve/plugins/imap4flags/tst-hasflag.c + +2009-02-03 21:06:34 +0100 Stephan Bosch <stephan@rename-it.nl> (bd16e831) + + Fixed README: now mentions the naming differences of the imap4flags and + enotify extensions compared to the old CMU Sieve plugin. + + +M README + +2009-02-02 11:03:07 +0100 Stephan Bosch <stephan@rename-it.nl> (e54e3922) + + Fixed compile warning caused by missing include. + + +M src/lib-sieve/cmd-redirect.c + +2009-02-01 19:49:03 +0100 Stephan Bosch <stephan@rename-it.nl> (448d8db5) + + Installed RFC documents for notify extension and corresponding mailto + method. + + +D doc/rfc/draft-ietf-sieve-notify-12.txt +R051 doc/rfc/draft-ietf-sieve-notify-mailto-10.txt doc/rfc/notify-mailto.rfc5436.txt +A doc/rfc/notify.rfc5435.txt +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2009-02-01 14:06:47 +0100 Stephan Bosch <stephan@rename-it.nl> (97c1dc8d) + + Cleaned up :matches match-type code. + + +M src/lib-sieve/mcht-matches.c +M tests/match-types/matches.svtest + +2009-02-01 13:30:11 +0100 Stephan Bosch <stephan@rename-it.nl> (8d4f5015) + + Fixed bug in the :matches match type. + + +M src/lib-sieve/mcht-matches.c +M tests/match-types/matches.svtest + +2009-01-27 17:19:22 +0100 Stephan Bosch <stephan@rename-it.nl> (ab6177dd) + + Added important TODO item. + + +M TODO + +2009-01-27 10:54:31 +0100 Stephan Bosch <stephan@rename-it.nl> (826c4ef8) + + Changed SMTP message generation back to CRLF, because the Sieve engine uses + CRLF internally. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/rfc2822.c + +2009-01-27 00:32:20 +0100 Stephan Bosch <stephan@rename-it.nl> (8e33424b) + + Fixed use of data stack by binary dumping code. + + +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code.c + +2009-01-27 00:31:57 +0100 Stephan Bosch <stephan@rename-it.nl> (37ed7849) + + Regex: fixed segfault bug occuring when regex is freed. + + +M src/lib-sieve/plugins/regex/mcht-regex.c + +2009-01-27 00:31:05 +0100 Stephan Bosch <stephan@rename-it.nl> (6b604fd1) + + Testsuite: fixed warning. + + +M src/testsuite/tst-test-script-compile.c + +2009-01-27 00:30:43 +0100 Stephan Bosch <stephan@rename-it.nl> (286d42d4) + + Increased various initial pool sizes. + + +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-validator.c + +2009-01-26 23:21:36 +0100 Stephan Bosch <stephan@rename-it.nl> (d4bc6cce) + + Increased initial size of binary's lazy_file pool. + + +M src/lib-sieve/sieve-binary.c + +2009-01-26 22:58:30 +0100 Stephan Bosch <stephan@rename-it.nl> (cc9ea513) + + Fixed error in the SMTP message composition that caused mixing of CRLF and + LF in redirected messages. + + +M src/lib-sieve/rfc2822.c + +2009-01-22 23:17:06 +0100 Stephan Bosch <stephan@rename-it.nl> (751e4095) + + Updated NEWS file. + + +M NEWS + +2009-01-22 23:16:30 +0100 Stephan Bosch <stephan@rename-it.nl> (dbadda3a) + + Updated NEWS file. + + +M NEWS + +2009-01-22 22:02:30 +0100 Stephan Bosch <stephan@rename-it.nl> (7527d467) + + Updated README file. + + +M README + +2009-01-22 21:55:27 +0100 Stephan Bosch <stephan@rename-it.nl> (8687fe89) + + Prepared NEWS file for next release. + + +M NEWS + +2009-01-22 20:43:52 +0100 Stephan Bosch <stephan@rename-it.nl> (6d2522d0) + + Updated documentation. + + +M INSTALL + +2009-01-22 00:20:10 +0100 Stephan Bosch <stephan@rename-it.nl> (cf33f358) + + Testsuite: added simple tests for the match values produced by the :regex + match. + + +M Makefile.am +A tests/extensions/regex/match-values.svtest + +2009-01-22 00:19:41 +0100 Stephan Bosch <stephan@rename-it.nl> (8fa2ee03) + + Regex: fixed bug in the match value indexes. + + +M src/lib-sieve/plugins/regex/mcht-regex.c + +2009-01-18 17:52:40 +0100 Stephan Bosch <stephan@rename-it.nl> (2919e2d0) + + Added multiscript draft to the doc/rfc directory. + + +A doc/rfc/draft-degener-sieve-multiscript-00.txt + +2009-01-18 17:32:15 +0100 Stephan Bosch <stephan@rename-it.nl> (bfbd7d01) + + Testsuite: added storage of outgoing SMTP messages. + + +M src/testsuite/Makefile.am +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-message.c +A src/testsuite/testsuite-smtp.c +A src/testsuite/testsuite-smtp.h +M src/testsuite/testsuite.c +M src/testsuite/tst-test-script-run.c + +2009-01-18 14:07:46 +0100 Stephan Bosch <stephan@rename-it.nl> (fc011a3e) + + Testsuite: exported message handling to separate module. + + +M src/testsuite/Makefile.am +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +A src/testsuite/testsuite-message.c +A src/testsuite/testsuite-message.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite.c + +2009-01-16 19:56:15 +0100 Stephan Bosch <stephan@rename-it.nl> (b4e7dc74) + + Enotify: cleaned up method API. + + +M TODO +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2009-01-16 19:20:22 +0100 Stephan Bosch <stephan@rename-it.nl> (2f8711f9) + + Testsuite: improved testsuite with respect to testing of setflag, addflag + and removeflag commands. + + +M tests/extensions/imapflags/basic.svtest +M tests/extensions/imapflags/hasflag.svtest + +2009-01-16 19:19:46 +0100 Stephan Bosch <stephan@rename-it.nl> (b9ba12b3) + + Imap4flags: merged setflag, addflag and removeflag implementations. + + +M TODO +M src/lib-sieve/plugins/imapflags/Makefile.am +D src/lib-sieve/plugins/imapflags/cmd-addflag.c +A src/lib-sieve/plugins/imapflags/cmd-flag.c +D src/lib-sieve/plugins/imapflags/cmd-removeflag.c +D src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h + +2009-01-16 18:32:12 +0100 Stephan Bosch <stephan@rename-it.nl> (3eb9eaed) + + Added sieve_subaddress_sep setting. + + +M INSTALL +M src/lib-sieve/plugins/subaddress/ext-subaddress.c + +2009-01-11 12:14:38 +0100 Stephan Bosch <stephan@rename-it.nl> (e46dea37) + + Fixed bug in the outgoing mail address verification. + + +M src/lib-sieve/sieve-address.c +M tests/compile/errors.svtest +M tests/compile/errors/out-address.sieve + +2009-01-11 11:56:13 +0100 Stephan Bosch <stephan@rename-it.nl> (7dab1255) + + Enotify/Mailto: prevented single recipient from receiving multiple + notifications on the same message. + + +M TODO +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M tests/extensions/enotify/execute.svtest +M tests/extensions/enotify/execute/duplicates.sieve + +2009-01-11 11:53:13 +0100 Stephan Bosch <stephan@rename-it.nl> (5ef4fda9) + + Testsuite: fixed segfault bugs in the error handling. + + +M src/testsuite/testsuite.c + +2009-01-10 23:57:03 +0100 Stephan Bosch <stephan@rename-it.nl> (8c07be8e) + + Small project status update to the README. + + +M README + +2009-01-10 23:50:24 +0100 Stephan Bosch <stephan@rename-it.nl> (3f157f00) + + Enotify: added API for detecting and killing duplicate notification + recipients. + + +M TODO +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M tests/extensions/enotify/execute.svtest +A tests/extensions/enotify/execute/duplicates.sieve + +2009-01-10 23:19:48 +0100 Stephan Bosch <stephan@rename-it.nl> (935133cc) + + Multiscript: implemented sorting of script files in script directories for + Sieve plugin. + + +M TODO +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-01-10 23:07:59 +0100 Stephan Bosch <stephan@rename-it.nl> (702921e7) + + Updated documentation. + + +M INSTALL +M README +M TODO +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-01-10 22:22:17 +0100 Stephan Bosch <stephan@rename-it.nl> (d60ea1a8) + + Reprioritized TODO. + + +M TODO + +2009-01-10 21:54:06 +0100 Stephan Bosch <stephan@rename-it.nl> (a48cf926) + + Got array_get_pool() integrated into Dovecot. + + +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2009-01-10 21:14:50 +0100 Stephan Bosch <stephan@rename-it.nl> (ac14b30e) + + Updated documentation. + + +M README +M TODO + +2009-01-10 20:37:42 +0100 Stephan Bosch <stephan@rename-it.nl> (d5c70708) + + Fixed segfault in lda sieve plugin. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2009-01-10 19:28:28 +0100 Stephan Bosch <stephan@rename-it.nl> (b54aac45) + + Enotify/Mailto: fixed bug in the generation of the SMTP envelope sender. + + +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2009-01-10 19:18:13 +0100 Stephan Bosch <stephan@rename-it.nl> (77eb7de3) + + Enotify: fixed various indent mishaps in ntfy-mailto.c. + + +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2009-01-10 19:15:05 +0100 Stephan Bosch <stephan@rename-it.nl> (5c0e1898) + + Multiscript: added untested multiscript support to the lda sieve plugin. + + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-test.c + +2009-01-09 21:37:37 +0100 Stephan Bosch <stephan@rename-it.nl> (a301c3c1) + + Added a few accessors to the binary object for convenience. + + +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h + +2009-01-09 21:37:03 +0100 Stephan Bosch <stephan@rename-it.nl> (a69ec7dd) + + Testsuite: fixed warning. + + +M src/testsuite/testsuite.c + +2009-01-09 02:31:19 +0100 Stephan Bosch <stephan@rename-it.nl> (37288bc4) + + Testsuite: fixed result handling. + + +M src/testsuite/testsuite.c + +2009-01-09 01:37:28 +0100 Stephan Bosch <stephan@rename-it.nl> (b4a41703) + + Removed remaining references to sieve-exec. + + +M TODO + +2009-01-07 01:14:05 +0100 Stephan Bosch <stephan@rename-it.nl> (b3f7c89e) + + Extended sievec command to allow compiling an entire directory. + + +M doc/man/sievec.1 +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite.c + +2009-01-06 23:42:30 +0100 Stephan Bosch <stephan@rename-it.nl> (c9ae3e44) + + Minor revisions to the sieved man page. + + +M doc/man/sieved.1 + +2009-01-06 23:40:00 +0100 Stephan Bosch <stephan@rename-it.nl> (e1c090fe) + + Made outfile argument of the sievec command optional. + + +M doc/man/sievec.1 +M src/sieve-tools/sievec.c + +2009-01-06 23:16:32 +0100 Stephan Bosch <stephan@rename-it.nl> (338121cb) + + Updated README. + + +M README + +2009-01-06 22:48:48 +0100 Stephan Bosch <stephan@rename-it.nl> (1e538582) + + Merged sieve-exec tool into sieve-test. + + +M doc/man/sieve-test.1 +M doc/man/sievec.1 +M doc/man/sieved.1 +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve.c +M src/sieve-tools/Makefile.am +D src/sieve-tools/sieve-exec.c +M src/sieve-tools/sieve-test.c + +2009-01-06 01:30:55 +0100 Stephan Bosch <stephan@rename-it.nl> (3792833c) + + Fixed various result error messages. + + +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2009-01-06 00:28:56 +0100 Stephan Bosch <stephan@rename-it.nl> (f75b4a61) + + Fixed a theoretical security hole occuring when directory is opened as a + Sieve binary. + + +M src/lib-sieve/sieve-binary.c + +2009-01-04 19:17:14 +0100 Stephan Bosch <stephan@rename-it.nl> (8763c8d1) + + Updated TODO. + + +M TODO +M src/sieve-tools/sieve-test.c + +2009-01-04 18:08:23 +0100 Stephan Bosch <stephan@rename-it.nl> (d717b880) + + Multiscript: fixed small bug in result printing. + + +M src/lib-sieve/sieve-result.c +M src/sieve-tools/sieve-test.c + +2009-01-04 17:54:12 +0100 Stephan Bosch <stephan@rename-it.nl> (11eb119a) + + Multiscript: improved handling of the keep action. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/sieve-tools/sieve-test.c + +2009-01-04 01:00:50 +0100 Stephan Bosch <stephan@rename-it.nl> (82d7857b) + + Updated TODO. + + +M TODO + +2009-01-04 00:55:07 +0100 Stephan Bosch <stephan@rename-it.nl> (bcbb3217) + + Multiscript: implemented execution of multiple scripts for the sieve-test + command. + + +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/sieve-tools/sieve-test.c + +2009-01-03 21:54:29 +0100 Stephan Bosch <stephan@rename-it.nl> (9f5a9b7c) + + Multiscript: implemented API. + + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h + +2009-01-03 20:26:41 +0100 Stephan Bosch <stephan@rename-it.nl> (8c269b44) + + Multiscript: various changes to the interpreter to facilitate multiscript + support. + + +M doc/man/sieve-test.1 +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-exec.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite.c + +2009-01-02 23:23:06 +0100 Stephan Bosch <stephan@rename-it.nl> (92a22a1a) + + Multiscript: added keep status evaluation to result object. + + +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2009-01-02 22:57:51 +0100 Stephan Bosch <stephan@rename-it.nl> (1d773826) + + Updated copyright messages to 2009. + + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/mail-raw.h +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve-tool/sieve-tool.h +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/cmd-stop.c +M src/lib-sieve/cmp-i-ascii-casemap.c +M src/lib-sieve/cmp-i-octet.c +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify-limits.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-import.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-limits.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/regex/ext-regex-common.c +M src/lib-sieve/plugins/regex/ext-regex-common.h +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.h +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables-dump.h +M src/lib-sieve/plugins/variables/ext-variables-limits.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-name.c +M src/lib-sieve/plugins/variables/ext-variables-name.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/rfc2822.c +M src/lib-sieve/rfc2822.h +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-limits.c +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-objects.c +M src/lib-sieve/sieve-objects.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c +M src/lib-sieve/tst-truefalse.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/plugins/lda-sieve/lda-sieve-plugin.h +M src/sieve-tools/sieve-exec.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c +M src/sieve-tools/sieved.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-result-print.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-arguments.c +M src/testsuite/testsuite-arguments.h +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-log.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-result.h +M src/testsuite/testsuite-script.c +M src/testsuite/testsuite-script.h +M src/testsuite/testsuite-substitutions.c +M src/testsuite/testsuite-substitutions.h +M src/testsuite/testsuite.c +M src/testsuite/tst-test-error.c +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-result.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c + +2009-01-02 21:48:57 +0100 Stephan Bosch <stephan@rename-it.nl> (60a4708a) + + Testsuite: extended multiscript testing. + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve.c +M src/testsuite/testsuite-result.c +M tests/multiscript/conflicts.svtest +A tests/multiscript/fileinto-frop.sieve +A tests/multiscript/keep.sieve + +2009-01-02 14:51:03 +0100 Stephan Bosch <stephan@rename-it.nl> (3285d7b9) + + Testsuite: added multiscript tests and required support. + + +M Makefile.am +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/testsuite/Makefile.am +A src/testsuite/cmd-test-result-print.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-log.c +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-result.h +M src/testsuite/tst-test-result-execute.c +M src/testsuite/tst-test-script-compile.c +M src/testsuite/tst-test-script-run.c +A tests/multiscript/basic.svtest +A tests/multiscript/conflicts.svtest +A tests/multiscript/fileinto-inbox.sieve +A tests/multiscript/notify.sieve +A tests/multiscript/reject-1.sieve +A tests/multiscript/reject-2.sieve +A tests/multiscript/vacation.sieve + +2009-01-02 14:12:33 +0100 Stephan Bosch <stephan@rename-it.nl> (0d907631) + + Enotify: removed conflicting action flag. + + +M src/lib-sieve/plugins/enotify/cmd-notify.c + +2009-01-02 14:11:27 +0100 Stephan Bosch <stephan@rename-it.nl> (1cdc4fab) + + Testsuite: forgot to add new files. + + +A src/testsuite/testsuite-log.c +A src/testsuite/testsuite-log.h +A src/testsuite/testsuite-script.c +A src/testsuite/testsuite-script.h + +2009-01-02 12:35:13 +0100 Stephan Bosch <stephan@rename-it.nl> (bff1bf54) + + Testsuite: split off script and error handler implementations into separate + modules. + + +M src/testsuite/Makefile.am +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-result.c +M src/testsuite/tst-test-error.c +M tests/extensions/enotify/basic.svtest + +2009-01-01 22:27:19 +0100 Stephan Bosch <stephan@rename-it.nl> (3c46a10a) + + Fixed warning caused by previous changes. + + +M src/lib-sieve/plugins/enotify/cmd-notify.c + +2009-01-01 19:37:26 +0100 Stephan Bosch <stephan@rename-it.nl> (6cdfe4f4) + + Multiscript: resolved inter-script action conflict situations. + + +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-result.c + +2009-01-01 19:14:40 +0100 Stephan Bosch <stephan@rename-it.nl> (643e8901) + + Cleaned up action interface. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c + +2009-01-01 18:12:08 +0100 Stephan Bosch <stephan@rename-it.nl> (4a2e1f72) + + Multiscript: adjusted result object for sequential execution. + + +M TODO +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/testsuite/tst-test-result.c +M tests/execute/actions.svtest +M tests/extensions/vacation/execute.svtest + +2008-12-29 17:32:34 +0100 Stephan Bosch <stephan@rename-it.nl> (a5744734) + + Updated TODO. + + +M TODO + +2008-12-28 21:09:49 +0100 Stephan Bosch <stephan@rename-it.nl> (b73e9222) + + Testsuite: added basic result execution tests for various extensions. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-result.c +M src/testsuite/testsuite-result.c +M tests/execute/actions.svtest +M tests/extensions/imapflags/execute.svtest +M tests/extensions/reject/execute.svtest +M tests/extensions/vacation/execute.svtest + +2008-12-28 20:00:26 +0100 Stephan Bosch <stephan@rename-it.nl> (84b5f74b) + + Testsuite: added support for executing results. + + +M src/lib-sieve/sieve-result.h +M src/testsuite/Makefile.am +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-result.c +M src/testsuite/testsuite-result.h +A src/testsuite/tst-test-result-execute.c +M tests/extensions/enotify/execute.svtest + +2008-12-28 18:49:06 +0100 Stephan Bosch <stephan@rename-it.nl> (0e272ca2) + + Testsuite: forgot committing rename in previous commit. + + +R074 src/testsuite/tst-test-compile.c src/testsuite/tst-test-script-compile.c +R065 src/testsuite/tst-test-execute.c src/testsuite/tst-test-script-run.c + +2008-12-28 18:47:27 +0100 Stephan Bosch <stephan@rename-it.nl> (09137580) + + Testsuite: renamed script compile and run commands to be more intuitive. + + +M src/testsuite/Makefile.am +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/tst-test-result.c +M tests/compile/compile.svtest +M tests/compile/errors.svtest +M tests/compile/examples.svtest +M tests/execute/actions.svtest +M tests/execute/errors.svtest +M tests/extensions/enotify/errors.svtest +M tests/extensions/enotify/execute.svtest +M tests/extensions/imapflags/execute.svtest +M tests/extensions/include/errors.svtest +M tests/extensions/regex/errors.svtest +M tests/extensions/reject/execute.svtest +M tests/extensions/relational/errors.svtest +M tests/extensions/vacation/errors.svtest +M tests/extensions/vacation/execute.svtest +M tests/extensions/variables/errors.svtest +M tests/testsuite.svtest + +2008-12-28 18:06:38 +0100 Stephan Bosch <stephan@rename-it.nl> (27844839) + + Testsuite: started implementing support for testsuite-specific string + substitutions. + + +M src/lib-sieve/sieve-code.c +M src/testsuite/Makefile.am +M src/testsuite/ext-testsuite.c +A src/testsuite/testsuite-arguments.c +A src/testsuite/testsuite-arguments.h +M src/testsuite/testsuite-common.h +A src/testsuite/testsuite-substitutions.c +A src/testsuite/testsuite-substitutions.h +M tests/testsuite.svtest + +2008-12-28 13:37:18 +0100 Stephan Bosch <stephan@rename-it.nl> (d622ff1a) + + Exported variable string argument into the Sieve engine itself as 'catenated + string' (for similar use in other extensions like the testsuite). + + +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h + +2008-12-28 12:21:09 +0100 Stephan Bosch <stephan@rename-it.nl> (9c996b7e) + + Exported variable string operand into the Sieve engine itself as 'catenated + string' (for similar use in other extensions like the testsuite). + + +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h + +2008-12-28 01:56:48 +0100 Stephan Bosch <stephan@rename-it.nl> (0cd98756) + + Updated TODO. + + +M TODO + +2008-12-28 01:56:39 +0100 Stephan Bosch <stephan@rename-it.nl> (2d214818) + + Enotify: mailto: forgot to add 'from' header to list of reserved headers. + + +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2008-12-28 01:49:39 +0100 Stephan Bosch <stephan@rename-it.nl> (48d8584d) + + Updated TODO list. + + +M TODO + +2008-12-28 01:48:32 +0100 Stephan Bosch <stephan@rename-it.nl> (124df196) + + Enotify: added enotify extension to default compile. + + +M Makefile.am +M TODO +M configure.in +M dsieve-config.h.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +M src/lib-sieve/sieve-extensions.c + +2008-12-28 01:31:35 +0100 Stephan Bosch <stephan@rename-it.nl> (3023a857) + + Enotify: mailto: enforced limits on number of recipients and headers. + + +M TODO +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2008-12-28 00:48:17 +0100 Stephan Bosch <stephan@rename-it.nl> (9b5384db) + + Enotify: mailto: finished URI parsing. + + +M TODO +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M tests/extensions/enotify/errors.svtest +M tests/extensions/enotify/errors/uri-mailto.sieve + +2008-12-27 23:57:52 +0100 Stephan Bosch <stephan@rename-it.nl> (18e89e3a) + + Enotify: mailto: fixed various bugs introduced by previous enthousiastic + commit. + + +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2008-12-27 23:47:26 +0100 Stephan Bosch <stephan@rename-it.nl> (8e50743d) + + Enotify: mailto: added check for duplicates of unique headers in the mailto + URI. + + +M TODO +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2008-12-27 22:47:45 +0100 Stephan Bosch <stephan@rename-it.nl> (ec0368c2) + + Enotify: previous change did not distinguish Cc recipients. + + +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2008-12-27 22:43:33 +0100 Stephan Bosch <stephan@rename-it.nl> (877ba290) + + Enotify: added check for duplicate recipients within URI. + + +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2008-12-27 21:57:43 +0100 Stephan Bosch <stephan@rename-it.nl> (9b37865e) + + Updated TODO. + + +M TODO + +2008-12-27 21:52:31 +0100 Stephan Bosch <stephan@rename-it.nl> (a3ab3278) + + Enotify: added FIXME. + + +M src/lib-sieve/plugins/enotify/ext-enotify-common.c + +2008-12-27 21:33:53 +0100 Stephan Bosch <stephan@rename-it.nl> (6c1b2dff) + + Enotify: added runtime support for options and performed some minor + cleanups. + + +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h + +2008-12-27 19:25:43 +0100 Stephan Bosch <stephan@rename-it.nl> (ec0a0295) + + Enotify: added parsing support for the :options argument. + + +M TODO +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M tests/extensions/enotify/errors.svtest +A tests/extensions/enotify/errors/options.sieve + +2008-12-27 14:24:52 +0100 Stephan Bosch <stephan@rename-it.nl> (924f35f9) + + Fixed semantic bug in extension handling. + + +M src/lib-sieve/sieve-extensions.c + +2008-12-27 14:11:20 +0100 Stephan Bosch <stephan@rename-it.nl> (c744cea0) + + Fixed segfault bug in extension handling. + + +M src/lib-sieve/sieve-extensions.c + +2008-12-27 00:09:43 +0100 Stephan Bosch <stephan@rename-it.nl> (e86e6068) + + Moved new_message_id function to sieve-message.c where it is more + appropriate. + + +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h + +2008-12-27 00:08:55 +0100 Stephan Bosch <stephan@rename-it.nl> (eac31301) + + Updated documentation. + + +M README +M src/lib-sieve/plugins/enotify/ext-enotify.c + +2008-12-25 23:31:31 +0100 Stephan Bosch <stephan@rename-it.nl> (4bf97c70) + + Updated TODO. + + +M TODO + +2008-12-25 23:26:59 +0100 Stephan Bosch <stephan@rename-it.nl> (031af6a2) + + Enotify: implemented notify_method_capability test. + + +M Makefile.am +M TODO +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +A tests/extensions/enotify/notify_method_capability.svtest +R077 tests/extensions/enotify/valid-notify-method.svtest tests/extensions/enotify/valid_notify_method.svtest + +2008-12-25 21:07:02 +0100 Stephan Bosch <stephan@rename-it.nl> (887c8f69) + + Enotify: implemented the valid_notify_method test. + + +M TODO +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M tests/extensions/enotify/errors.svtest +R100 tests/extensions/enotify/errors/url-mailto.sieve tests/extensions/enotify/errors/uri-mailto.sieve +R100 tests/extensions/enotify/errors/url.sieve tests/extensions/enotify/errors/uri.sieve +A tests/extensions/enotify/valid-notify-method.svtest + +2008-12-25 18:02:06 +0100 Stephan Bosch <stephan@rename-it.nl> (8e29831d) + + Simplified handling of extension ids. + + +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-validator.c +M src/testsuite/ext-testsuite.c + +2008-12-25 15:26:34 +0100 Stephan Bosch <stephan@rename-it.nl> (c2a70097) + + Renamed extension object registry. + + +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/regex/ext-regex-common.c +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-objects.c +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h + +2008-12-21 20:50:54 +0100 Stephan Bosch <stephan@rename-it.nl> (2d060bda) + + Merged concurrent changes. + + +2008-12-21 20:49:19 +0100 Stephan Bosch <stephan@rename-it.nl> (9ea68a04) + + Implemented support for configuring the available extensions. + + +M TODO +M doc/man/sieve-test.1 +M doc/man/sievec.1 +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-tools/sieve-test.c +M src/sieve-tools/sievec.c + +2008-12-21 16:32:07 +0100 Stephan Bosch <stephan@rename-it.nl> (590bcfd9) + + Vacation: changed location of X-Sieve header. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2008-12-21 16:30:16 +0100 Stephan Bosch <stephan@rename-it.nl> (5eabe7ae) + + Vacation: last change used wrong address. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2008-12-21 16:11:52 +0100 Stephan Bosch <stephan@rename-it.nl> (a5264617) + + Vacation: properly implemented use of :from address argument. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2008-12-21 15:55:07 +0100 Stephan Bosch <stephan@rename-it.nl> (63ed66d9) + + Fixed accidental paste in sieve-address.c. + + +M src/lib-sieve/sieve-address.c + +2008-12-21 14:26:22 +0100 Stephan Bosch <stephan@rename-it.nl> (1d830b2d) + + Enotify: added recipient verification and implemented proper To and Cc + header composition. + + +M TODO +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M tests/extensions/enotify/errors.svtest +M tests/extensions/enotify/errors/url-mailto.sieve + +2008-12-21 12:35:11 +0100 Stephan Bosch <stephan@rename-it.nl> (d7b2fe30) + + Enotify: forgot to add new file to the test suite. + + +A tests/extensions/enotify/errors/from-mailto.sieve + +2008-12-21 12:33:46 +0100 Stephan Bosch <stephan@rename-it.nl> (19b76ef1) + + Enotify: implemented verification of the :from address. + + +M TODO +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M tests/extensions/enotify/errors.svtest + +2008-12-21 11:38:38 +0100 Stephan Bosch <stephan@rename-it.nl> (2277d1c6) + + Enotify: made log struct name shorter. + + +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h + +2008-12-21 11:37:24 +0100 Stephan Bosch <stephan@rename-it.nl> (73ca4dbd) + + Fixed compiler warning about signed char. + + +M src/lib-sieve/rfc2822.c + +2008-12-21 02:18:51 +0100 Stephan Bosch <stephan@rename-it.nl> (9a045825) + + Enotify: corrected mailto URI error messages. + + +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2008-12-21 01:30:02 +0100 Stephan Bosch <stephan@rename-it.nl> (60e726c4) + + Enotify: cleaned up URI error handling. + + +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2008-12-21 01:08:38 +0100 Stephan Bosch <stephan@rename-it.nl> (43d53ad3) + + Enotify: shielded most of the method API from compiler internals. + + +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h + +2008-12-20 21:45:13 +0100 Stephan Bosch <stephan@rename-it.nl> (392dc84a) + + Enotify: added owner email to auto-submitted header. + + +M TODO +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2008-12-19 18:04:11 +0100 Stephan Bosch <stephan@rename-it.nl> (084ea434) + + Updated TODO. + + +M TODO + +2008-12-19 17:27:56 +0100 Stephan Bosch <stephan@rename-it.nl> (1c0ad81a) + + Small cosmetic changes to lexer sources. + + +M src/lib-sieve/sieve-lexer.c + +2008-12-19 17:20:13 +0100 Stephan Bosch <stephan@rename-it.nl> (57b1da62) + + Enotify: mailto: excluded body 'header' in URI from the header field body + verification. + + +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2008-12-19 17:06:02 +0100 Stephan Bosch <stephan@rename-it.nl> (9e32d835) + + Enotify: mailto: implemented verification of (unstructured) header field + bodies and improved URI syntax checking. + + +M TODO +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/rfc2822.c +M src/lib-sieve/rfc2822.h + +2008-12-19 16:12:57 +0100 Stephan Bosch <stephan@rename-it.nl> (87a9a696) + + Substituted mail_get_headers for mail_get_headers_utf8 for those occasions + where utf8 is of no concern. + + +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/tst-exists.c + +2008-12-19 16:07:03 +0100 Stephan Bosch <stephan@rename-it.nl> (a2968815) + + Improved result execution and prevented failure on store action on dry run + (with no specified namespace). + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c + +2008-12-19 16:06:09 +0100 Stephan Bosch <stephan@rename-it.nl> (419fec52) + + Enotify: avoided sending notifications on auto-submitted messages. + + +M TODO +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2008-12-19 10:25:46 +0100 Stephan Bosch <stephan@rename-it.nl> (d67280b3) + + Adapted to changes in the Dovecot API. + + +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-validator.c + +2008-12-18 00:23:05 +0100 Stephan Bosch <stephan@rename-it.nl> (06e78525) + + Merged concurrent changes. + + +2008-12-18 00:22:17 +0100 Stephan Bosch <stephan@rename-it.nl> (7f6dcb03) + + Updated TODO: listed what remains to be done for the enotify extension and + its mailto method. + + +M TODO + +2008-12-18 00:21:34 +0100 Stephan Bosch <stephan@rename-it.nl> (ff5efcaa) + + Updated enotify:mailto draft RFC. + + +R081 doc/rfc/draft-ietf-sieve-notify-mailto-09.txt doc/rfc/draft-ietf-sieve-notify-mailto-10.txt + +2008-12-14 20:08:47 +0100 Stephan Bosch <stephan@rename-it.nl> (d44d2500) + + Enotify: mailto: added filtering of reserved headers. + + +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2008-12-14 18:39:36 +0100 Stephan Bosch <stephan@rename-it.nl> (d3fdab9f) + + Enotify: changed notify message to match the latest draft specification + better (not yet compliant). + + +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2008-12-14 14:12:55 +0100 Stephan Bosch <stephan@rename-it.nl> (64353ac9) + + Enotify: now using new message composition functions. + + +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2008-12-14 14:12:22 +0100 Stephan Bosch <stephan@rename-it.nl> (0f4adc23) + + Fixed message typo in sieve-exec tool. + + +M src/sieve-tools/sieve-exec.c + +2008-12-14 13:51:23 +0100 Stephan Bosch <stephan@rename-it.nl> (7e21211c) + + Reject: now using new message composition functions. + + +M src/lib-sieve/ext-reject.c +M src/lib-sieve/rfc2822.c + +2008-12-14 12:59:47 +0100 Stephan Bosch <stephan@rename-it.nl> (74a29965) + + Change to configure.in caused compile error. + + +M configure.in + +2008-12-14 12:44:53 +0100 Stephan Bosch <stephan@rename-it.nl> (f8de116f) + + Fixed bug in configure script that emitted Dovecot version in config header + in stead of Sieve version. + + +M configure.in + +2008-12-14 12:40:38 +0100 Stephan Bosch <stephan@rename-it.nl> (05145e75) + + Added X-Sieve header to redirected messages. + + +M src/lib-sieve/cmd-redirect.c + +2008-12-14 11:05:36 +0100 Stephan Bosch <stephan@rename-it.nl> (8b9941f5) + + Vacation: now using new message composition functions. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2008-12-14 11:05:19 +0100 Stephan Bosch <stephan@rename-it.nl> (d2101dad) + + Created basic internet mail message composition functionality. + + +M src/lib-sieve/rfc2822.c +M src/lib-sieve/rfc2822.h + +2008-12-14 00:06:38 +0100 Stephan Bosch <stephan@rename-it.nl> (78580a2c) + + Vacation: added support for properly updating references header. + + +M Makefile.am +M TODO +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/rfc2822.c +M src/lib-sieve/rfc2822.h +A tests/extensions/vacation/references.sieve +A tests/extensions/vacation/references.svtest + +2008-12-13 20:34:04 +0100 Stephan Bosch <stephan@rename-it.nl> (7a38f1a5) + + Enotify: implemented basic notify mailto: execution. + + +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2008-12-13 18:41:20 +0100 Stephan Bosch <stephan@rename-it.nl> (7f6f9208) + + Enotify: implemented construction and printing of action object. + + +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h + +2008-12-13 18:18:57 +0100 Stephan Bosch <stephan@rename-it.nl> (33da3e49) + + Enotify: implemented runtime part. + + +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h + +2008-12-12 19:50:11 +0100 Stephan Bosch <stephan@rename-it.nl> (97450ea5) + + Enotify: restructured mailto url parsing to use arrays for the results. + + +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2008-12-12 19:40:27 +0100 Stephan Bosch <stephan@rename-it.nl> (3230382e) + + Enotify: added verification of header field names in mailto url. + + +M Makefile.am +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +A tests/extensions/enotify/errors.svtest +A tests/extensions/enotify/errors/url-mailto.sieve +A tests/extensions/enotify/errors/url.sieve + +2008-12-10 13:42:03 +0100 Stephan Bosch <stephan@rename-it.nl> (c4c589b1) + + Reject: improved message rejection log message. + + +M src/lib-sieve/ext-reject.c + +2008-12-09 19:06:27 +0100 Stephan Bosch <stephan@rename-it.nl> (25db5e1a) + + Compiler now warns about syntactically invalid header field names. + + +M TODO +M src/lib-sieve/rfc2822.c +M src/lib-sieve/rfc2822.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +A tests/compile/warnings/invalid-headers.sieve + +2008-12-09 18:20:20 +0100 Stephan Bosch <stephan@rename-it.nl> (8bc9fddf) + + Exported true and false commands to separate file. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +A src/lib-sieve/tst-truefalse.c + +2008-11-30 21:04:54 +0100 Stephan Bosch <stephan@rename-it.nl> (d55cc35f) + + Fixed bug in improved capability string composition. + + +M src/lib-sieve/sieve-extensions.c + +2008-11-30 21:02:18 +0100 Stephan Bosch <stephan@rename-it.nl> (0c039f4e) + + Enotify: further developed URI parsing. + + +M src/lib-sieve/plugins/enotify/ext-enotify-limits.h +M src/lib-sieve/plugins/enotify/ntfy-mailto.c + +2008-11-30 21:01:54 +0100 Stephan Bosch <stephan@rename-it.nl> (d59421e5) + + Added support for header verification. + + +M src/lib-sieve/Makefile.am +A src/lib-sieve/rfc2822.c +A src/lib-sieve/rfc2822.h + +2008-11-30 01:30:14 +0100 Stephan Bosch <stephan@rename-it.nl> (979b0e8e) + + Enotify: implemented coarse mailto URI parsing. + + +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M tests/extensions/enotify/basic.svtest + +2008-11-30 00:45:05 +0100 Stephan Bosch <stephan@rename-it.nl> (ef717dbc) + + Added new draft-bis version of mailto RFC to doc/rfc. + + +A doc/rfc/draft-duerst-mailto-bis-05.txt + +2008-11-30 00:25:23 +0100 Stephan Bosch <stephan@rename-it.nl> (5c6fb4d8) + + Activated unload handler for extensions. + + +M src/lib-sieve/sieve-extensions.c + +2008-11-30 00:14:45 +0100 Stephan Bosch <stephan@rename-it.nl> (041b39df) + + Enotify: implemented uri scheme verification. + + +M src/lib-sieve/plugins/enotify/Makefile.am +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +A src/lib-sieve/plugins/enotify/ext-enotify-limits.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M tests/extensions/enotify/execute.svtest + +2008-11-29 21:27:50 +0100 Stephan Bosch <stephan@rename-it.nl> (fc8896f8) + + Added unload method to extension object. + + +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-match-types.c +M src/testsuite/ext-testsuite.c + +2008-11-28 23:04:40 +0100 Stephan Bosch <stephan@rename-it.nl> (4145d299) + + Reprioritized TODO. + + +M TODO + +2008-11-26 20:50:33 +0100 Stephan Bosch <stephan@rename-it.nl> (a00f056c) + + Added tag 0.1.2 for changeset f01fe5f1e816 + + +2008-11-26 20:50:20 +0100 Stephan Bosch <stephan@rename-it.nl> (171e3bfa) + + Added tag 0.1.1 for changeset e534276ecf10 + + +2008-11-26 20:49:50 +0100 Stephan Bosch <stephan@rename-it.nl> (cf2ad5bb) + + Released v0.1.2 for Dovecot v1.2.alpha4. + + +M NEWS +M configure.in + +2008-11-26 17:14:40 +0100 Stephan Bosch <stephan@rename-it.nl> (02092823) + + Vacation: improved log message for discarded vacation response. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2008-11-26 14:35:21 +0100 Stephan Bosch <stephan@rename-it.nl> (c8d13dac) + + Fixed bug in the handling of context during result execution, which resulted + in broken redirect action. + + +M src/lib-sieve/sieve-result.c + +2008-11-25 00:03:23 +0100 Stephan Bosch <stephan@rename-it.nl> (bd9e1b23) + + Released v0.1.1 for Dovecot v1.2.alpha4. + + +M configure.in + +2008-11-24 23:38:56 +0100 Stephan Bosch <stephan@rename-it.nl> (510ee56c) + + Updated NEWS file. + + +M NEWS + +2008-11-22 15:29:29 +0100 Stephan Bosch <stephan@rename-it.nl> (13716444) + + Added registry for extension capabilities like the available notify methods + and adjusted the enotify extension accordingly. + + +M src/lib-sieve/plugins/enotify/Makefile.am +A src/lib-sieve/plugins/enotify/ext-enotify-common.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/plugins/enotify/ntfy-mailto.c +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h + +2008-11-21 23:40:14 +0100 Stephan Bosch <stephan@rename-it.nl> (671f9be3) + + Forgot to move RFC 2244 to proper place in doc/rfc. + + +R100 src/lib-sieve/plugins/comparator-i-ascii-numeric/rfc2244.txt doc/rfc/i-ascii-numeric.rfc2244.txt + +2008-11-21 23:34:40 +0100 Stephan Bosch <stephan@rename-it.nl> (be698fd0) + + Enotify: implemented :encodeurl variables modifier. + + +M Makefile.am +A doc/rfc/uri.rfc3986.txt +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +A tests/extensions/enotify/encodeurl.svtest + +2008-11-21 22:45:08 +0100 Stephan Bosch <stephan@rename-it.nl> (3d3aa53e) + + Added TODO item. + + +M TODO + +2008-11-21 19:59:00 +0100 Stephan Bosch <stephan@rename-it.nl> (7964f451) + + Adapted to changes in the mailbox_open() API. + + +M src/lib-sieve-tool/mail-raw.c +M src/lib-sieve-tool/sieve-tool.c +M src/lib-sieve/sieve-actions.c +M src/sieve-tools/sieve-exec.c +M src/sieve-tools/sieve-test.c +M src/testsuite/testsuite.c + +2008-11-20 00:54:54 +0100 Stephan Bosch <stephan@rename-it.nl> (bbe95b34) + + Merged concurrent changes. + + +2008-11-20 00:54:38 +0100 Stephan Bosch <stephan@rename-it.nl> (90f4fed4) + + Enotify: copied action implementation from old plugin. + + +A doc/rfc/mailto.rfc2368.txt +M src/lib-sieve/plugins/enotify/Makefile.am +M src/lib-sieve/plugins/enotify/cmd-notify.c +A src/lib-sieve/plugins/enotify/ntfy-mailto.c +A src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +M src/lib-sieve/plugins/enotify/vmodf-encodeurl.c + +2008-11-20 00:54:14 +0100 Stephan Bosch <stephan@rename-it.nl> (f461b22e) + + Fixed error handling of actions that send mail. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2008-11-20 00:06:58 +0100 Stephan Bosch <stephan@rename-it.nl> (0c1b149c) + + Enabled (optional) support for Valgrind in the testsuite and fixed a few + intricate bugs in the process. + + +M Makefile.am +M configure.in +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h + +2008-11-19 21:24:10 +0100 Stephan Bosch <stephan@rename-it.nl> (e58d90ca) + + Changed acquisition of usernames in sieve command line tools. + + +M src/lib-sieve-tool/sieve-tool.c + +2008-11-19 20:59:45 +0100 Stephan Bosch <stephan@rename-it.nl> (bdc8a61f) + + Testsuite: added test for header folding. + + +M tests/header.svtest + +2008-11-19 20:50:11 +0100 Stephan Bosch <stephan@rename-it.nl> (35e1b03b) + + Fixed bug in mail_raw implementation: mail_namespaces_deinit() must not be + called explicitly for v1.2. + + +M src/lib-sieve-tool/mail-raw.c + +2008-11-17 22:44:19 +0100 Stephan Bosch <stephan@rename-it.nl> (c7e0c93e) + + Previous change did not compile. + + +M src/lib-sieve/sieve-actions.c + +2008-11-17 22:38:28 +0100 Stephan Bosch <stephan@rename-it.nl> (f7c37a6b) + + Matched changes in Dovecot to properly handle/ignore the new mailbox ACL + support. + + +M src/lib-sieve/sieve-actions.c + +2008-11-16 23:31:32 +0100 Stephan Bosch <stephan@rename-it.nl> (590b593b) + + Added notify mailto draft. + + +A doc/rfc/draft-ietf-sieve-notify-mailto-09.txt + +2008-11-16 18:27:34 +0100 Stephan Bosch <stephan@rename-it.nl> (59a3a988) + + Enotify: finished skeleton by addin empty :encodeurl implementation. + + +M src/lib-sieve/plugins/enotify/Makefile.am +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +A src/lib-sieve/plugins/enotify/vmodf-encodeurl.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M tests/extensions/enotify/execute.svtest + +2008-11-16 16:28:15 +0100 Stephan Bosch <stephan@rename-it.nl> (cdcba6c7) + + Testsuite: added draft RFC examples as execution tests. + + +M Makefile.am +A tests/extensions/enotify/execute.svtest +A tests/extensions/enotify/execute/draft-rfc-ex1.sieve +A tests/extensions/enotify/execute/draft-rfc-ex2.sieve +A tests/extensions/enotify/execute/draft-rfc-ex3.sieve +A tests/extensions/enotify/execute/draft-rfc-ex5.sieve +A tests/extensions/enotify/execute/draft-rfc-ex6.sieve + +2008-11-15 01:39:24 +0100 Stephan Bosch <stephan@rename-it.nl> (913e9f17) + + Merged concurrent changes. + + +2008-11-15 01:38:37 +0100 Stephan Bosch <stephan@rename-it.nl> (3188d46e) + + Include: fixed bug in import/export commands. + + +M src/lib-sieve/plugins/include/ext-include-variables.c + +2008-11-15 00:34:43 +0100 Stephan Bosch <stephan@rename-it.nl> (1432e68b) + + Fixed small indentation error. + + +M src/lib-sieve/plugins/include/ext-include-variables.c + +2008-11-14 23:09:11 +0100 Stephan Bosch <stephan@rename-it.nl> (375100c9) + + Fixed bug in handling of non-existent scripts. + + +M src/lib-sieve/sieve-script.c + +2008-11-14 22:57:57 +0100 Stephan Bosch <stephan@rename-it.nl> (2fb5a4e3) + + Prepared NEWS file for next release. + + +M NEWS + +2008-11-14 12:34:34 +0100 Stephan Bosch <stephan@rename-it.nl> (d900c359) + + Slightly improved documentation. + + +M INSTALL +M README + +2008-11-12 17:05:48 +0100 Stephan Bosch <stephan@rename-it.nl> (e3488325) + + Imap4flags: fixed bug in the handling of the internal variable. + + Previously the final value of internal variable was for every store action + that didn't specify a :flags argument explicitly. This results in out-of + order assignment/removal of flags, e.g. also the flags assigned keep actions + that were executed before the addflag/setflag command were modified. + +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-validator.c + +2008-11-12 10:09:23 +0100 Stephan Bosch <stephan@rename-it.nl> (3415d166) + + Updated TODO. + + +M TODO + +2008-11-12 10:03:36 +0100 Stephan Bosch <stephan@rename-it.nl> (b970b8c7) + + Removed man page issue from README file. + + +M README + +2008-11-12 00:17:36 +0100 Stephan Bosch <stephan@rename-it.nl> (d48d3b68) + + Updated README. + + +M README + +2008-11-12 00:06:35 +0100 Stephan Bosch <stephan@rename-it.nl> (a604dd72) + + Created man page for the sieve-test command. + + +M Makefile.am +A doc/man/sieve-test.1 + +2008-11-11 23:12:34 +0100 Stephan Bosch <stephan@rename-it.nl> (5a9e7203) + + Created man page for the sieved command. + + +M Makefile.am +A doc/man/sieved.1 + +2008-11-11 22:11:40 +0100 Stephan Bosch <stephan@rename-it.nl> (9002e1d9) + + Enabled installation of man pages. + + +M Makefile.am + +2008-11-11 22:11:18 +0100 Stephan Bosch <stephan@rename-it.nl> (9c9ffe38) + + Forgot to add new sieve-config.h to the distribution. + + +M src/lib-sieve/Makefile.am + +2008-11-11 21:28:37 +0100 Stephan Bosch <stephan@rename-it.nl> (e0d9b467) + + Created (currently uninstalled) man page for the sievec command. + + +A doc/man/sievec.1 + +2008-11-11 11:23:21 +0100 Stephan Bosch <stephan@rename-it.nl> (8e9c34fc) + + Testsuite: fail with informative error if compiled against dovecot headers + only. + + +M Makefile.am + +2008-11-11 00:34:31 +0100 Stephan Bosch <stephan@rename-it.nl> (c922e57a) + + Re-enabled support for compiling against Dovecot headers. + + +M configure.in +M src/Makefile.am + +2008-11-10 08:18:09 +0100 Stephan Bosch <stephan@rename-it.nl> (2917405f) + + Enotify: added skeleton implementation of notify_method_capability test. + + +M src/lib-sieve/plugins/enotify/Makefile.am +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +A src/lib-sieve/plugins/enotify/tst-notify-method-capability.c + +2008-11-09 22:57:52 +0100 Stephan Bosch <stephan@rename-it.nl> (bd8d2804) + + Enotify: added skeleton implementation of valid_notify_method test. + + +M src/lib-sieve/plugins/enotify/Makefile.am +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +A src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +M tests/extensions/enotify/basic.svtest + +2008-11-07 21:17:06 +0100 Stephan Bosch <stephan@rename-it.nl> (234a0f8b) + + Enotify: implemented skeleton for the notify command. + + +M Makefile.am +M src/lib-sieve/plugins/enotify/cmd-notify.c +M src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +A tests/extensions/enotify/basic.svtest + +2008-11-02 23:29:00 +0100 Stephan Bosch <stephan@rename-it.nl> (2dc98704) + + ENotify: activated empty implementation. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/sieve-extensions.c + +2008-11-02 22:52:30 +0100 Stephan Bosch <stephan@rename-it.nl> (94af6350) + + Started using autoconf output. + + +M .hgignore +M configure.in +A dsieve-config.h.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/sieve-common.h +A src/lib-sieve/sieve-config.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.h + +2008-11-02 11:36:28 +0100 Stephan Bosch <stephan@rename-it.nl> (e18b475b) + + Added UTF-8 to modified UTF-7 folder name conversion for compatibility with + IMAP. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/sieve-actions.h + +2008-11-02 11:30:46 +0100 Stephan Bosch <stephan@rename-it.nl> (76eb6954) + + Accidentally added binaries for sieve tools. + + +M .hgignore +D src/sieve-tools/sieve-exec +D src/sieve-tools/sieve-test +D src/sieve-tools/sievec +D src/sieve-tools/sieved + +2008-11-01 23:03:04 +0100 Stephan Bosch <stephan@rename-it.nl> (38f98623) + + Enotify: built skeleton for the notify command. + + +A doc/rfc/draft-ietf-sieve-notify-12.txt +M src/lib-sieve/plugins/enotify/Makefile.am +A src/lib-sieve/plugins/enotify/cmd-notify.c +A src/lib-sieve/plugins/enotify/ext-enotify-common.h +M src/lib-sieve/plugins/enotify/ext-enotify.c + +2008-11-01 20:48:57 +0100 Stephan Bosch <stephan@rename-it.nl> (7b531076) + + Removed code duplication between testsuite and commandline tools. Also + restructured source code of the tools. + + +M README +M TODO +M configure.in +M src/Makefile.am +A src/lib-sieve-tool/Makefile.am +R100 src/lib-util/mail-raw.c src/lib-sieve-tool/mail-raw.c +R100 src/lib-util/mail-raw.h src/lib-sieve-tool/mail-raw.h +R075 src/sieve-bin/bin-common.c src/lib-sieve-tool/sieve-tool.c +A src/lib-sieve-tool/sieve-tool.h +D src/lib-util/Makefile.am +D src/sieve-bin/bin-common.h +R085 src/sieve-bin/Makefile.am src/sieve-tools/Makefile.am +A src/sieve-tools/sieve-exec +R091 src/sieve-bin/sieve-exec.c src/sieve-tools/sieve-exec.c +A src/sieve-tools/sieve-test +R093 src/sieve-bin/sieve-test.c src/sieve-tools/sieve-test.c +A src/sieve-tools/sievec +R088 src/sieve-bin/sievec.c src/sieve-tools/sievec.c +A src/sieve-tools/sieved +R078 src/sieve-bin/sieved.c src/sieve-tools/sieved.c +M src/testsuite/Makefile.am +M src/testsuite/testsuite.c + +2008-10-30 23:41:22 +0100 Stephan Bosch <stephan@rename-it.nl> (501216f5) + + Removed now obsolete namespaces.c/h from testsuite and commandline tools. + + +M src/sieve-bin/Makefile.am +D src/sieve-bin/namespaces.c +D src/sieve-bin/namespaces.h +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c +M src/testsuite/Makefile.am +D src/testsuite/namespaces.c +D src/testsuite/namespaces.h +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite.c + +2008-10-30 23:05:38 +0100 Stephan Bosch <stephan@rename-it.nl> (bcd3ad56) + + Enabled all available mail storage types (those compiled in Dovecot) for the + commandline tools and the testsuite. + + +M src/sieve-bin/Makefile.am +M src/sieve-bin/namespaces.c +M src/testsuite/Makefile.am +M src/testsuite/namespaces.c + +2008-10-30 22:30:17 +0100 Stephan Bosch <stephan@rename-it.nl> (078fda7e) + + Merged mail-raw implementations of sieve commandline tools and the + testsuite, thus removing duplicate code. + + +M configure.in +M src/Makefile.am +A src/lib-util/Makefile.am +R076 src/sieve-bin/mail-raw.c src/lib-util/mail-raw.c +R079 src/sieve-bin/mail-raw.h src/lib-util/mail-raw.h +M src/sieve-bin/Makefile.am +M src/sieve-bin/bin-common.c +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c +M src/testsuite/Makefile.am +D src/testsuite/mail-raw.c +D src/testsuite/mail-raw.h +M src/testsuite/testsuite-common.c + +2008-10-30 20:07:36 +0100 Stephan Bosch <stephan@rename-it.nl> (c67ac6db) + + Made lda plugin properly refer to the main script as 'main script' and not + the basename of the sieve file (which is of no interest to the user for the + main script). + + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-bin/bin-common.c + +2008-10-30 19:49:53 +0100 Stephan Bosch <stephan@rename-it.nl> (ec8fc9f2) + + Improved logging of failed script load. + + +M src/lib-sieve/sieve-script.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2008-10-29 23:49:47 +0100 Stephan Bosch <stephan@rename-it.nl> (4b214656) + + Now using folder name as specified by user in log messages in stead of + internal representation. + + +M src/lib-sieve/sieve-actions.c + +2008-10-29 21:26:08 +0100 Stephan Bosch <stephan@rename-it.nl> (3434e90d) + + Added mail_debug messages to plugin to find problems in the sieve path + specification more easily. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2008-10-29 01:26:25 +0100 Stephan Bosch <stephan@rename-it.nl> (69b33e90) + + Added TODO item. + + +M TODO + +2008-10-29 01:13:22 +0100 Stephan Bosch <stephan@rename-it.nl> (2adb6a61) + + Command sievec -d always wrote to std out. + + +M src/sieve-bin/sievec.c + +2008-10-29 01:12:44 +0100 Stephan Bosch <stephan@rename-it.nl> (ec932428) + + Fixed missing mask argument in two open calls (bug found by Sergey Ivanov). + + +M src/sieve-bin/bin-common.c +M src/testsuite/testsuite.c + +2008-10-25 20:27:14 +0200 Stephan Bosch <stephan@rename-it.nl> (64869811) + + Started development of enotify extension. + + +M configure.in +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/enotify/Makefile.am +A src/lib-sieve/plugins/enotify/ext-enotify.c + +2008-10-23 20:11:15 +0200 Stephan Bosch <stephan@rename-it.nl> (1f81f1d2) + + Added tag 0.1.0 for changeset 065c12acdcc0 + + +2008-10-23 20:08:52 +0200 Stephan Bosch <stephan@rename-it.nl> (f7270d1e) + + Released v0.1.0 for Dovecot v1.2.alpha3. + + +M TODO +M configure.in + +2008-10-23 19:44:57 +0200 Stephan Bosch <stephan@rename-it.nl> (419330a9) + + Minor revisions to the package documentation. + + +M AUTHORS +M NEWS +M README + +2008-10-22 20:26:59 +0200 Stephan Bosch <stephan@rename-it.nl> (27a05dc9) + + Fixed warning caused by mixup between mail_storage and sieve_storage. + + +M src/lib-sieve/sieve-types.h + +2008-10-22 16:10:13 +0200 Stephan Bosch <stephan@rename-it.nl> (057f6ea1) + + Improved execution of store action. + + +M src/lib-sieve/sieve-actions.c + +2008-10-21 21:49:14 +0200 Stephan Bosch <stephan@rename-it.nl> (cf5025c7) + + Properly set storage_r in plugin function to prevent double errors. + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-types.h +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2008-10-20 02:13:27 +0200 Stephan Bosch <stephan@rename-it.nl> (ff2b8ffd) + + Prevented transaction context from becoming NULL in execution of store + action. + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-result.c + +2008-10-20 01:57:36 +0200 Stephan Bosch <stephan@rename-it.nl> (7e6a0ecc) + + Fixed context handling bug in the result execution. + + +M src/lib-sieve/sieve-result.c + +2008-10-19 18:35:17 +0200 Stephan Bosch <stephan@rename-it.nl> (c459d469) + + Clarified errors occurring when colon is missing. + + +M src/lib-sieve/sieve-validator.c +M tests/compile/errors.svtest +A tests/compile/errors/typos.sieve + +2008-10-19 17:56:01 +0200 Stephan Bosch <stephan@rename-it.nl> (71fa5a02) + + Corrected error message. + + +M src/lib-sieve/sieve-validator.c +M tests/compile/errors.svtest + +2008-10-19 17:47:49 +0200 Stephan Bosch <stephan@rename-it.nl> (6564cc41) + + Clarified error messages for missing semicolon. + + +M README +M src/lib-sieve/sieve-validator.c +M tests/compile/errors.svtest + +2008-10-19 16:46:12 +0200 Stephan Bosch <stephan@rename-it.nl> (11f12b4d) + + Repaired 'make dist' tarball output. + + +M Makefile.am +M src/lib-sieve/plugins/body/Makefile.am +D src/lib-sieve/plugins/body/body.sieve +M src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.am +D src/lib-sieve/plugins/comparator-i-ascii-numeric/cmp-i-ascii-numeric.sieve +M src/lib-sieve/plugins/copy/Makefile.am +D src/lib-sieve/plugins/copy/copy.sieve +M src/lib-sieve/plugins/imapflags/Makefile.am +D src/lib-sieve/plugins/imapflags/imapflags-2.sieve +D src/lib-sieve/plugins/imapflags/imapflags-errors.sieve +D src/lib-sieve/plugins/imapflags/imapflags-implicit.sieve +D src/lib-sieve/plugins/imapflags/imapflags-variables.sieve +D src/lib-sieve/plugins/imapflags/imapflags.sieve +M src/lib-sieve/plugins/regex/Makefile.am +M src/lib-sieve/plugins/relational/Makefile.am +D src/lib-sieve/plugins/relational/relational.sieve +M src/lib-sieve/plugins/subaddress/Makefile.am +D src/lib-sieve/plugins/subaddress/subaddress.sieve +M src/lib-sieve/plugins/vacation/Makefile.am +D src/lib-sieve/plugins/vacation/vacation-errors.sieve +D src/lib-sieve/plugins/vacation/vacation.sieve +M src/lib-sieve/plugins/variables/Makefile.am +D src/lib-sieve/plugins/variables/variables-errors.sieve +D src/lib-sieve/plugins/variables/variables-match.sieve +D src/lib-sieve/plugins/variables/variables-nspace.sieve +D src/lib-sieve/plugins/variables/variables-regex.sieve +D src/lib-sieve/plugins/variables/variables.sieve +M src/testsuite/Makefile.am + +2008-10-19 15:48:14 +0200 Stephan Bosch <stephan@rename-it.nl> (4fc62256) + + Revised README. + + +M INSTALL +M README +M configure.in + +2008-10-19 15:19:54 +0200 Stephan Bosch <stephan@rename-it.nl> (599d9b5b) + + Testsuite: added support for basic result checking. + + +M TODO +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/testsuite/Makefile.am +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +A src/testsuite/testsuite-result.c +A src/testsuite/testsuite-result.h +M src/testsuite/tst-test-error.c +A src/testsuite/tst-test-result.c +M tests/execute/actions.svtest +M tests/execute/actions/fileinto.sieve +M tests/execute/actions/redirect.sieve +M tests/extensions/reject/execute.svtest +M tests/extensions/vacation/execute.svtest +A tests/extensions/vacation/execute/action.sieve + +2008-10-19 12:36:31 +0200 Stephan Bosch <stephan@rename-it.nl> (98bd2cc5) + + Reported RFC questions to the ietf-mta-filters mailinglist. + + +M TODO +D doc/rfc/RFC Controversy.txt +A doc/rfc/RFC-questions.txt + +2008-10-19 11:58:33 +0200 Stephan Bosch <stephan@rename-it.nl> (7b83caf1) + + Added explicit messages and tests for unsupported use of variables. + + +M TODO +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/sieve-comparators.c +M tests/compile/errors.svtest +A tests/compile/errors/unsupported.sieve + +2008-10-12 12:45:10 +0200 Stephan Bosch <stephan@rename-it.nl> (3a8746c9) + + Updated TODO. + + +M TODO + +2008-10-12 12:43:34 +0200 Stephan Bosch <stephan@rename-it.nl> (76534ffd) + + Fixed TODO: made sure main scope used in variables dumping is unreferenced + when code dumper is freed. + + +M TODO +M src/lib-sieve/plugins/variables/ext-variables-dump.c + +2008-10-12 12:17:30 +0200 Stephan Bosch <stephan@rename-it.nl> (830d93e4) + + Tested replacing cmusieve with sieve. + + +M TODO + +2008-10-12 00:24:32 +0200 Stephan Bosch <stephan@rename-it.nl> (d5f36c0c) + + Function t_str_new_const got moved to its proper place in Dovecot. + + +M src/lib-sieve/sieve-binary.c + +2008-10-11 23:36:32 +0200 Stephan Bosch <stephan@rename-it.nl> (e2873f16) + + Added extension support to code dumper. + + +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h + +2008-10-11 23:13:16 +0200 Stephan Bosch <stephan@rename-it.nl> (d04c3011) + + Removed/solved minor TODOs. + + +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-parser.c + +2008-10-11 22:21:35 +0200 Stephan Bosch <stephan@rename-it.nl> (f2a05b1c) + + Merged concurrent changes. + + +2008-10-11 22:07:06 +0200 Stephan Bosch <stephan@rename-it.nl> (1445fd34) + + Variables/Include: added support for dumping variables declared in extension + scopes. + + +M TODO +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2008-10-09 23:24:54 +0200 Stephan Bosch <stephan@rename-it.nl> (5ddf67da) + + Fixed amd64 logging segfault; turns out using same va_args in multiple + vprintf calls is not possible. + + +M TODO +M src/lib-sieve/sieve-error.c + +2008-10-05 19:44:51 +0200 Stephan Bosch <stephan@rename-it.nl> (631fb839) + + Added support for mailbox autocreate and autosubscribe. + + +M src/lib-sieve/sieve-actions.c + +2008-10-05 19:14:43 +0200 Stephan Bosch <stephan@rename-it.nl> (2a983ad8) + + Made plugin use tried_default_save indicator to prevent duplicate error + messages. + + +M TODO +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite.c + +2008-10-04 10:41:52 +0200 Stephan Bosch <stephan@rename-it.nl> (dc75895b) + + Updated TODO. + + +M TODO + +2008-09-28 21:24:25 +0200 Stephan Bosch <stephan@rename-it.nl> (6127ac70) + + Variables: added identifier dump support for main scope. + + +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-dump.c +M src/lib-sieve/plugins/variables/ext-variables-dump.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h + +2008-09-18 17:46:46 +0200 Stephan Bosch <stephan@rename-it.nl> (cf568449) + + Variables: added dumptime context. + + +M src/lib-sieve/plugins/variables/Makefile.am +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +A src/lib-sieve/plugins/variables/ext-variables-dump.c +A src/lib-sieve/plugins/variables/ext-variables-dump.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h + +2008-09-15 16:10:57 +0200 Stephan Bosch <stephan@rename-it.nl> (546f6cce) + + Merged concurrent changes. + + +2008-09-14 21:06:44 +0200 Stephan Bosch <stephan@rename-it.nl> (960ab63b) + + Started NEWS file. + + +M NEWS + +2008-09-14 21:05:45 +0200 Stephan Bosch <stephan@rename-it.nl> (13acebb5) + + Moved design description to doc/devel directory. + + +M Makefile.am +R100 DESIGN doc/devel/DESIGN + +2008-09-14 21:02:29 +0200 Stephan Bosch <stephan@rename-it.nl> (ba5c8551) + + Restructured Sieve example scripts. + + +M README +R100 sieve/examples/elvey.sieve examples/elvey.sieve +R100 sieve/examples/jerry.sieve examples/jerry.sieve +R100 sieve/examples/mjohnson.sieve examples/mjohnson.sieve +R100 sieve/examples/mklose.sieve examples/mklose.sieve +R100 sieve/examples/relational.rfc5231.sieve examples/relational.rfc5231.sieve +R100 sieve/examples/rfc3028.sieve examples/rfc3028.sieve +R100 sieve/examples/sanjay.sieve examples/sanjay.sieve +R100 sieve/examples/sieve_examples.sieve examples/sieve_examples.sieve +R100 sieve/examples/subaddress.rfc5233.sieve examples/subaddress.rfc5233.sieve +R100 sieve/examples/vacation.sieve examples/vacation.sieve +R100 sieve/examples/vivil.sieve examples/vivil.sieve +D sieve/tests/actions.sieve +D sieve/tests/address-part.sieve +D sieve/tests/basic.sieve +D sieve/tests/comparator.sieve +D sieve/tests/encoded-character.sieve +D sieve/tests/envelope.sieve +D sieve/tests/extensions.sieve +D sieve/tests/if.sieve +D sieve/tests/match-type.sieve +D sieve/tests/matches.sieve +D sieve/tests/stop.sieve +D sieve/tests/vacation.sieve +M tests/compile/examples.svtest + +2008-09-14 20:54:05 +0200 Stephan Bosch <stephan@rename-it.nl> (632ffdc2) + + Testsuite: added execution tests for core actions (to find segfaults). + + +M Makefile.am +A tests/execute/actions.svtest +R100 sieve/tests/fileinto.sieve tests/execute/actions/fileinto.sieve +R100 sieve/tests/redirect.sieve tests/execute/actions/redirect.sieve +M tests/extensions/reject/execute.svtest + +2008-09-14 20:42:14 +0200 Stephan Bosch <stephan@rename-it.nl> (f6d0011c) + + Testsuite: added trivial reject action execution test. + + +M Makefile.am +A tests/extensions/reject/execute.svtest +R100 sieve/tests/reject.sieve tests/extensions/reject/execute/basic.sieve + +2008-09-13 13:12:31 +0200 Stephan Bosch <stephan@rename-it.nl> (fe47287a) + + Testsuite: added final existing error tests. + + +D sieve/errors/address-errors.sieve +D sieve/errors/address-part-errors.sieve +D sieve/errors/encoded-character.sieve +D sieve/errors/envelope-errors.sieve +D sieve/errors/header-errors.sieve +D sieve/errors/if-errors.sieve +D sieve/errors/interesting.sieve +D sieve/errors/keep-errors.sieve +D sieve/errors/parse-errors.sieve +D sieve/errors/require-errors.sieve +D sieve/errors/size-errors.sieve +D sieve/errors/stop-errors.sieve +D sieve/errors/tag-errors.sieve +M tests/compile/errors.svtest +R100 sieve/errors/out-address-errors.sieve tests/compile/errors/out-address.sieve +A tests/compile/errors/tag.sieve + +2008-09-13 13:01:50 +0200 Stephan Bosch <stephan@rename-it.nl> (3e5d9e87) + + Improved README to be more readable. + + +M README + +2008-09-12 17:49:45 +0200 Stephan Bosch <stephan@rename-it.nl> (d3040380) + + Removed useless PTR_OFFSET from logfile error handler implementation. + + +M src/lib-sieve/sieve-error.c + +2008-09-12 16:55:55 +0200 Stephan Bosch <stephan@rename-it.nl> (40b09103) + + Added pre-release TODO item. + + +M TODO + +2008-09-12 16:55:07 +0200 Stephan Bosch <stephan@rename-it.nl> (6032e179) + + Improved argument error reporting. + + +M TODO +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/include/cmd-import.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-size.c +M src/testsuite/testsuite-objects.c + +2008-09-12 15:27:26 +0200 Stephan Bosch <stephan@rename-it.nl> (b40b9a03) + + Restructured error reporting in validator and code generator. + + +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h + +2008-09-12 12:06:46 +0200 Stephan Bosch <stephan@rename-it.nl> (441c0cf4) + + Fixed new ia64 warnings. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/tst-size.c +M src/testsuite/tst-test-error.c + +2008-09-12 11:56:12 +0200 Stephan Bosch <stephan@rename-it.nl> (923f1d9f) + + Fixed new ia64 warnings in sieve-code. + + +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h + +2008-09-12 11:36:42 +0200 Stephan Bosch <stephan@rename-it.nl> (68ee3d06) + + Fixed new ia64 warnings in sieve-code. + + +M src/lib-sieve/sieve-code.h + +2008-09-12 11:29:39 +0200 Stephan Bosch <stephan@rename-it.nl> (c6cce133) + + Fixed ia64 warnings in sieve-code. + + +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h + +2008-09-12 11:17:04 +0200 Stephan Bosch <stephan@rename-it.nl> (5ff0ca84) + + Variables: fixed ia64 compiler warnings. + + +M src/lib-sieve/plugins/variables/ext-variables-arguments.c + +2008-09-12 01:53:02 +0200 Stephan Bosch <stephan@rename-it.nl> (dd1e90bd) + + Forgot to handle return value of o_stream_send in logfile error hander + implementation. + + +M src/lib-sieve/sieve-error.c + +2008-09-12 01:42:32 +0200 Stephan Bosch <stephan@rename-it.nl> (7efd8493) + + Forgot O_TRUNC in logfile error handler's second logfile open() call. + + +M src/lib-sieve/sieve-error.c + +2008-09-12 01:39:22 +0200 Stephan Bosch <stephan@rename-it.nl> (71b15ea8) + + Include: improved trace verbosity for import command. + + +M src/lib-sieve/plugins/include/cmd-import.c + +2008-09-12 01:33:47 +0200 Stephan Bosch <stephan@rename-it.nl> (8e04ea9b) + + Hopefully resolved various type cast warnings surfacing on ia_64 and not on + i386. + + +M src/lib-sieve/plugins/include/cmd-import.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-interpreter.c + +2008-09-12 00:23:02 +0200 Stephan Bosch <stephan@rename-it.nl> (d7df5723) + + Testsuite: added address test case for specific strange situation. + + +M tests/address.svtest + +2008-09-12 00:14:54 +0200 Stephan Bosch <stephan@rename-it.nl> (99fbcb16) + + Relational: fixed portability issue in count match type (warning). + + +M src/lib-sieve/plugins/relational/mcht-count.c + +2008-09-10 00:12:11 +0200 Stephan Bosch <stephan@rename-it.nl> (2ed474f1) + + Updated documentation. + + +M README + +2008-09-10 00:07:44 +0200 Stephan Bosch <stephan@rename-it.nl> (41236087) + + Devised simple log rotation to prevent per-user sieve processing logs to + grow indefinitely. + + +M TODO +M src/lib-sieve/sieve-error.c + +2008-09-09 23:36:22 +0200 Stephan Bosch <stephan@rename-it.nl> (c6edfbd3) + + Updated TODO list. + + +M TODO + +2008-09-09 21:52:49 +0200 Stephan Bosch <stephan@rename-it.nl> (5d7ae356) + + Improved byte code dumping to be more readable. + + +M TODO +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/testsuite-objects.c +M src/testsuite/tst-test-compile.c +M src/testsuite/tst-test-error.c + +2008-09-09 20:37:28 +0200 Stephan Bosch <stephan@rename-it.nl> (5ac2b5d0) + + Updated TODO file. + + +M TODO + +2008-09-07 23:51:20 +0200 Stephan Bosch <stephan@rename-it.nl> (c2aa6250) + + Updated documentation. + + +M INSTALL +M README +M TODO + +2008-09-07 23:44:09 +0200 Stephan Bosch <stephan@rename-it.nl> (f1a46b60) + + Removed redundant security issue listed in TODO. + + +M TODO + +2008-09-07 23:43:33 +0200 Stephan Bosch <stephan@rename-it.nl> (a3bd699e) + + Resolved handling of invalid addresses in headers for the most part. + + +M Makefile.am +M TODO +M src/lib-sieve/mcht-is.c +M src/lib-sieve/sieve-address-parts.c +A tests/address.svtest + +2008-09-07 15:41:59 +0200 Stephan Bosch <stephan@rename-it.nl> (f6e23af1) + + Variables: made sure broken/malicious binary cannot allocate variable + storage of arbitrary size. + + +M TODO +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2008-09-07 15:13:26 +0200 Stephan Bosch <stephan@rename-it.nl> (d1e1d88e) + + Variables: added coding of variable scope. + + +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/variables/ext-variables-common.c + +2008-09-07 14:00:27 +0200 Stephan Bosch <stephan@rename-it.nl> (4f576f76) + + Added support for per-script extension intialization. + + +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-match-types.c +M src/testsuite/ext-testsuite.c + +2008-09-06 13:54:10 +0200 Stephan Bosch <stephan@rename-it.nl> (90c44cdc) + + Reduced the severity of the warning indicating the experimental nature of + this implementation. + + +M INSTALL +M README + +2008-09-06 13:48:31 +0200 Stephan Bosch <stephan@rename-it.nl> (b27ff823) + + Updated TODO. + + +M TODO + +2008-08-31 22:10:21 +0200 Stephan Bosch <stephan@rename-it.nl> (fe7db221) + + Minor cosmetic change to code dumping. + + +M src/lib-sieve/sieve-code-dumper.c + +2008-08-31 22:07:20 +0200 Stephan Bosch <stephan@rename-it.nl> (acf33c8b) + + Added the concept of a script code header to list the extensions actually + used by a script (was using all extensions listed in the binary). + + +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite.c + +2008-08-31 19:09:46 +0200 Stephan Bosch <stephan@rename-it.nl> (3be89fef) + + Revised implementation of the require command. + + +M src/lib-sieve/cmd-require.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-validator.c + +2008-08-31 16:52:55 +0200 Stephan Bosch <stephan@rename-it.nl> (7c41ad4c) + + Vacation: properly implemented handling of variables vs. handle generation. + + +M Makefile.am +M TODO +M src/lib-sieve/plugins/vacation/cmd-vacation.c +A tests/extensions/vacation/execute.svtest +A tests/extensions/vacation/execute/no-handle.sieve + +2008-08-31 16:52:23 +0200 Stephan Bosch <stephan@rename-it.nl> (45e617d9) + + Forgot to add niet testsuite files. + + +A tests/extensions/imapflags/execute.svtest +A tests/extensions/imapflags/execute/flags-side-effect.sieve + +2008-08-31 16:08:02 +0200 Stephan Bosch <stephan@rename-it.nl> (dc61b367) + + Added support for runtime detection of variable strings. + + +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h + +2008-08-31 15:56:09 +0200 Stephan Bosch <stephan@rename-it.nl> (66e546f2) + + Updated TODO. + + +M TODO + +2008-08-31 15:43:23 +0200 Stephan Bosch <stephan@rename-it.nl> (7e424263) + + Imapflags: properly implemented handling of duplicate store actions with + different :flags. + + +M Makefile.am +M TODO +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-result.c + +2008-08-30 15:34:27 +0200 Stephan Bosch <stephan@rename-it.nl> (afc00f9f) + + Fixed assertion triggered at the end when redirect was executed before. + + +M src/lib-sieve/cmd-redirect.c + +2008-08-30 15:22:33 +0200 Stephan Bosch <stephan@rename-it.nl> (395def89) + + Incorporated changes in deliver into the mail-raw implementation of the + sieve tools. + + +M src/sieve-bin/mail-raw.c +M src/sieve-bin/mail-raw.h +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c + +2008-08-26 22:40:03 +0200 Stephan Bosch <stephan@rename-it.nl> (4b052f04) + + Imapflags: Added FIXME. + + +M TODO +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c + +2008-08-26 22:11:29 +0200 Stephan Bosch <stephan@rename-it.nl> (51030fce) + + Implemented policy limit on the maximum number of redirect actions in a + result. + + +M TODO +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M tests/execute/errors.svtest +M tests/execute/errors/actions-limit.sieve +A tests/execute/errors/redirect-limit.sieve + +2008-08-26 21:36:59 +0200 Stephan Bosch <stephan@rename-it.nl> (987e8c52) + + Implemented limit on the number of actions active simultaneously. + + +M src/lib-sieve/Makefile.am +A src/lib-sieve/sieve-limits.c +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-result.c +M tests/execute/errors.svtest +A tests/execute/errors/actions-limit.sieve + +2008-08-26 20:36:39 +0200 Stephan Bosch <stephan@rename-it.nl> (3d88888a) + + Include: fixed a stupid bug triggered when variables are not used. + + +M src/lib-sieve/plugins/variables/ext-variables-common.c +A tests/extensions/include/errors/action-conflicts.sieve +A tests/extensions/include/errors/included/action-fileinto.sieve +A tests/extensions/include/errors/included/action-reject.sieve +D tests/extensions/include/errors/runtime.sieve + +2008-08-26 20:04:22 +0200 Stephan Bosch <stephan@rename-it.nl> (6011d823) + + Testsuite: activated runtime tests for the include extension. + + +M tests/extensions/include/errors.svtest + +2008-08-26 19:52:25 +0200 Stephan Bosch <stephan@rename-it.nl> (a97f7c97) + + Testsuite: added runtime error tests for vacation extension. + + +M Makefile.am +A tests/extensions/vacation/errors.svtest +A tests/extensions/vacation/errors/conflict-reject.sieve + +2008-08-26 17:04:27 +0200 Stephan Bosch <stephan@rename-it.nl> (7170fd88) + + Testsuite: added simple runtime action conflict tests. + + +M Makefile.am +A tests/execute/errors.svtest +R050 tests/execute/errors/action-conflicts.sieve tests/execute/errors/conflict-reject-fileinto.sieve +A tests/execute/errors/conflict-reject-keep.sieve +A tests/execute/errors/conflict-reject-redirect.sieve + +2008-08-26 17:02:38 +0200 Stephan Bosch <stephan@rename-it.nl> (abae653f) + + Installed refuse-reject draft RFC in doc/rfc directory. + + +A doc/rfc/draft-ietf-sieve-refuse-reject-07.txt + +2008-08-25 17:50:51 +0200 Stephan Bosch <stephan@rename-it.nl> (cf7d2f83) + + Testsuite: added support for testing runtime errors. + + +M src/lib-sieve/sieve-interpreter.c +M src/testsuite/Makefile.am +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite.c +A src/testsuite/tst-test-execute.c +R061 sieve/errors/action-conflicts.sieve tests/execute/errors/action-conflicts.sieve +R100 sieve/errors/action-duplicates.sieve tests/execute/errors/action-duplicates.sieve + +2008-08-25 13:25:19 +0200 Stephan Bosch <stephan@rename-it.nl> (682dfe3d) + + Vacation: discovered and partially fixed various RFC-related issues. + + +M TODO +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h + +2008-08-25 12:41:30 +0200 Stephan Bosch <stephan@rename-it.nl> (7db9c846) + + Installed new RFC for vacation extension in doc/rfc directory. + + +R069 src/lib-sieve/plugins/vacation/draft-ietf-sieve-vacation-07.txt doc/rfc/vacation.rfc5230.txt +M src/lib-sieve/plugins/vacation/ext-vacation.c + +2008-08-25 12:30:17 +0200 Stephan Bosch <stephan@rename-it.nl> (4c312848) + + Updated TODO. + + +M TODO + +2008-08-25 12:28:52 +0200 Stephan Bosch <stephan@rename-it.nl> (e24042e2) + + Finished code cleanup for now. + + +M TODO +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/ext-testsuite.c +M src/testsuite/mail-raw.c +M src/testsuite/mail-raw.h +M src/testsuite/namespaces.c +M src/testsuite/namespaces.h +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h +M src/testsuite/testsuite.c +M src/testsuite/tst-test-compile.c +M src/testsuite/tst-test-error.c + +2008-08-25 12:15:46 +0200 Stephan Bosch <stephan@rename-it.nl> (badedb46) + + Cleaned up Sieve tools. + + +M src/sieve-bin/bin-common.c +M src/sieve-bin/bin-common.h +M src/sieve-bin/mail-raw.c +M src/sieve-bin/mail-raw.h +M src/sieve-bin/namespaces.c +M src/sieve-bin/namespaces.h +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c +M src/sieve-bin/sievec.c +M src/sieve-bin/sieved.c + +2008-08-25 12:01:35 +0200 Stephan Bosch <stephan@rename-it.nl> (a56cf623) + + Cleaned up LDA Sieve plugin. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/plugins/lda-sieve/lda-sieve-plugin.h + +2008-08-25 11:55:55 +0200 Stephan Bosch <stephan@rename-it.nl> (c4123b21) + + Cleaned up variables extension. + + +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.h +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-limits.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-name.c +M src/lib-sieve/plugins/variables/ext-variables-name.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c + +2008-08-25 11:23:47 +0200 Stephan Bosch <stephan@rename-it.nl> (d346afab) + + Vacation: removed useless duplicate_mark call. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c + +2008-08-25 11:13:19 +0200 Stephan Bosch <stephan@rename-it.nl> (39c91487) + + Cleaned up vacation extension. + + +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/lib-sieve/plugins/vacation/ext-vacation.c + +2008-08-18 00:05:57 +0200 Stephan Bosch <stephan@rename-it.nl> (b023088a) + + Testsuite: extended tests for the subaddress extension. + + +M Makefile.am +A sieve/examples/subaddress.rfc5233.sieve +M tests/compile/examples.svtest +R100 tests/address-parts/subaddress.svtest tests/extensions/subaddress/basic.svtest +A tests/extensions/subaddress/rfc.svtest + +2008-08-17 23:46:10 +0200 Stephan Bosch <stephan@rename-it.nl> (fa36892b) + + Installed new subaddress RFC in doc/rfc directory. + + +A doc/rfc/subaddress.rfc5233.txt +D src/lib-sieve/plugins/subaddress/rfc3598.txt + +2008-08-17 23:44:02 +0200 Stephan Bosch <stephan@rename-it.nl> (c2d12799) + + Cleaned up subaddress extension. + + +M src/lib-sieve/plugins/subaddress/ext-subaddress.c + +2008-08-17 23:37:10 +0200 Stephan Bosch <stephan@rename-it.nl> (16553960) + + Testsuite: restructured and extended tests for the relational extension. + + +M Makefile.am +A sieve/examples/relational.rfc5231.sieve +R086 tests/compile/compile-examples.svtest tests/compile/examples.svtest +R100 tests/match-types/relational.svtest tests/extensions/relational/basic.svtest +A tests/extensions/relational/errors.svtest +A tests/extensions/relational/errors/validation.sieve +A tests/extensions/relational/rfc.svtest + +2008-08-17 23:09:25 +0200 Stephan Bosch <stephan@rename-it.nl> (969153d7) + + Installed new relational RFC in doc/rfc directory. + + +A doc/rfc/relational.rfc5231.txt +D src/lib-sieve/plugins/relational/rfc3431.txt + +2008-08-17 23:03:21 +0200 Stephan Bosch <stephan@rename-it.nl> (60278d79) + + Cleaned up relational extension. + + +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c + +2008-08-17 22:54:18 +0200 Stephan Bosch <stephan@rename-it.nl> (0031692b) + + Cleaned up regex extension. + + +M src/lib-sieve/plugins/regex/ext-regex-common.c +M src/lib-sieve/plugins/regex/ext-regex-common.h +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/mcht-regex.c + +2008-08-17 22:41:33 +0200 Stephan Bosch <stephan@rename-it.nl> (78bbdc89) + + Cleaned up include extension. + + +M src/lib-sieve/plugins/include/cmd-import.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-limits.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/ext-include.c + +2008-08-17 19:31:10 +0200 Stephan Bosch <stephan@rename-it.nl> (eb2f38ca) + + Cleaned up imapflags extension. + + +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c + +2008-08-17 19:03:50 +0200 Stephan Bosch <stephan@rename-it.nl> (43aedf5b) + + Cleaned up copy extension. + + +M src/lib-sieve/plugins/copy/ext-copy.c + +2008-08-17 18:52:38 +0200 Stephan Bosch <stephan@rename-it.nl> (91888b9d) + + Cleaned up comparator-i;ascii-numeric. + + +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c + +2008-08-16 20:47:26 +0200 Stephan Bosch <stephan@rename-it.nl> (75233d72) + + Forgot to add test file. + + +A tests/extensions/body/match-values.svtest + +2008-08-16 20:46:59 +0200 Stephan Bosch <stephan@rename-it.nl> (bfc6d259) + + Testsuite: added test for the behavior of the body test with match values. + + +M Makefile.am + +2008-08-16 20:36:29 +0200 Stephan Bosch <stephan@rename-it.nl> (47d3a843) + + Body: now disables match value processing during body test evaluation as + required by RFC. + + +M src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/sieve-match-types.c + +2008-08-16 20:12:08 +0200 Stephan Bosch <stephan@rename-it.nl> (f7ae127f) + + Finished code cleanup of the sieve library itself. + + +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h + +2008-08-16 19:31:55 +0200 Stephan Bosch <stephan@rename-it.nl> (151d4705) + + Broad code cleanup. + + +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-objects.c +M src/lib-sieve/sieve-objects.h + +2008-08-16 18:41:02 +0200 Stephan Bosch <stephan@rename-it.nl> (c4c7722f) + + Forgot to add new file for stop command. + + +A src/lib-sieve/cmd-stop.c + +2008-08-16 18:40:25 +0200 Stephan Bosch <stephan@rename-it.nl> (1fe262fe) + + Cleaned up commands implementation. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/include/cmd-import.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-code-dumper.c +D src/lib-sieve/sieve-commands-private.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/tst-test-compile.c +M src/testsuite/tst-test-error.c + +2008-08-16 16:08:35 +0200 Stephan Bosch <stephan@rename-it.nl> (17c6bc69) + + Cleaned up sieve-code. + + +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h + +2008-08-16 15:46:37 +0200 Stephan Bosch <stephan@rename-it.nl> (e6a1cd52) + + Cleaned up sieve-binary-dumper. + + +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-dumper.h + +2008-08-16 15:42:23 +0200 Stephan Bosch <stephan@rename-it.nl> (e04f3bfe) + + Cleaned up sieve-binary. + + +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h + +2008-08-16 15:30:15 +0200 Stephan Bosch <stephan@rename-it.nl> (cda64c34) + + Cleaned up sieve-ast. + + +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h + +2008-08-16 15:10:05 +0200 Stephan Bosch <stephan@rename-it.nl> (211fafea) + + Cleaned up sieve-address. + + +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h + +2008-08-16 15:01:01 +0200 Stephan Bosch <stephan@rename-it.nl> (680c052b) + + Cleaned up actions implementation. + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h + +2008-08-16 14:41:35 +0200 Stephan Bosch <stephan@rename-it.nl> (0d246fa2) + + Cleaned up address part and comparator implementation. + + +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-comparators.c + +2008-08-16 14:33:40 +0200 Stephan Bosch <stephan@rename-it.nl> (ad66ace5) + + Cleaned up match type implementation. + + +D sieve/errors/match-type-errors.sieve +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-header.c +M src/testsuite/tst-test-error.c +M tests/compile/errors.svtest +A tests/compile/errors/match-type.sieve + +2008-08-16 13:28:51 +0200 Stephan Bosch <stephan@rename-it.nl> (4001d8dd) + + Regex: improvements and bugfixes. + + +M TODO +M src/lib-sieve/plugins/regex/mcht-regex.c + +2008-08-16 12:49:35 +0200 Stephan Bosch <stephan@rename-it.nl> (64ab6616) + + Testsuite: restructured regex tests. + + +M Makefile.am +R100 tests/match-types/regex.svtest tests/extensions/regex/basic.svtest +A tests/extensions/regex/errors.svtest +R100 src/lib-sieve/plugins/regex/regex-errors.sieve tests/extensions/regex/errors/compile.sieve + +2008-08-16 12:29:06 +0200 Stephan Bosch <stephan@rename-it.nl> (556da050) + + Regex: fixed a few minor bugs. + + +M Makefile.am +R100 src/lib-sieve/plugins/regex/draft-murchison-sieve-regex-07.txt doc/rfc/draft-murchison-sieve-regex-07.txt +M src/lib-sieve/plugins/regex/mcht-regex.c +D src/lib-sieve/plugins/regex/regex.sieve +M src/lib-sieve/sieve-match-types.c +A tests/extensions/variables/regex.svtest +M tests/match-types/regex.svtest + +2008-08-14 01:35:12 +0200 Stephan Bosch <stephan@rename-it.nl> (9c6afd6b) + + Compile fix for changes in Dovecot. + + +M src/sieve-bin/mail-raw.c +M src/sieve-bin/mail-raw.h +M src/sieve-bin/namespaces.c +M src/sieve-bin/namespaces.h +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c +M src/testsuite/mail-raw.c +M src/testsuite/mail-raw.h +M src/testsuite/namespaces.c +M src/testsuite/namespaces.h +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite.c + +2008-08-13 23:50:15 +0200 Stephan Bosch <stephan@rename-it.nl> (d728be0d) + + Include: implemented runtime checking of export/import. + + +M TODO +M src/lib-sieve/plugins/include/cmd-import.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/variables/ext-variables-common.c +A tests/extensions/include/errors/runtime.sieve + +2008-08-13 22:51:59 +0200 Stephan Bosch <stephan@rename-it.nl> (d532a1e6) + + Include: transformed import and export to actual code operations for runtime + checking. + + +M src/lib-sieve/plugins/include/cmd-import.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-validator.c +M tests/extensions/include/variables.svtest + +2008-08-13 00:20:23 +0200 Stephan Bosch <stephan@rename-it.nl> (efa202a1) + + Variables: added functionality to obtain variable identifier from storage + using linked scope. + + +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2008-08-13 00:08:39 +0200 Stephan Bosch <stephan@rename-it.nl> (e82940d9) + + Variables: invalid variable indexes now trigger interpretation to fail with + EXEC_BIN_CORRUPT. + + +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2008-08-12 23:44:46 +0200 Stephan Bosch <stephan@rename-it.nl> (6aa6745d) + + Include: variable indexes are now verified to the global variable scope, + meaning that a corrupt binary cannot allocate arbitrary global variables + anymore. + + +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.c + +2008-08-12 23:23:01 +0200 Stephan Bosch <stephan@rename-it.nl> (6cef9457) + + Removed obsoleted runtime_load() extension event. + + +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-match-types.c +M src/testsuite/ext-testsuite.c + +2008-08-12 23:12:17 +0200 Stephan Bosch <stephan@rename-it.nl> (de5f14ed) + + Added run() event to the interpreter_extension object. + + +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-match-types.c + +2008-08-12 22:18:50 +0200 Stephan Bosch <stephan@rename-it.nl> (501ff34c) + + Cleaned up TODO file. + + +M TODO + +2008-08-12 22:14:35 +0200 Stephan Bosch <stephan@rename-it.nl> (de454e6f) + + Variables: implemented limits on number of variables in a scope, the length + of variable names, size of variable values and the number of accesible match + values. + + +M TODO +M doc/rfc/RFC Controversy.txt +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/variables/Makefile.am +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +A src/lib-sieve/plugins/variables/ext-variables-limits.h +M src/lib-sieve/plugins/variables/ext-variables-name.c +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M tests/extensions/variables/basic.svtest +M tests/extensions/variables/errors.svtest +A tests/extensions/variables/errors/limits.sieve + +2008-08-12 19:51:56 +0200 Stephan Bosch <stephan@rename-it.nl> (2f3c95e5) + + Limited number of accepted match values + + +M TODO +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/include/Makefile.am +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-match-types.c + +2008-08-12 19:04:37 +0200 Stephan Bosch <stephan@rename-it.nl> (2fcb69aa) + + Include: forgot to add new file to the repository. + + +A src/lib-sieve/plugins/include/ext-include-limits.h + +2008-08-12 19:03:12 +0200 Stephan Bosch <stephan@rename-it.nl> (e91c056f) + + Merged concurrent changes. + + +2008-08-12 19:02:12 +0200 Stephan Bosch <stephan@rename-it.nl> (1307169e) + + Include: limited the number of included scripts. + + +M TODO +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h + +2008-08-12 00:56:25 +0200 Stephan Bosch <stephan@rename-it.nl> (85d12ee4) + + LDA-Plugin: prevented plugin from polluting the logfiles when the script + does not exist. + + +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-bin/bin-common.c + +2008-08-11 00:11:57 +0200 Stephan Bosch <stephan@rename-it.nl> (de2e6138) + + Include: used wrong messaging function in previous commit. + + +M src/lib-sieve/plugins/include/cmd-include.c +M tests/extensions/include/errors.svtest +M tests/extensions/include/errors/generic.sieve + +2008-08-11 00:05:22 +0200 Stephan Bosch <stephan@rename-it.nl> (01ce939b) + + Include: prohibited use of '/' in scriptnames. + + +M src/lib-sieve/plugins/include/cmd-include.c + +2008-08-10 22:12:24 +0200 Stephan Bosch <stephan@rename-it.nl> (3f062944) + + Body: discovered various issues (listed in disabled tests). + + +M TODO +M tests/extensions/body/basic.svtest + +2008-08-10 21:34:17 +0200 Stephan Bosch <stephan@rename-it.nl> (d15163da) + + Body: added test regarding empty bodies and fixed testsuite to flush the + message context when the message is changed. + + +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/testsuite/cmd-test-set.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h +M tests/extensions/body/basic.svtest + +2008-08-10 20:44:56 +0200 Stephan Bosch <stephan@rename-it.nl> (60316c19) + + Body: fixed default comparator and added testsuite test to prevent this in + the future. + + +M src/lib-sieve/plugins/body/tst-body.c +M tests/extensions/body/basic.svtest + +2008-08-10 20:20:54 +0200 Stephan Bosch <stephan@rename-it.nl> (a6ccf5ae) + + Body: fixed bug in the :raw transform, added much comment to the body + extraction code and added a first simple test to the testsuite. + + +M Makefile.am +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/tst-body.c +A tests/extensions/body/basic.svtest + +2008-08-10 18:52:13 +0200 Stephan Bosch <stephan@rename-it.nl> (97b967b5) + + Made the lexer conform to the new Sieve RFC. + + +M src/lib-sieve/sieve-lexer.c +M src/testsuite/mail-raw.c + +2008-08-10 14:43:06 +0200 Stephan Bosch <stephan@rename-it.nl> (84fab47c) + + Installed RFC for the body extension in the doc/rfc directory. + + +A doc/rfc/body.rfc5173.txt +D src/lib-sieve/plugins/body/draft-ietf-sieve-body-07.txt +M src/lib-sieve/plugins/body/ext-body.c + +2008-08-10 13:35:55 +0200 Stephan Bosch <stephan@rename-it.nl> (d9c6094e) + + Made sure error messages do not print large erroneous values. + + +M TODO +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/tst-address.c + +2008-08-10 11:54:28 +0200 Stephan Bosch <stephan@rename-it.nl> (287f7c2e) + + Limited the depth of the AST and added tests to verify that it is resolved + gracefully. + + +M TODO +M src/lib-sieve/sieve-parser.c +M tests/compile/errors.svtest +M tests/compile/errors/parser.sieve + +2008-08-09 20:31:22 +0200 Stephan Bosch <stephan@rename-it.nl> (6e979c25) + + Limited number of command arguments. + + +M src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-parser.c +M tests/compile/errors.svtest +A tests/compile/errors/parser.sieve + +2008-08-09 19:40:20 +0200 Stephan Bosch <stephan@rename-it.nl> (ad194526) + + Made lexer use the (i_*) ctype.h functions. + + +M src/lib-sieve/sieve-lexer.c + +2008-08-09 18:51:39 +0200 Stephan Bosch <stephan@rename-it.nl> (4d8f8da7) + + Limited the length of identifiers. + + +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-limits.h +M tests/compile/errors.svtest +M tests/compile/errors/lexer.sieve + +2008-08-09 17:34:13 +0200 Stephan Bosch <stephan@rename-it.nl> (2bdf696e) + + Enforced limits on string length and handled the finite nature of integers + for number parsing and the construction of the AST. + + +M TODO +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-lexer.c +A src/lib-sieve/sieve-limits.h +M src/lib-sieve/sieve-parser.c +M tests/compile/errors.svtest +A tests/compile/errors/lexer.sieve + +2008-08-06 00:00:40 +0200 Stephan Bosch <stephan@rename-it.nl> (fe0422ab) + + Include: fixed bug in global variables referencing the main script. + + +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-variables.c + +2008-08-05 23:12:00 +0200 Stephan Bosch <stephan@rename-it.nl> (85b8865c) + + Include: symbol table for global variables now also includes locations for + the first import/export of each known variable. + + +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M tests/extensions/include/variables.svtest + +2008-08-05 22:32:19 +0200 Stephan Bosch <stephan@rename-it.nl> (af990c23) + + Include: included scripts are now referenced by an include_id in stead of + the binary block id. + + +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h + +2008-08-05 21:25:47 +0200 Stephan Bosch <stephan@rename-it.nl> (e0a8b6be) + + Forgot to implement free() event for validator and interpreter extensions. + + +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-validator.c + +2008-08-05 20:15:09 +0200 Stephan Bosch <stephan@rename-it.nl> (5b195b1c) + + Include: added symbol table to the binary for global variables. + + +M src/lib-sieve/plugins/include/cmd-import.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/testsuite/ext-testsuite.c +M tests/extensions/include/errors.svtest +A tests/extensions/include/errors/import-runtime.sieve +M tests/extensions/include/errors/variables.sieve + +2008-08-05 10:02:25 +0200 Stephan Bosch <stephan@rename-it.nl> (33ec65c7) + + Updated documentation. + + +M README +M TODO + +2008-08-03 23:33:47 +0200 Stephan Bosch <stephan@rename-it.nl> (f475b6da) + + Minor TODO file revisions. + + +M TODO + +2008-08-03 23:21:02 +0200 Stephan Bosch <stephan@rename-it.nl> (c1e6e217) + + Testsuite: added match values test for the :regex match + + +M Makefile.am +A tests/match-types/regex.svtest + +2008-08-03 23:15:31 +0200 Stephan Bosch <stephan@rename-it.nl> (ea223592) + + Fixed replacing match values only when a test succeeds. + + +M TODO +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M tests/extensions/variables/match.svtest +M tests/match-types/matches.svtest + +2008-08-03 19:34:01 +0200 Stephan Bosch <stephan@rename-it.nl> (b043e882) + + Upgraded validator and interpreter extension support to provide destruction + notifications. + + +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h + +2008-08-02 17:24:03 +0200 Stephan Bosch <stephan@rename-it.nl> (e3afed79) + + Include: found one issue. + + +M TODO + +2008-08-02 16:22:04 +0200 Stephan Bosch <stephan@rename-it.nl> (e83f2e46) + + Testsuite: added circular include tests. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite.c +M tests/extensions/include/errors.svtest +A tests/extensions/include/errors/circular-1.sieve +A tests/extensions/include/errors/circular-2.sieve +A tests/extensions/include/errors/circular-3.sieve +A tests/extensions/include/errors/included/circular-one.sieve +A tests/extensions/include/errors/included/circular-three-2.sieve +A tests/extensions/include/errors/included/circular-three-3.sieve +A tests/extensions/include/errors/included/circular-three.sieve +A tests/extensions/include/errors/included/circular-two-2.sieve +A tests/extensions/include/errors/included/circular-two.sieve +R100 tests/extensions/include/variables-included1.sieve tests/extensions/include/included/variables-included1.sieve +R100 tests/extensions/include/variables-included2.sieve tests/extensions/include/included/variables-included2.sieve +R100 tests/extensions/include/variables-included3.sieve tests/extensions/include/included/variables-included3.sieve + +2008-08-02 15:48:00 +0200 Stephan Bosch <stephan@rename-it.nl> (a78fd5bb) + + Include: cleaned up source directory. + + +R100 src/lib-sieve/plugins/include/draft-daboo-sieve-include-05.txt doc/rfc/draft-daboo-sieve-include-05.txt +M src/lib-sieve/plugins/include/Makefile.am +D src/lib-sieve/plugins/include/include-variables.sieve +D src/lib-sieve/plugins/include/include-variables1.sieve +D src/lib-sieve/plugins/include/include-variables2.sieve +D src/lib-sieve/plugins/include/include-variables3.sieve +D src/lib-sieve/plugins/include/include.sieve +D src/lib-sieve/plugins/include/included1.sieve +D src/lib-sieve/plugins/include/included2.sieve +D src/lib-sieve/plugins/include/included3.sieve +M tests/extensions/include/errors.svtest +R060 src/lib-sieve/plugins/include/include-error.sieve tests/extensions/include/errors/generic.sieve + +2008-08-02 15:36:26 +0200 Stephan Bosch <stephan@rename-it.nl> (45c19dad) + + Testsuite: added compile error tests for the include extension. + + +M Makefile.am +D src/lib-sieve/plugins/include/include-variables-error2.sieve +A tests/extensions/include/errors.svtest +R080 src/lib-sieve/plugins/include/include-variables-error.sieve tests/extensions/include/errors/variables-inactive.sieve +A tests/extensions/include/errors/variables.sieve + +2008-08-02 15:35:54 +0200 Stephan Bosch <stephan@rename-it.nl> (718c4b72) + + Copy: forgot to remove RFC from old location. + + +D src/lib-sieve/plugins/copy/rfc3894.txt + +2008-08-02 15:34:21 +0200 Stephan Bosch <stephan@rename-it.nl> (a65a1af8) + + Copy: moved RFC to doc/rfc directory. + + +A doc/rfc/copy.rfc3894.txt + +2008-08-02 15:12:31 +0200 Stephan Bosch <stephan@rename-it.nl> (2a48ee8c) + + Imapflags: updated specification to RFC 5232. + + +A doc/rfc/imap4flags.rfc5232.txt +D src/lib-sieve/plugins/imapflags/draft-ietf-sieve-imapflags-05.txt +M src/lib-sieve/plugins/imapflags/ext-imapflags.c + +2008-08-02 15:04:20 +0200 Stephan Bosch <stephan@rename-it.nl> (d77cbb86) + + Imapflags: found one new issue. + + +M TODO + +2008-08-02 14:55:45 +0200 Stephan Bosch <stephan@rename-it.nl> (a22b5d49) + + Imapflags: accidentally omitted support for multiple variables in the + hasflag test. + + +M Makefile.am +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/sieve-generator.c +R080 tests/extensions/imapflags/rfc.svtest tests/extensions/imapflags/hasflag.svtest + +2008-08-02 13:02:22 +0200 Stephan Bosch <stephan@rename-it.nl> (91eb50e0) + + Testsuite: added new tests for the variables extension. + + +M TODO +M tests/extensions/variables/errors.svtest +M tests/extensions/variables/errors/set.sieve +M tests/extensions/variables/string.svtest + +2008-08-02 12:41:30 +0200 Stephan Bosch <stephan@rename-it.nl> (0999c475) + + Fixed various case-sensitivily-related issues. + + +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-validator.c +M tests/compile/trivial.sieve +M tests/extensions/variables/errors.svtest + +2008-08-02 12:25:07 +0200 Stephan Bosch <stephan@rename-it.nl> (30c8cf2e) + + Variables: fixed various error handling issues. + + +M Makefile.am +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +A tests/extensions/variables/errors.svtest +A tests/extensions/variables/errors/namespace.sieve +A tests/extensions/variables/errors/set.sieve + +2008-08-02 12:24:30 +0200 Stephan Bosch <stephan@rename-it.nl> (d1dfd428) + + Fixed a warning. + + +M src/lib-sieve/sieve-address.c + +2008-08-01 22:02:55 +0200 Stephan Bosch <stephan@rename-it.nl> (e4ac3052) + + Fixed 'make dist' to produce a working tarball. + + +M Makefile.am +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/variables/Makefile.am +M src/lib-sieve/plugins/variables/ext-variables.c + +2008-08-01 21:22:44 +0200 Stephan Bosch <stephan@rename-it.nl> (5e87e933) + + Testsuite: added test regarding matching the empty string and fixed an issue + in the i;ascii-numeric comparator. + + +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M tests/match-types/contains.svtest +M tests/match-types/is.svtest +M tests/match-types/matches.svtest +M tests/match-types/relational.svtest + +2008-08-01 20:40:36 +0200 Stephan Bosch <stephan@rename-it.nl> (548ad669) + + Variables: fixed :count issue for the string test. + + +M Makefile.am +M TODO +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M tests/extensions/variables/string.svtest + +2008-08-01 20:11:39 +0200 Stephan Bosch <stephan@rename-it.nl> (8b678f10) + + Testsuite: added more tests for the variables extension and found one issue. + + +M TODO +M tests/extensions/variables/basic.svtest +M tests/extensions/variables/modifiers.svtest +A tests/extensions/variables/string.svtest + +2008-08-01 19:25:36 +0200 Stephan Bosch <stephan@rename-it.nl> (6f1a5e10) + + Testsuite: added RFC compliance tests for the variables extension and fixed + use of wrong default comparator. + + +M Makefile.am +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-header.c +M tests/extensions/variables/basic.svtest +M tests/extensions/variables/match.svtest +A tests/extensions/variables/modifiers.svtest +M tests/match-types/contains.svtest + +2008-08-01 17:54:40 +0200 Stephan Bosch <stephan@rename-it.nl> (353c11c7) + + Fixed bug in the order of default argument processing. Variable strings were + evaluated befor constant strings, which is wrong. + + +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/sieve-validator.c +A tests/extensions/variables/quoting.svtest + +2008-08-01 16:32:58 +0200 Stephan Bosch <stephan@rename-it.nl> (5e3518f2) + + Envelope: added more test and fixed source route parsing. + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/sieve-address.c +M tests/extensions/envelope.svtest + +2008-08-01 02:26:16 +0200 Stephan Bosch <stephan@rename-it.nl> (be8b4eb0) + + Envelope: fixed one bug in the path parsing (printfs active). + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/sieve-address.c +M tests/extensions/envelope.svtest + +2008-07-31 10:44:17 +0200 Stephan Bosch <stephan@rename-it.nl> (d65ee78e) + + Envelope: working towards proper RFC compliance of forward/return-path + parsing. + + +M TODO +M doc/rfc/RFC Controversy.txt +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-common.h +M tests/extensions/envelope.svtest +M tests/testsuite.svtest + +2008-07-29 23:05:05 +0200 Stephan Bosch <stephan@rename-it.nl> (51a0cc34) + + Variables: fixed RFC compliance issue regarding failing validation on + unknown namespaces. + + +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M tests/extensions/variables/basic.svtest + +2008-07-29 22:38:44 +0200 Stephan Bosch <stephan@rename-it.nl> (71e66c81) + + Variables: fixed bug in variables substitution (RFC example failed during + testing). + + +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M tests/extensions/variables/basic.svtest + +2008-07-29 22:21:32 +0200 Stephan Bosch <stephan@rename-it.nl> (b29320f2) + + Variables: fixed very significant bug in the variable scope implementation. + + +M src/lib-sieve/plugins/variables/ext-variables-common.c +M tests/extensions/variables/basic.svtest + +2008-07-29 22:21:04 +0200 Stephan Bosch <stephan@rename-it.nl> (a1c77607) + + Removed superfluous include. + + +M src/lib-sieve/sieve-binary.h + +2008-07-29 19:32:30 +0200 Stephan Bosch <stephan@rename-it.nl> (e64a9b8f) + + Testsuite: cleaned up basic varibles test case. + + +M tests/extensions/variables/basic.svtest + +2008-07-29 19:15:35 +0200 Stephan Bosch <stephan@rename-it.nl> (a4faba00) + + Testsuite: moved tests directory to the root of the package. + + +M Makefile.am +M configure.in +M src/testsuite/Makefile.am +R100 src/testsuite/tests/address-parts/subaddress.svtest tests/address-parts/subaddress.svtest +R100 src/testsuite/tests/comparators/core.svtest tests/comparators/core.svtest +R052 src/testsuite/tests/compile/compile-examples.svtest tests/compile/compile-examples.svtest +R100 src/testsuite/tests/compile/compile.svtest tests/compile/compile.svtest +R100 src/testsuite/tests/compile/errors.svtest tests/compile/errors.svtest +R100 src/testsuite/tests/compile/errors/address-part.sieve tests/compile/errors/address-part.sieve +R100 src/testsuite/tests/compile/errors/address.sieve tests/compile/errors/address.sieve +R100 src/testsuite/tests/compile/errors/encoded-character.sieve tests/compile/errors/encoded-character.sieve +R100 src/testsuite/tests/compile/errors/envelope.sieve tests/compile/errors/envelope.sieve +R100 src/testsuite/tests/compile/errors/header.sieve tests/compile/errors/header.sieve +R100 src/testsuite/tests/compile/errors/if.sieve tests/compile/errors/if.sieve +R100 src/testsuite/tests/compile/errors/keep.sieve tests/compile/errors/keep.sieve +R100 src/testsuite/tests/compile/errors/require.sieve tests/compile/errors/require.sieve +R100 src/testsuite/tests/compile/errors/size.sieve tests/compile/errors/size.sieve +R100 src/testsuite/tests/compile/errors/stop.sieve tests/compile/errors/stop.sieve +R100 src/testsuite/tests/compile/redirect.sieve tests/compile/redirect.sieve +R100 src/testsuite/tests/compile/trivial.sieve tests/compile/trivial.sieve +R100 src/testsuite/tests/control-structures.svtest tests/control-structures.svtest +R100 src/testsuite/tests/exists.svtest tests/exists.svtest +R100 src/testsuite/tests/extensions/encoded-character.svtest tests/extensions/encoded-character.svtest +R100 src/testsuite/tests/extensions/envelope.svtest tests/extensions/envelope.svtest +R100 src/testsuite/tests/extensions/imapflags/basic.svtest tests/extensions/imapflags/basic.svtest +R100 src/testsuite/tests/extensions/imapflags/rfc.svtest tests/extensions/imapflags/rfc.svtest +R100 src/testsuite/tests/extensions/include/variables-included1.sieve tests/extensions/include/variables-included1.sieve +R100 src/testsuite/tests/extensions/include/variables-included2.sieve tests/extensions/include/variables-included2.sieve +R100 src/testsuite/tests/extensions/include/variables-included3.sieve tests/extensions/include/variables-included3.sieve +R100 src/testsuite/tests/extensions/include/variables.svtest tests/extensions/include/variables.svtest +R100 src/testsuite/tests/extensions/variables/basic.svtest tests/extensions/variables/basic.svtest +R100 src/testsuite/tests/extensions/variables/match.svtest tests/extensions/variables/match.svtest +R100 src/testsuite/tests/header.svtest tests/header.svtest +R100 src/testsuite/tests/lexer.svtest tests/lexer.svtest +R100 src/testsuite/tests/match-types/contains.svtest tests/match-types/contains.svtest +R100 src/testsuite/tests/match-types/is.svtest tests/match-types/is.svtest +R100 src/testsuite/tests/match-types/matches.svtest tests/match-types/matches.svtest +R100 src/testsuite/tests/match-types/relational.svtest tests/match-types/relational.svtest +R100 src/testsuite/tests/testsuite.svtest tests/testsuite.svtest + +2008-07-29 18:55:47 +0200 Stephan Bosch <stephan@rename-it.nl> (e3b19039) + + Installed variables rfc in the doc/rfc directory. + + +R100 src/lib-sieve/plugins/variables/rfc5229.txt doc/rfc/variables.rfc5229.txt + +2008-07-29 17:08:15 +0200 Stephan Bosch <stephan@rename-it.nl> (734239f9) + + Encoded-character: resolved error reporting issue, added some syntax error + tests and fixed some parsing bugs in the process. + + +M TODO +M src/lib-sieve/ext-encoded-character.c +M src/testsuite/tests/compile/errors/encoded-character.sieve +M src/testsuite/tests/extensions/encoded-character.svtest + +2008-07-29 15:19:28 +0200 Stephan Bosch <stephan@rename-it.nl> (c2c58e59) + + Testsuite: added compile error testcases and discovered one new issue. + + +M TODO +M src/lib-sieve/ext-encoded-character.c +M src/testsuite/tests/compile/errors.svtest +A src/testsuite/tests/compile/errors/address-part.sieve +A src/testsuite/tests/compile/errors/encoded-character.sieve +A src/testsuite/tests/compile/errors/envelope.sieve +A src/testsuite/tests/compile/errors/keep.sieve +A src/testsuite/tests/compile/errors/size.sieve +A src/testsuite/tests/compile/errors/stop.sieve +M src/testsuite/tests/control-structures.svtest + +2008-07-29 11:36:26 +0200 Stephan Bosch <stephan@rename-it.nl> (9e2140cb) + + Reprioritized TODO file. + + +M TODO + +2008-07-29 11:30:15 +0200 Stephan Bosch <stephan@rename-it.nl> (ea0e6b49) + + Variables: resolved issues in the scope implementation. + + +M TODO +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2008-07-29 10:58:17 +0200 Stephan Bosch <stephan@rename-it.nl> (c4879d7c) + + Added proper extension support to AST object. + + +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h + +2008-07-28 20:39:51 +0200 Stephan Bosch <stephan@rename-it.nl> (f597ac97) + + Testsuite: added a few more compile error test cases. + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-validator.c +M src/testsuite/tests/compile/errors.svtest +A src/testsuite/tests/compile/errors/address.sieve +M src/testsuite/tests/compile/errors/header.sieve +A src/testsuite/tests/compile/errors/if.sieve +A src/testsuite/tests/compile/errors/require.sieve +M src/testsuite/testsuite-common.c + +2008-07-28 18:44:23 +0200 Stephan Bosch <stephan@rename-it.nl> (7b048e6c) + + Testsuite: completed support for error validation and added one test case. + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/testsuite/Makefile.am +R097 src/testsuite/tests/errors.svtest src/testsuite/tests/compile/errors.svtest +R100 src/testsuite/tests/header-errors.sieve src/testsuite/tests/compile/errors/header.sieve +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite.c +M src/testsuite/tst-test-compile.c +M src/testsuite/tst-test-error.c + +2008-07-28 16:29:12 +0200 Stephan Bosch <stephan@rename-it.nl> (616b274f) + + Testsuite: started support for error validation. + + +M src/testsuite/Makefile.am +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-set.c +M src/testsuite/ext-testsuite.c +A src/testsuite/tests/errors.svtest +A src/testsuite/tests/header-errors.sieve +M src/testsuite/testsuite-common.h +M src/testsuite/tst-test-compile.c +A src/testsuite/tst-test-error.c + +2008-07-28 14:59:16 +0200 Stephan Bosch <stephan@rename-it.nl> (43d05ac5) + + Testsuite: marginally improved match-type tests. + + +M TODO +M src/testsuite/Makefile.am +M src/testsuite/tests/match-types/contains.svtest +A src/testsuite/tests/match-types/is.svtest + +2008-07-28 12:49:45 +0200 Stephan Bosch <stephan@rename-it.nl> (141a7794) + + Added variables testcase to the testsuite. + + +M src/testsuite/Makefile.am + +2008-07-28 12:48:14 +0200 Stephan Bosch <stephan@rename-it.nl> (34fd1a7b) + + Fixed bugs in the :matches match type. + + +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +A src/testsuite/tests/extensions/variables/match.svtest +M src/testsuite/tests/lexer.svtest +M src/testsuite/tests/match-types/matches.svtest + +2008-07-28 00:22:23 +0200 Stephan Bosch <stephan@rename-it.nl> (f153305d) + + Encoded-character: fixed a few bugs to properly match the examples provided + in the RFC. + + +M src/lib-sieve/ext-encoded-character.c +M src/testsuite/Makefile.am +A src/testsuite/tests/extensions/encoded-character.svtest + +2008-07-27 21:53:04 +0200 Stephan Bosch <stephan@rename-it.nl> (8de497f0) + + Added stripping of right white space from header content. + + +M TODO +M src/lib-sieve/tst-header.c + +2008-07-27 18:00:21 +0200 Stephan Bosch <stephan@rename-it.nl> (ed2c80bc) + + Updated TODO + + +M TODO + +2008-07-27 17:52:34 +0200 Stephan Bosch <stephan@rename-it.nl> (47b8548c) + + Envelope: forgot to add new test case. + + +A src/testsuite/tests/extensions/envelope.svtest + +2008-07-27 17:52:03 +0200 Stephan Bosch <stephan@rename-it.nl> (1118aaef) + + Envelope: <> return path now always matches as the empty string, regardless + of the specified address part. + + +M TODO +M src/lib-sieve/ext-envelope.c +M src/testsuite/Makefile.am + +2008-07-27 17:17:57 +0200 Stephan Bosch <stephan@rename-it.nl> (a924297f) + + Minor TODO file change. + + +M TODO + +2008-07-27 17:17:02 +0200 Stephan Bosch <stephan@rename-it.nl> (3b233deb) + + Forgot to adjust comment. + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/tst-address.c + +2008-07-27 17:15:24 +0200 Stephan Bosch <stephan@rename-it.nl> (b1e91a0a) + + Updated documentation. + + +M doc/rfc/RFC Controversy.txt + +2008-07-27 17:12:10 +0200 Stephan Bosch <stephan@rename-it.nl> (7aa007fb) + + Envelope: added compile-time envelope-part verification. + + +M TODO +M doc/rfc/RFC Controversy.txt +A sieve/errors/envelope-errors.sieve +M sieve/examples/elvey.sieve +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/tst-address.c + +2008-07-27 16:27:40 +0200 Stephan Bosch <stephan@rename-it.nl> (6a1073f6) + + Added RFC controversy file to log all matters that require clarification + from RFC editors. + + +A doc/rfc/RFC Controversy.txt + +2008-07-27 16:00:47 +0200 Stephan Bosch <stephan@rename-it.nl> (ae34854c) + + Restricted allowable headers for the address test. + + +M TODO + +2008-07-27 15:59:47 +0200 Stephan Bosch <stephan@rename-it.nl> (7a0738ab) + + Imapflags: forgot to add testcase file. + + +M TODO +M sieve/errors/address-errors.sieve +M src/lib-sieve/tst-address.c +A src/testsuite/tests/extensions/imapflags/rfc.svtest + +2008-07-27 13:12:07 +0200 Stephan Bosch <stephan@rename-it.nl> (0db3a614) + + Disallowed extraction of key elements from key strings for match types for + with that would not make sense. + + +M src/lib-sieve/sieve-match.c + +2008-07-27 13:08:33 +0200 Stephan Bosch <stephan@rename-it.nl> (a26cb52c) + + Imapflags: resolved problem of hasflags encountering duplicate flags in flag + lists contained in a variable. + + +M TODO +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/testsuite/Makefile.am +M src/testsuite/tests/extensions/imapflags/basic.svtest + +2008-07-27 12:43:29 +0200 Stephan Bosch <stephan@rename-it.nl> (0b2f9a20) + + Imapflags: resolved string representation issue in hasflag. + + +M TODO +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-header.c +M src/testsuite/Makefile.am +M src/testsuite/tests/extensions/imapflags/basic.svtest + +2008-07-27 11:50:07 +0200 Stephan Bosch <stephan@rename-it.nl> (778eab7c) + + Resolved code duplication among commands that use comparators and + match-types and found problems in the imapflags extension in the process. + + +M TODO +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-match.c +M src/lib-sieve/sieve-match.h +M src/lib-sieve/tst-header.c +A src/testsuite/tests/extensions/imapflags/basic.svtest + +2008-07-26 10:28:50 +0200 Stephan Bosch <stephan@rename-it.nl> (a79ccdb9) + + LDA-Sieve plugin: forgot to save the new binary when encountered a corrupt + one. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2008-07-26 00:11:06 +0200 Stephan Bosch <stephan@rename-it.nl> (540a6429) + + Improved the handling corrupt binaries further for the action commands. + + +M TODO +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h + +2008-07-25 23:30:26 +0200 Stephan Bosch <stephan@rename-it.nl> (31fb8075) + + Significantly improved handling of old/corrupt binaries and revised matching + implementation in the process. + + +M TODO +M src/lib-sieve/Makefile.am +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +A src/lib-sieve/sieve-match.c +A src/lib-sieve/sieve-match.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-header.c +M src/sieve-bin/sieve-test.c +M src/testsuite/Makefile.am +M src/testsuite/tests/control-structures.svtest +A src/testsuite/tests/match-types/relational.svtest +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite.c + +2008-07-25 20:54:21 +0200 Stephan Bosch <stephan@rename-it.nl> (4a5d8262) + + Fixed extremely stupid bug in the i;ascii-numeric comparator. + + +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c + +2008-07-25 19:17:20 +0200 Stephan Bosch <stephan@rename-it.nl> (d3d97752) + + Implemented graceful handling of corrupt binaries by the sieve lda plugin. + + +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-interpreter.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c + +2008-07-25 17:38:44 +0200 Stephan Bosch <stephan@rename-it.nl> (8ba069ed) + + Properly configured package name. + + +M configure.in + +2008-07-25 17:26:40 +0200 Stephan Bosch <stephan@rename-it.nl> (c17c8361) + + Working towards improving the handling of currupt binaries: defined multiple + exit codes for execution functions and defined trace macro for reporting + binary corruptions. + + +M TODO +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-types.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c +M src/sieve-bin/sieve-exec.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/tst-test-compile.c + +2008-07-25 14:23:02 +0200 Stephan Bosch <stephan@rename-it.nl> (4b4530a3) + + Testsuite: forgot to add test cases for include extension. + + +M TODO +A src/testsuite/tests/extensions/include/variables-included1.sieve +A src/testsuite/tests/extensions/include/variables-included2.sieve +A src/testsuite/tests/extensions/include/variables-included3.sieve +A src/testsuite/tests/extensions/include/variables.svtest + +2008-07-25 12:12:33 +0200 Stephan Bosch <stephan@rename-it.nl> (2ff8eeed) + + Fixed code emission for extension-defined variables and removed hardcoded + paths from include extension. + + +M TODO +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/testsuite/Makefile.am +M src/testsuite/testsuite.c + +2008-07-25 10:25:47 +0200 Stephan Bosch <stephan@rename-it.nl> (2959236f) + + Added future TODO item. + + +M TODO + +2008-07-25 01:05:51 +0200 Stephan Bosch <stephan@rename-it.nl> (dd937bb3) + + Updated TODO and removed spurious FIXME. + + +M TODO +M src/lib-sieve/sieve-interpreter.h + +2008-07-25 00:48:21 +0200 Stephan Bosch <stephan@rename-it.nl> (8c1c6f61) + + Updated documentation. + + +M README +M src/testsuite/ext-testsuite.c + +2008-07-25 00:05:16 +0200 Stephan Bosch <stephan@rename-it.nl> (e38b0bbd) + + Testsuite: added test_compile command to test compilation of scripts. + + +M .hgignore +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/testsuite/Makefile.am +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/ext-testsuite.c +A src/testsuite/tests/compile/compile-examples.svtest +A src/testsuite/tests/compile/compile.svtest +A src/testsuite/tests/compile/redirect.sieve +A src/testsuite/tests/compile/trivial.sieve +M src/testsuite/testsuite-common.h +A src/testsuite/tst-test-compile.c + +2008-07-24 22:59:18 +0200 Stephan Bosch <stephan@rename-it.nl> (1af2938b) + + Revised Sieve address validation functionality. + + +M TODO +M sieve/errors/out-address-errors.sieve +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-binary.c + +2008-07-24 17:48:56 +0200 Stephan Bosch <stephan@rename-it.nl> (c0e64243) + + Started using new str_new_const() function. + + +M README +M TODO +M configure.in +M src/lib-sieve/sieve-binary.c + +2008-07-24 17:35:47 +0200 Stephan Bosch <stephan@rename-it.nl> (e6995fc0) + + Imapflags: improved handling of invalid flags. + + +M TODO +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/imapflags/imapflags-errors.sieve +M src/lib-sieve/plugins/imapflags/imapflags.sieve +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2008-07-24 13:50:03 +0200 Stephan Bosch <stephan@rename-it.nl> (7f089988) + + Significantly improved pool allocation by checking --enable-debug warnings + from dovecot. + + +M TODO +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-validator.c + +2008-07-24 09:37:56 +0200 Stephan Bosch <stephan@rename-it.nl> (b62a2c59) + + Removed all legacy use of array_create(). + + +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-validator.c + +2008-07-24 08:49:20 +0200 Stephan Bosch <stephan@rename-it.nl> (293e7d6b) + + Lexer: fixed repetitive string alloation problem. + + +M src/lib-sieve/sieve-lexer.c + +2008-07-23 18:53:22 +0200 Stephan Bosch <stephan@rename-it.nl> (473c9384) + + Fixed bug introduced by previous change. + + +M src/lib-sieve/sieve-binary.c + +2008-07-23 18:38:14 +0200 Stephan Bosch <stephan@rename-it.nl> (73b03bea) + + Reworked operand and operation binary coding functions. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +D src/lib-sieve/sieve-extensions-private.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-match-types.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-objects.c + +2008-07-23 13:51:51 +0200 Stephan Bosch <stephan@rename-it.nl> (4a7ba645) + + Fully substituted the use of extension ids with the use of the extension + object itself. + + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-extensions-private.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-message.c +M src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-objects.c +M src/lib-sieve/sieve-objects.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h + +2008-07-23 11:38:15 +0200 Stephan Bosch <stephan@rename-it.nl> (be78a55b) + + Made initially assigned extension id available directly from the const + extension object itself. + + +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-validator.c +M src/testsuite/ext-testsuite.c + +2008-07-23 00:42:51 +0200 Stephan Bosch <stephan@rename-it.nl> (e81dd2cf) + + Reworked previous change into three elegant macros. + + +M TODO +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h + +2008-07-22 20:14:45 +0200 Stephan Bosch <stephan@rename-it.nl> (79d351ae) + + Made utility functions for neatly handing system errors, warnings and + notices. + + +M TODO +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-script.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2008-07-22 11:02:20 +0200 Stephan Bosch <stephan@rename-it.nl> (6359fb85) + + Testsuite: added tests for use of allof/anyof with a single test and + optimized code generation. + + +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/testsuite/tests/control-structures.svtest + +2008-07-22 10:38:40 +0200 Stephan Bosch <stephan@rename-it.nl> (9ecbfb56) + + Testsuite: added test case for the header test and found one issue. + + +M TODO +A src/testsuite/tests/header.svtest +M src/testsuite/tests/match-types/contains.svtest + +2008-07-22 09:43:15 +0200 Stephan Bosch <stephan@rename-it.nl> (630d8e4b) + + Testsuite: added lexer string scan comparison test and fixed lexer bug in + the process. + + +M src/lib-sieve/sieve-lexer.c +M src/testsuite/Makefile.am +A src/testsuite/tests/lexer.svtest + +2008-07-21 23:57:05 +0200 Stephan Bosch <stephan@rename-it.nl> (6e9716f2) + + Testsuite: added some control structure tests involving nesting. + + +M TODO +M src/testsuite/tests/control-structures.svtest + +2008-07-21 23:37:01 +0200 Stephan Bosch <stephan@rename-it.nl> (5a47c74b) + + Testsuite: added tests for 'exists' test and fixed a semantic error in the + 'exists' test. + + +M TODO +M src/lib-sieve/tst-exists.c +M src/testsuite/Makefile.am +A src/testsuite/tests/exists.svtest +M src/testsuite/testsuite-objects.c + +2008-07-21 23:19:39 +0200 Stephan Bosch <stephan@rename-it.nl> (3b53c87f) + + Testsuite: tested handling of teststuite envelope environment and fixed bugs + in the envelope test in the process. + + +M TODO +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/sieve-address-parts.c +M src/testsuite/tests/testsuite.svtest +M src/testsuite/testsuite-objects.c + +2008-07-21 21:59:37 +0200 Stephan Bosch <stephan@rename-it.nl> (ed86429a) + + Testsuite: added test case for subadress extension. + + +M src/testsuite/Makefile.am +A src/testsuite/tests/address-parts/subaddress.svtest +M src/testsuite/testsuite-common.c + +2008-07-21 19:30:16 +0200 Stephan Bosch <stephan@rename-it.nl> (3f15068e) + + Coupled testsuite to 'make test'. + + +M Makefile.am +M TODO +M configure.in +M src/Makefile.am +M src/testsuite/Makefile.am +M src/testsuite/tests/testsuite.svtest +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite.c + +2008-07-21 17:26:18 +0200 Stephan Bosch <stephan@rename-it.nl> (78c2ac15) + + Cleaned up test and core extension implementations. + + +M sieve/tests/encoded-character.sieve +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c + +2008-07-21 16:11:56 +0200 Stephan Bosch <stephan@rename-it.nl> (5fb4684d) + + Cleaned up command implementations. + + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c + +2008-07-21 13:41:43 +0200 Stephan Bosch <stephan@rename-it.nl> (2793a703) + + Fixed handling of script files that are in fact symbolic links. + + +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c + +2008-07-21 12:37:57 +0200 Stephan Bosch <stephan@rename-it.nl> (04ac5df4) + + Fixed bug in binary created without a corresponding script object. + + +M src/lib-sieve/sieve-binary.c + +2008-07-21 12:23:50 +0200 Stephan Bosch <stephan@rename-it.nl> (a0203d2e) + + Reversed stat() and open() on two occasions to make retrieved stat + information guaranteed to be valid for the opened file and added error + handling for various close() system calls. + + +M TODO +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-script.c + +2008-07-21 02:26:25 +0200 Stephan Bosch <stephan@rename-it.nl> (778874e1) + + Updated TODO list. + + +M TODO + +2008-07-21 02:09:28 +0200 Stephan Bosch <stephan@rename-it.nl> (7c33d499) + + Removed various unnecessary includes of <ctype.h> and replaced yey another + toupper() with its i_* equivalent. + + +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-modifiers.c +M src/lib-sieve/plugins/variables/ext-variables-name.c +M src/lib-sieve/plugins/variables/ext-variables-name.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/sieve-actions.c + +2008-07-21 01:52:49 +0200 Stephan Bosch <stephan@rename-it.nl> (a4a7eba1) + + Removed direct use of isdigit, isalpha and isalnum and replaced these with + their dovecot i_* equivalents to prevent problems on some systems. + + +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/variables/ext-variables-name.c + +2008-07-21 01:45:08 +0200 Stephan Bosch <stephan@rename-it.nl> (81dc9e2e) + + Updated TODO. + + +M TODO + +2008-07-21 01:20:05 +0200 Stephan Bosch <stephan@rename-it.nl> (9f778b94) + + Variables: made set modifiers descendants of the sieve object too. + + +M src/lib-sieve/plugins/variables/Makefile.am +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +A src/lib-sieve/plugins/variables/ext-variables-modifiers.c +A src/lib-sieve/plugins/variables/ext-variables-modifiers.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/variables-match.sieve +A src/testsuite/tests/extensions/variables/basic.svtest + +2008-07-20 21:37:18 +0200 Stephan Bosch <stephan@rename-it.nl> (966d850b) + + Testsuite: made testsuite objects a descendant from sieve objects. + + +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-objects.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h + +2008-07-20 18:32:25 +0200 Stephan Bosch <stephan@rename-it.nl> (a2562989) + + Removed remaining code duplication among comparators, match types and + address parts. + + +M TODO +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h + +2008-07-20 17:01:29 +0200 Stephan Bosch <stephan@rename-it.nl> (655f933f) + + Updated TODO list. + + +M TODO + +2008-07-20 16:59:49 +0200 Stephan Bosch <stephan@rename-it.nl> (d1bcfc06) + + Made side effects sieve objects too. + + +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-objects.c +M src/lib-sieve/sieve-objects.h + +2008-07-20 15:27:02 +0200 Stephan Bosch <stephan@rename-it.nl> (1947ba30) + + Introduced the concept of a sieve object to merge the coding of comparators, + match types, address parts and other objects that might need to be + represented in byte code (removes lots of code duplication). + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmp-i-ascii-casemap.c +M src/lib-sieve/cmp-i-octet.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/regex/ext-regex-common.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +A src/lib-sieve/sieve-objects.c +A src/lib-sieve/sieve-objects.h + +2008-07-19 19:43:29 +0200 Stephan Bosch <stephan@rename-it.nl> (c289acca) + + Revised extension support for match-types. + + +M TODO +M src/lib-sieve/cmp-i-octet.c +M src/lib-sieve/mcht-contains.c +M src/lib-sieve/mcht-is.c +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/regex/Makefile.am +A src/lib-sieve/plugins/regex/ext-regex-common.c +M src/lib-sieve/plugins/regex/ext-regex-common.h +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/relational/ext-relational-common.c +M src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/relational/mcht-count.c +M src/lib-sieve/plugins/relational/mcht-value.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h + +2008-07-19 16:31:14 +0200 Stephan Bosch <stephan@rename-it.nl> (db760623) + + Cleaned up comparator implementation. + + +M src/lib-sieve/Makefile.am +A src/lib-sieve/cmp-i-ascii-casemap.c +A src/lib-sieve/cmp-i-octet.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h + +2008-07-19 15:57:46 +0200 Stephan Bosch <stephan@rename-it.nl> (b4c6eaff) + + Revised extension support for comparators. + + +M TODO +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +A src/testsuite/tests/comparators/core.svtest + +2008-07-18 21:31:11 +0200 Stephan Bosch <stephan@rename-it.nl> (a5dba1ca) + + Fixed stupid bug in the match-type context validation. + + +M src/lib-sieve/sieve-comparators.c + +2008-07-18 18:32:29 +0200 Stephan Bosch <stephan@rename-it.nl> (37d7c200) + + Made error reporting cleaner by avoiding the scriptname of the main script + and indicating that the printed numbers are in fact source code lines. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +A src/lib-sieve/sieve-types.h +M src/lib-sieve/sieve.h + +2008-07-18 12:37:30 +0200 Stephan Bosch <stephan@rename-it.nl> (c71a9299) + + Fixed warnings caused by remaining spurious inline definitions in + sieve-validator.h + + +M src/lib-sieve/sieve-validator.h + +2008-07-17 17:30:59 +0200 Stephan Bosch <stephan@rename-it.nl> (998fd1b4) + + Code cleanup: parser, lexer, lda-plugin and main interface. + + +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2008-07-17 00:02:29 +0200 Stephan Bosch <stephan@rename-it.nl> (536aa183) + + Updated TODO. + + +M TODO + +2008-07-16 23:50:54 +0200 Stephan Bosch <stephan@rename-it.nl> (68a97ad7) + + Update INSTALL file. + + +M INSTALL + +2008-07-16 23:35:23 +0200 Stephan Bosch <stephan@rename-it.nl> (eece6d40) + + Updated documentation. + + +M README +M TODO + +2008-07-16 23:22:54 +0200 Stephan Bosch <stephan@rename-it.nl> (66156bc7) + + Made runtime errors for action conflicts more user-friendly by adding + sourcecode line numbers. + + +M TODO +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2008-07-16 21:02:53 +0200 Stephan Bosch <stephan@rename-it.nl> (86706f81) + + Cleaned up generator code and added emission of source line positions for + all actions. + + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/testsuite-objects.c + +2008-07-14 23:51:56 +0200 Stephan Bosch <stephan@rename-it.nl> (59a8068d) + + Resolved various small issues. + + +M TODO +M sieve/tests/stop.sieve +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-parser.c + +2008-07-14 23:18:52 +0200 Stephan Bosch <stephan@rename-it.nl> (e2bc8e5f) + + Removed last significant printf()s from library code. + + +M TODO +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c +M src/testsuite/testsuite.c + +2008-07-14 22:33:58 +0200 Stephan Bosch <stephan@rename-it.nl> (79333170) + + Added address normalization to prevent redirect action duplicates. + + +M sieve/tests/actions.sieve +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-result.c + +2008-07-14 20:19:25 +0200 Stephan Bosch <stephan@rename-it.nl> (a0dd0dfe) + + Made "INBOX" folder name case-insensitive. + + +M src/lib-sieve/sieve-actions.c + +2008-07-14 19:57:37 +0200 Stephan Bosch <stephan@rename-it.nl> (4e78793d) + + Built result print functions thus removing various printf()s. + + +M TODO +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/copy/ext-copy.c +A src/lib-sieve/plugins/imapflags/imapflags-implicit.sieve +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/sieve-bin/sieve-test.c +M src/testsuite/testsuite.c + +2008-07-14 15:35:33 +0200 Stephan Bosch <stephan@rename-it.nl> (cbca6b3c) + + Removed various printf()s. + + +M TODO +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-result.c +M src/sieve-bin/sieve-exec.c + +2008-07-14 15:09:44 +0200 Stephan Bosch <stephan@rename-it.nl> (e3b369ee) + + Implemented support for side-effects to implicit keep and finished the + imapflags extension. + + +M README +M TODO +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/imapflags/imapflags.sieve +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/sieve-result.c + +2008-07-14 12:55:35 +0200 Stephan Bosch <stephan@rename-it.nl> (1a10419a) + + Previous change in extension interface for implicit side effect support + broke include extension. + + +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-match-types.c +M src/testsuite/ext-testsuite.c + +2008-07-14 12:19:21 +0200 Stephan Bosch <stephan@rename-it.nl> (3b694edd) + + Added support for implicit side effects and adjusted imapflags extension + accordingly. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/include/include.sieve +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +A src/lib-sieve/sieve-message.c +A src/lib-sieve/sieve-message.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2008-07-13 08:29:32 +0200 Stephan Bosch <stephan@rename-it.nl> (2165100f) + + Imapflags: flags are stored for explicit actions. + + +M TODO +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h + +2008-07-12 23:43:49 +0200 Stephan Bosch <stephan@rename-it.nl> (2cef2750) + + Imapflags: cleaned up some debug messages and fixed triggered assertion. + + +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/tag-flags.c + +2008-07-12 23:36:31 +0200 Stephan Bosch <stephan@rename-it.nl> (ca866fee) + + Forgot a few trace macros. + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c + +2008-07-12 23:22:21 +0200 Stephan Bosch <stephan@rename-it.nl> (ba7d7f88) + + Updated TODO list. + + +M TODO + +2008-07-12 23:21:03 +0200 Stephan Bosch <stephan@rename-it.nl> (4a5820ad) + + Fixed typos in some error messages. + + +M src/lib-sieve/sieve-actions.c + +2008-07-12 21:32:37 +0200 Stephan Bosch <stephan@rename-it.nl> (edfef28a) + + Improved address validation significantly. + + +M sieve/errors/out-address-errors.sieve +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +R091 src/lib-sieve/sieve-validator-address.c src/lib-sieve/sieve-address.c +A src/lib-sieve/sieve-address.h +M src/lib-sieve/sieve-validator.h + +2008-07-12 18:23:44 +0200 Stephan Bosch <stephan@rename-it.nl> (dd65eb4d) + + Added two simple test cases. + + +A src/testsuite/tests/control-structures.svtest +A src/testsuite/tests/match-types/contains.svtest + +2008-07-12 18:23:25 +0200 Stephan Bosch <stephan@rename-it.nl> (edc41252) + + Forgot trace macro for the stop command. + + +M src/lib-sieve/sieve-commands.c + +2008-07-12 18:19:04 +0200 Stephan Bosch <stephan@rename-it.nl> (fc8962d1) + + Removed llist TODO item, turns out to be less mergeable than initially + thought. + + +M TODO + +2008-06-29 20:57:42 +0200 Stephan Bosch <stephan@rename-it.nl> (141727dd) + + Testsuite: extended :matches tests. + + +M src/testsuite/tests/match-types/matches.svtest + +2008-06-29 17:58:11 +0200 Stephan Bosch <stephan@rename-it.nl> (e3033532) + + Introduced trace macro for runtime tracing and improved testsuite + implementation. + + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c +M src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test-set.c +M src/testsuite/cmd-test.c +M src/testsuite/ext-testsuite.c +M src/testsuite/tests/match-types/matches.svtest +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite.c + +2008-06-29 14:49:34 +0200 Stephan Bosch <stephan@rename-it.nl> (3cbee323) + + Testsuite: fixed CRLF bug in reading a script-specified mail message. + + +M src/lib-sieve/mcht-matches.c +M src/testsuite/mail-raw.c +M src/testsuite/tests/match-types/matches.svtest + +2008-06-29 12:09:23 +0200 Stephan Bosch <stephan@rename-it.nl> (8fbebb06) + + Fixed bugs in :matches implementation. + + +M sieve/tests/matches.sieve +M src/lib-sieve/mcht-matches.c +M src/lib-sieve/tst-header.c +M src/testsuite/tests/match-types/matches.svtest + +2008-06-28 23:37:44 +0200 Stephan Bosch <stephan@rename-it.nl> (2761af1e) + + Added testcase to the testsuite. + + +M src/lib-sieve/sieve-generator.c +A src/testsuite/tests/match-types/matches.svtest +R100 src/testsuite/tests/testsuite.sieve src/testsuite/tests/testsuite.svtest + +2008-06-28 20:13:53 +0200 Stephan Bosch <stephan@rename-it.nl> (2e03af4e) + + Updated documentation. + + +M README +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/variables/ext-variables.c + +2008-06-28 20:06:50 +0200 Stephan Bosch <stephan@rename-it.nl> (2ca344ea) + + Updated TODO. + + +M TODO + +2008-06-28 20:04:54 +0200 Stephan Bosch <stephan@rename-it.nl> (64fb240c) + + Added support for limits on the maximum number of errors collected during + compilation. + + +M TODO +M src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-validator.c +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-bin/bin-common.c +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c +M src/testsuite/testsuite.c + +2008-06-28 18:34:16 +0200 Stephan Bosch <stephan@rename-it.nl> (f9a27524) + + Updated documentation. + + +M README +M TODO + +2008-06-28 18:30:21 +0200 Stephan Bosch <stephan@rename-it.nl> (5c408f0a) + + Added compile-time address validation. + + +A sieve/errors/out-address-errors.sieve +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +D src/lib-sieve/sieve-address.c +M src/lib-sieve/sieve-commands.h +A src/lib-sieve/sieve-validator-address.c +M src/lib-sieve/sieve-validator.h + +2008-06-28 14:58:59 +0200 Stephan Bosch <stephan@rename-it.nl> (7df409aa) + + Added IMAIL rfc. + + +A doc/rfc/imail.rfc2822.txt + +2008-06-28 14:50:10 +0200 Stephan Bosch <stephan@rename-it.nl> (4dcc0210) + + Updated doc/rfc directory. + + +D doc/rfc/rfc3028.txt +R065 doc/rfc/draft-ietf-sieve-3028bis-13.txt doc/rfc/sieve.rfc5228.txt +R100 doc/rfc/rfc3629.txt doc/rfc/utf-8.rfc3629.txt + +2008-06-28 14:45:48 +0200 Stephan Bosch <stephan@rename-it.nl> (a35aa2c2) + + Updated documentation. + + +M README +M TODO + +2008-06-28 14:42:22 +0200 Stephan Bosch <stephan@rename-it.nl> (e968cf85) + + Imapflags: finished for implicit flag attachment to fileinto and keep + commands. + + +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-extensions-private.h + +2008-06-17 12:25:59 +0200 Stephan Bosch <stephan@rename-it.nl> (5cd6a700) + + Added the concept of persistent tags and implemented imapflags extension for + bare keep and fileinto commands (intermittent commit, not working properly + yet). + + +M TODO +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/vacation/cmd-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/tst-size.c +M src/testsuite/testsuite-objects.c + +2008-06-04 02:04:08 +0200 Stephan Bosch <stephan@rename-it.nl> (c1dfc976) + + Imapflags: added execution support for variables. + + +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/imapflags-variables.sieve +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2008-06-04 01:32:28 +0200 Stephan Bosch <stephan@rename-it.nl> (dc90fc9c) + + Imapflags: added validation and code support for variables. + + +M src/lib-sieve/plugins/imapflags/Makefile.am +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +A src/lib-sieve/plugins/imapflags/imapflags-variables.sieve +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h + +2008-06-03 19:03:55 +0200 Stephan Bosch <stephan@rename-it.nl> (51da5845) + + Fixed bug in duplicate argument detection. + + +M TODO +M src/lib-sieve/plugins/vacation/vacation.sieve +M src/lib-sieve/sieve-validator.c + +2008-06-03 18:10:01 +0200 Stephan Bosch <stephan@rename-it.nl> (346397cd) + + Vacation: exported command implementation to separate file. + + +M src/lib-sieve/plugins/vacation/Makefile.am +A src/lib-sieve/plugins/vacation/cmd-vacation.c +A src/lib-sieve/plugins/vacation/ext-vacation-common.h +M src/lib-sieve/plugins/vacation/ext-vacation.c + +2008-06-03 17:43:26 +0200 Stephan Bosch <stephan@rename-it.nl> (f1ba624e) + + Fixed bug in sieved. + + +M src/lib-sieve/sieve-binary.c +M src/sieve-bin/sieved.c + +2008-06-03 17:25:49 +0200 Stephan Bosch <stephan@rename-it.nl> (9a6010b5) + + Minor compile and documentation changes. + + +M INSTALL +M README +M configure.in +M src/sieve-bin/Makefile.am + +2008-06-03 13:02:00 +0200 Stephan Bosch <stephan@rename-it.nl> (f9539ec2) + + Made lda sieve plugin save and load binaries. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2008-06-03 12:10:56 +0200 Stephan Bosch <stephan@rename-it.nl> (b66c7cfd) + + Resolved all outstanding warnings. + + +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/sieve-bin/sievec.c +M src/testsuite/cmd-test.c +M src/testsuite/testsuite-common.c + +2008-06-03 11:32:18 +0200 Stephan Bosch <stephan@rename-it.nl> (3f22c88d) + + Updated documentation and fixed 'make dist'. + + +A DESIGN +M INSTALL +M Makefile.am +M README +A TODO +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/body/Makefile.am +M src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.am +M src/lib-sieve/plugins/copy/Makefile.am +M src/lib-sieve/plugins/imapflags/Makefile.am +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/include/Makefile.am +M src/lib-sieve/plugins/regex/Makefile.am +M src/lib-sieve/plugins/relational/Makefile.am +M src/lib-sieve/plugins/subaddress/Makefile.am +M src/lib-sieve/plugins/vacation/Makefile.am +M src/lib-sieve/plugins/variables/Makefile.am + +2008-05-29 10:10:49 +0200 Stephan Bosch <stephan@rename-it.nl> (7e5c0211) + + Testsuite: added test_fail command. + + +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/testsuite/Makefile.am +A src/testsuite/cmd-test-fail.c +M src/testsuite/cmd-test.c +M src/testsuite/ext-testsuite.c +M src/testsuite/tests/testsuite.sieve +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h + +2008-05-29 01:57:55 +0200 Stephan Bosch <stephan@rename-it.nl> (67dc990f) + + Testsuite: added 'test' command to group sieve statements into a test. + + +M src/lib-sieve/cmd-if.c +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/testsuite/Makefile.am +M src/testsuite/cmd-test-set.c +A src/testsuite/cmd-test.c +M src/testsuite/ext-testsuite.c +M src/testsuite/tests/testsuite.sieve +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-objects.c + +2008-05-27 17:47:24 +0200 Stephan Bosch <stephan@rename-it.nl> (5e293402) + + Testsuite: added support for test object members. + + +M src/testsuite/cmd-test-set.c +M src/testsuite/ext-testsuite.c +M src/testsuite/tests/testsuite.sieve +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite-objects.c +M src/testsuite/testsuite-objects.h + +2008-05-25 12:48:24 +0200 Stephan Bosch <stephan@rename-it.nl> (d8bd4292) + + Testsuite: exported testsuit object interface to separate files. + + +M src/testsuite/Makefile.am +M src/testsuite/cmd-test-set.c +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +A src/testsuite/testsuite-objects.c +A src/testsuite/testsuite-objects.h + +2008-05-25 12:25:47 +0200 Stephan Bosch <stephan@rename-it.nl> (52d25c52) + + Testsuite: implemented testsuite object interface. + + +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-extensions-private.h +M src/testsuite/Makefile.am +R051 src/testsuite/cmd-test-message.c src/testsuite/cmd-test-set.c +M src/testsuite/ext-testsuite.c +M src/testsuite/tests/testsuite.sieve +M src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h + +2008-05-21 16:24:13 +0200 Stephan Bosch <stephan@rename-it.nl> (356ba5cc) + + vacation: added TODO regarding duplicate tagged arguments to the vacation + command. + + +M README +A src/lib-sieve/plugins/vacation/vacation-errors.sieve + +2008-05-21 16:23:12 +0200 Stephan Bosch <stephan@rename-it.nl> (2c5b0d7c) + + testsuite: removed spurious binary from repository. + + +M .hgignore +D src/testsuite/testsuite + +2008-05-21 12:58:31 +0200 Stephan Bosch <stephan@rename-it.nl> (a74fc814) + + Testsuite: setting message content works. + + +M configure.in +M src/testsuite/Makefile.am +M src/testsuite/cmd-test-message.c +M src/testsuite/mail-raw.c +M src/testsuite/tests/testsuite.sieve +M src/testsuite/testsuite +A src/testsuite/testsuite-common.c +M src/testsuite/testsuite-common.h +M src/testsuite/testsuite.c + +2008-05-21 00:29:40 +0200 Stephan Bosch <stephan@rename-it.nl> (98274544) + + Fixed execution of initial testsuite implementation. + + +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-extensions-private.h +M src/lib-sieve/sieve-extensions.c +M src/testsuite/cmd-test-message.c +M src/testsuite/ext-testsuite.c +M src/testsuite/testsuite +M src/testsuite/testsuite.c + +2008-05-20 17:31:45 +0200 Stephan Bosch <stephan@rename-it.nl> (9e50d466) + + Properly implemented dumping a binary including a list of required + extensions and support for extension-specific output. + + +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/include/ext-include-binary.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-binary-dumper.c +M src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-match-types.c +M src/testsuite/testsuite + +2008-05-18 18:03:19 +0200 Stephan Bosch <stephan@rename-it.nl> (40747643) + + RECOVERED FROM INCONSISTENCY: developed testsuite and binary dumping and + fixed various small issues. + + +M .hgignore +M src/Makefile.am +M src/lib-sieve/Makefile.am +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/imapflags.sieve +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-arguments.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-address-parts.c +A src/lib-sieve/sieve-binary-dumper.c +A src/lib-sieve/sieve-binary-dumper.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +A src/lib-sieve/sieve-dump.h +M src/lib-sieve/sieve-extensions-private.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve.c +M src/lib-sieve/tst-header.c +A src/testsuite/Makefile.am +A src/testsuite/cmd-test-message.c +A src/testsuite/ext-testsuite.c +A src/testsuite/mail-raw.c +A src/testsuite/mail-raw.h +A src/testsuite/namespaces.c +A src/testsuite/namespaces.h +A src/testsuite/tests/testsuite.sieve +A src/testsuite/testsuite +A src/testsuite/testsuite-common.h +A src/testsuite/testsuite.c + +2008-04-06 22:02:08 +0200 Stephan Bosch <stephan@rename-it.nl> (5148f381) + + Updated documentation. + + +M README + +2008-04-06 21:57:32 +0200 Stephan Bosch <stephan@rename-it.nl> (dd105ea5) + + Include: merged import and export commands into a single implementation and + implemented global variable storage. + + +M src/lib-sieve/plugins/include/Makefile.am +D src/lib-sieve/plugins/include/cmd-export.c +M src/lib-sieve/plugins/include/cmd-import.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/include-variables.sieve +M src/lib-sieve/plugins/include/include-variables1.sieve +M src/lib-sieve/plugins/include/include-variables2.sieve +A src/lib-sieve/plugins/include/include-variables3.sieve +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables-operands.c +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2008-04-06 15:16:37 +0200 Stephan Bosch <stephan@rename-it.nl> (d0d6216f) + + Variables: exported new operand definitions to separate file. + + +M README +M src/lib-sieve/plugins/variables/Makefile.am +M src/lib-sieve/plugins/variables/ext-variables-common.c +A src/lib-sieve/plugins/variables/ext-variables-operands.c +A src/lib-sieve/plugins/variables/ext-variables-operands.h +M src/lib-sieve/plugins/variables/ext-variables.c + +2008-04-05 18:14:17 +0200 Stephan Bosch <stephan@rename-it.nl> (86364f53) + + Variables: exported new argument definitions to separate file. + + +M src/lib-sieve/plugins/variables/Makefile.am +A src/lib-sieve/plugins/variables/ext-variables-arguments.c +A src/lib-sieve/plugins/variables/ext-variables-arguments.h +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables.c + +2008-04-05 16:58:18 +0200 Stephan Bosch <stephan@rename-it.nl> (c4612dce) + + Include: implemented global variable scope. + + +M src/lib-sieve/plugins/include/cmd-export.c +M src/lib-sieve/plugins/include/cmd-import.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-variables.c +M src/lib-sieve/plugins/include/ext-include-variables.h + +2008-04-03 17:10:58 +0200 Stephan Bosch <stephan@rename-it.nl> (36e5af33) + + Added -c option to sieve-test to force compile. + + +M README +M src/sieve-bin/sieve-test.c + +2008-03-24 23:29:00 +0100 Stephan Bosch <stephan@rename-it.nl> (fbbe6f49) + + Updated documentation. + + +M README +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/variables/ext-variables.c + +2008-03-24 23:12:00 +0100 Stephan Bosch <stephan@rename-it.nl> (d728ffb3) + + Include: moved variables support to separate file. + + +M src/lib-sieve/plugins/include/Makefile.am +M src/lib-sieve/plugins/include/cmd-export.c +M src/lib-sieve/plugins/include/cmd-import.c +M src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +A src/lib-sieve/plugins/include/ext-include-variables.c +A src/lib-sieve/plugins/include/ext-include-variables.h +M src/lib-sieve/plugins/include/include-variables1.sieve +M src/lib-sieve/plugins/include/include-variables2.sieve + +2008-03-24 22:07:07 +0100 Stephan Bosch <stephan@rename-it.nl> (4b8dc91a) + + Include: moved implementation of binary extension to separate file. + + +M src/lib-sieve/plugins/include/Makefile.am +M src/lib-sieve/plugins/include/cmd-export.c +A src/lib-sieve/plugins/include/ext-include-binary.c +A src/lib-sieve/plugins/include/ext-include-binary.h +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include.c + +2008-03-24 20:39:05 +0100 Stephan Bosch <stephan@rename-it.nl> (5f9a9f99) + + Include: added AST context and now export context detectects export of + imported variables. + + +M src/lib-sieve/plugins/include/cmd-export.c +M src/lib-sieve/plugins/include/cmd-import.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include.c +A src/lib-sieve/plugins/include/include-variables-error2.sieve +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h + +2008-03-24 15:08:20 +0100 Stephan Bosch <stephan@rename-it.nl> (95a88e1f) + + Include: moved script existance validation back to validation stage. + + +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +A src/lib-sieve/plugins/include/include-error.sieve +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h + +2008-03-24 01:01:05 +0100 Stephan Bosch <stephan@rename-it.nl> (c6e94477) + + Include: made import and export commands check whether the variables + extension is active. + + +M src/lib-sieve/plugins/include/Makefile.am +M src/lib-sieve/plugins/include/cmd-export.c +M src/lib-sieve/plugins/include/cmd-import.c +A src/lib-sieve/plugins/include/include-variables-error.sieve +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2008-03-23 23:56:50 +0100 Stephan Bosch <stephan@rename-it.nl> (a43e9271) + + Include: added skeleton import and export commands. + + +M src/lib-sieve/plugins/include/Makefile.am +A src/lib-sieve/plugins/include/cmd-export.c +A src/lib-sieve/plugins/include/cmd-import.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include.c +A src/lib-sieve/plugins/include/include-variables.sieve +A src/lib-sieve/plugins/include/include-variables1.sieve +A src/lib-sieve/plugins/include/include-variables2.sieve +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-script.c + +2008-03-23 19:14:51 +0100 Stephan Bosch <stephan@rename-it.nl> (d91124d5) + + Updated TODO. + + +M README + +2008-03-23 18:42:18 +0100 Stephan Bosch <stephan@rename-it.nl> (2d4e8c07) + + Regex: added match values support. + + +M src/lib-sieve/plugins/regex/mcht-regex.c +M src/lib-sieve/plugins/variables/Makefile.am +A src/lib-sieve/plugins/variables/variables-regex.sieve +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h + +2008-03-23 16:03:02 +0100 Stephan Bosch <stephan@rename-it.nl> (a5b4c2c5) + + Relational: split match-type implementation into separate file. + + +M src/lib-sieve/plugins/relational/Makefile.am +A src/lib-sieve/plugins/relational/ext-relational-common.c +A src/lib-sieve/plugins/relational/ext-relational-common.h +M src/lib-sieve/plugins/relational/ext-relational.c +A src/lib-sieve/plugins/relational/mcht-count.c +A src/lib-sieve/plugins/relational/mcht-value.c + +2008-03-23 15:03:54 +0100 Stephan Bosch <stephan@rename-it.nl> (4192b800) + + Regex: split match type implementation into separate file. + + +M src/lib-sieve/plugins/regex/Makefile.am +A src/lib-sieve/plugins/regex/ext-regex-common.h +M src/lib-sieve/plugins/regex/ext-regex.c +A src/lib-sieve/plugins/regex/mcht-regex.c + +2008-03-23 11:20:50 +0100 Stephan Bosch <stephan@rename-it.nl> (eaae9678) + + Exported match type implementations to separate files. + + +M src/lib-sieve/Makefile.am +A src/lib-sieve/mcht-contains.c +A src/lib-sieve/mcht-is.c +A src/lib-sieve/mcht-matches.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h + +2008-03-22 18:35:48 +0100 Stephan Bosch <stephan@rename-it.nl> (a493b63b) + + Finished :matches function for now, but it can still be improved and it + needs more testing. + + +M src/lib-sieve/plugins/variables/variables-match.sieve +M src/lib-sieve/sieve-match-types.c + +2008-03-09 20:36:42 +0100 Stephan Bosch <stephan@rename-it.nl> (8a09df74) + + Revised :matches function, but did finish. + + +M src/lib-sieve/plugins/variables/variables-match.sieve +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h + +2008-03-08 01:05:38 +0100 Stephan Bosch <stephan@rename-it.nl> (188a18a5) + + Variables: fixed bug in match value indexing. + + +M src/lib-sieve/plugins/variables/variables-match.sieve +M src/lib-sieve/sieve-match-types.c + +2008-03-08 00:28:34 +0100 Stephan Bosch <stephan@rename-it.nl> (1935269d) + + Variables: First work towards match value support. + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/tst-string.c +A src/lib-sieve/plugins/variables/variables-match.sieve +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-header.c + +2008-02-28 23:43:36 +0100 Stephan Bosch <stephan@rename-it.nl> (6c74642f) + + Updated documentation. + + +M README +M src/lib-sieve/plugins/variables/ext-variables.c + +2008-02-28 23:21:03 +0100 Stephan Bosch <stephan@rename-it.nl> (65fe3d7c) + + Variables: added variable name parsing to the set command and added error + handling. + + +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/variables-errors.sieve + +2008-02-28 22:10:44 +0100 Stephan Bosch <stephan@rename-it.nl> (83b1f62e) + + Variables: exported namespace+variable parsing to separate file. + + +M src/lib-sieve/plugins/variables/Makefile.am +M src/lib-sieve/plugins/variables/ext-variables-common.c +A src/lib-sieve/plugins/variables/ext-variables-name.c +A src/lib-sieve/plugins/variables/ext-variables-name.h +A src/lib-sieve/plugins/variables/variables-nspace.sieve + +2008-02-28 21:30:33 +0100 Stephan Bosch <stephan@rename-it.nl> (4c929247) + + Variables: exported namespace+variable parsing to separate function. + + +M src/lib-sieve/plugins/variables/ext-variables-common.c + +2008-02-28 11:04:29 +0100 Stephan Bosch <stephan@rename-it.nl> (8bd12076) + + Updated documentation. + + +M README + +2008-02-27 23:55:24 +0100 Stephan Bosch <stephan@rename-it.nl> (2ffba54f) + + Variables: added parsing support for namespaces. + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/plugins/variables/ext-variables-common.c + +2008-02-27 20:38:43 +0100 Stephan Bosch <stephan@rename-it.nl> (5d741fcd) + + Variables: fixed string test. + + +M src/lib-sieve/plugins/variables/tst-string.c + +2008-02-26 09:55:39 +0100 Stephan Bosch <stephan@rename-it.nl> (4101df7d) + + Expand ~ to home in sieve path. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2008-02-25 17:56:56 +0100 Stephan Bosch <stephan@rename-it.nl> (68da5027) + + Fixed indent in sieve-banary.c + + +M src/lib-sieve/sieve-binary.c + +2008-02-25 17:33:12 +0100 Stephan Bosch <stephan@rename-it.nl> (53258ecd) + + Simplified needlessly complex assignment. + + +M src/lib-sieve/sieve-script.c + +2008-02-25 17:30:53 +0100 Stephan Bosch <stephan@rename-it.nl> (9b8e94bb) + + Added TODO item. + + +M README + +2008-02-25 17:27:39 +0100 Stephan Bosch <stephan@rename-it.nl> (d3bfafef) + + Avoid direct to_lower() invocations; replaced by i_tolower(). + + +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/sieve-comparators.c + +2008-02-25 17:19:40 +0100 Stephan Bosch <stephan@rename-it.nl> (5b654ed2) + + Updated documentation. + + +M README + +2008-02-25 17:17:46 +0100 Stephan Bosch <stephan@rename-it.nl> (5687d842) + + Changed various p_new(pool_datastack_create(),) invocations to t_new() + + +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-match-types.c + +2008-02-25 17:04:48 +0100 Stephan Bosch <stephan@rename-it.nl> (c43f035f) + + Envelope: changed p_array_init(,pool_datastack_create(),) into + t_array_init(,) + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/plugins/variables/variables.sieve + +2008-02-25 16:57:07 +0100 Stephan Bosch <stephan@rename-it.nl> (be81f60a) + + Updated documentation. + + +M README + +2008-02-23 23:59:25 +0100 Stephan Bosch <stephan@rename-it.nl> (df66a8ed) + + Variables: fixed bug in string-list containing variables. + + +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/variables.sieve +M src/lib-sieve/sieve-code.c + +2008-02-23 22:17:54 +0100 Stephan Bosch <stephan@rename-it.nl> (7d36798b) + + Fixed bugs in string substitution support and the regex extension. + + +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/plugins/variables/variables.sieve +M src/lib-sieve/sieve-commands.c + +2008-02-23 18:47:10 +0100 Stephan Bosch <stephan@rename-it.nl> (6ea9cce1) + + Variables: updated included specification to new RFC 5229. + + +D src/lib-sieve/plugins/variables/draft-ietf-sieve-variables-08.txt +M src/lib-sieve/plugins/variables/ext-variables.c +A src/lib-sieve/plugins/variables/rfc5229.txt + +2008-02-23 00:49:36 +0100 Stephan Bosch <stephan@rename-it.nl> (a1dc327b) + + Updated documentation. + + +M README + +2008-02-23 00:24:08 +0100 Stephan Bosch <stephan@rename-it.nl> (f5e9b9ce) + + Variables: made variable identifiers case insensitive. + + +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/variables.sieve + +2008-02-22 23:29:06 +0100 Stephan Bosch <stephan@rename-it.nl> (03e43440) + + Variables: added check for equal precedence and added comment. + + +M src/lib-sieve/plugins/variables/cmd-set.c +A src/lib-sieve/plugins/variables/variables-errors.sieve + +2008-02-22 22:29:08 +0100 Stephan Bosch <stephan@rename-it.nl> (f4156454) + + Variables: activated 'quotewildcard' set modifier and fixed a bug. + + +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/variables.sieve + +2008-02-22 21:22:43 +0100 Stephan Bosch <stephan@rename-it.nl> (b7f46207) + + Variables: activated 'length' set modifier. + + +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/variables.sieve + +2008-02-22 20:49:14 +0100 Stephan Bosch <stephan@rename-it.nl> (7fcf3e32) + + Variables: activated support for set command modifiers. + + +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/variables.sieve + +2008-02-22 17:19:39 +0100 Stephan Bosch <stephan@rename-it.nl> (4aefe421) + + Adjusted body extension to compile with dovecot past 1.1.beta16 (message + parser changes) + + +M src/lib-sieve/plugins/body/ext-body-common.c + +2008-02-14 12:20:36 +0100 Stephan Bosch <stephan@rename-it.nl> (a12b44f5) + + Added notice about the omission CMU code to the AUTHORS file. + + +M AUTHORS + +2008-02-14 12:16:29 +0100 Stephan Bosch <stephan@rename-it.nl> (c8a4690e) + + Assigned proper package version and name. + + +M .hgignore +M configure.in + +2008-02-14 11:39:59 +0100 Stephan Bosch <stephan@rename-it.nl> (8fd8b8ae) + + Removed duplicate licence. + + +M .hgignore +A COPYING + +2008-02-14 11:39:22 +0100 Stephan Bosch <stephan@rename-it.nl> (b6123c0e) + + Added maintainermode functions to Makefile.am + + +M Makefile.am + +2008-02-13 13:24:35 +0100 Stephan Bosch <stephan@rename-it.nl> (81324947) + + Incorporated changes in dovecot-1.1 + + +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve.c +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2008-02-11 09:59:02 +0100 Stephan Bosch <stephan@rename-it.nl> (c3678c45) + + Variables: set modifiers are now sorted. + + +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/variables.sieve + +2008-02-10 16:41:20 +0100 Stephan Bosch <stephan@rename-it.nl> (792852f3) + + Added code support for set modifiers. + + +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2008-01-06 01:26:12 +0100 Stephan Bosch <stephan@rename-it.nl> (6a490856) + + Fixed bugs in validation error handling and fixed bugs in dynamic argument + support. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/plugins/variables/variables.sieve +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c + +2008-01-05 23:11:59 +0100 Stephan Bosch <stephan@rename-it.nl> (53ea2603) + + First successful variable substitutions. + + +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/variables.sieve +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-validator.c + +2008-01-05 02:25:41 +0100 Stephan Bosch <stephan@rename-it.nl> (5e2e9f9b) + + Merged concurrent changes. + + +2008-01-05 02:24:29 +0100 Stephan Bosch <stephan@rename-it.nl> (3337b5df) + + Changed operand read API to get access to the runtime environment inside the + read functions. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/sieve-ext-variables.h +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c + +2008-01-04 17:50:23 +0100 Stephan Bosch <stephan@rename-it.nl> (ca44fcdc) + + Minor fix in the error reporting of the sieve parser. + + +M sieve/errors/interesting.sieve +M src/lib-sieve/sieve-parser.c + +2008-01-04 01:53:00 +0100 Stephan Bosch <stephan@rename-it.nl> (6a1ff206) + + Implemented dynamic sieve_get_capabilities() for proper MANAGESIEVE support. + + +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve.c + +2008-01-04 01:11:56 +0100 Stephan Bosch <stephan@rename-it.nl> (020fe587) + + Published compiler API using script objects instead of paths. + + +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h + +2008-01-04 00:45:32 +0100 Stephan Bosch <stephan@rename-it.nl> (c752483a) + + Fixed segfault occuring when command did not exist. + + +M src/lib-sieve/sieve-validator.c + +2008-01-04 00:10:37 +0100 Stephan Bosch <stephan@rename-it.nl> (03c3f569) + + Small changes: removed T_FRAME and improved an error message. + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-script.c + +2008-01-03 20:28:10 +0100 Stephan Bosch <stephan@rename-it.nl> (5d7f1005) + + Implemented required features for use with MANAGESIEVE service. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/sieve-binary.c +A src/lib-sieve/sieve-error-private.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-result.c +A src/lib-sieve/sieve-script-private.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-bin/bin-common.c +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c + +2008-01-03 01:49:54 +0100 Stephan Bosch <stephan@rename-it.nl> (8b47f293) + + Added strbuf error handler. + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h + +2007-12-30 03:35:40 +0100 Stephan Bosch <stephan@rename-it.nl> (3cc0395d) + + Added variable operand to the variables extension. + + +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-match-types.c + +2007-12-30 02:23:24 +0100 Stephan Bosch <stephan@rename-it.nl> (aa8f3937) + + Added support for adding new types operands to the engine. + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-match-types.c + +2007-12-30 01:49:45 +0100 Stephan Bosch <stephan@rename-it.nl> (91438bbe) + + Defined variable argument for the variables extension. + + +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +A src/lib-sieve/plugins/variables/sieve-ext-variables.h + +2007-12-29 16:20:54 +0100 Stephan Bosch <stephan@rename-it.nl> (97987192) + + Changed validation and generation of string list argument to fully support + the new string list encoding. + + +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h + +2007-12-29 15:25:30 +0100 Stephan Bosch <stephan@rename-it.nl> (c14634ab) + + Changed encoding of stringlist. Now it contains string operands in stead of + bare strings. + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-code.c + +2007-12-29 05:54:31 +0100 Stephan Bosch <stephan@rename-it.nl> (aed4bf79) + + Removed obsolete code. + + +M src/lib-sieve/sieve-extensions-private.h + +2007-12-29 05:42:08 +0100 Stephan Bosch <stephan@rename-it.nl> (b4d68be1) + + Removed much code duplication between extensions that provide support for + further extension. + + +M sieve/tests/address-part.sieve +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-extensions-private.h +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-validator.c + +2007-12-27 14:42:41 +0100 Stephan Bosch <stephan@rename-it.nl> (817b48ce) + + Further migrated implementation of extensions to new extension architecture. + + +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-extensions-private.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h + +2007-12-27 01:24:42 +0100 Stephan Bosch <stephan@rename-it.nl> (9846f24f) + + Major changes in the extensions support. + + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/copy/copy.sieve +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/plugins/variables/cmd-set.c +M src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables.c +M src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +A src/lib-sieve/sieve-extensions-private.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c + +2007-12-26 15:40:50 +0100 Stephan Bosch <stephan@rename-it.nl> (1b1d60f8) + + Changed implementation of command context handling and instanced tags to + avoid duplicate lookups. + + +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h + +2007-12-26 14:00:12 +0100 Stephan Bosch <stephan@rename-it.nl> (6ca7825d) + + Further developed the variables extension. + + +M src/lib-sieve/plugins/variables/Makefile.am +A src/lib-sieve/plugins/variables/cmd-set.c +A src/lib-sieve/plugins/variables/ext-variables-common.c +A src/lib-sieve/plugins/variables/ext-variables-common.h +M src/lib-sieve/plugins/variables/ext-variables.c +A src/lib-sieve/plugins/variables/tst-string.c +M src/lib-sieve/plugins/variables/variables.sieve + +2007-12-25 16:16:15 +0100 Stephan Bosch <stephan@rename-it.nl> (549382e0) + + Started skeleton implementation of variables extension. + + +M README +M configure.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/variables/Makefile.am +A src/lib-sieve/plugins/variables/draft-ietf-sieve-variables-08.txt +A src/lib-sieve/plugins/variables/ext-variables.c +A src/lib-sieve/plugins/variables/variables.sieve +M src/lib-sieve/sieve-extensions.c + +2007-12-25 12:40:06 +0100 Stephan Bosch <stephan@rename-it.nl> (82e4024e) + + Fixed non-standard behavior for the encoded-character extension. + + +M sieve/tests/encoded-character.sieve +M src/lib-sieve/ext-encoded-character.c + +2007-12-25 12:06:41 +0100 Stephan Bosch <stephan@rename-it.nl> (d2cbd795) + + Finished encoded-character extension. + + +M README +A sieve/errors/encoded-character.sieve +M sieve/tests/encoded-character.sieve +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/sieve-bin/mail-raw.c + +2007-12-25 11:07:31 +0100 Stephan Bosch <stephan@rename-it.nl> (151cb427) + + Added UTF-8 rfc to doc/rfc directory. + + +A doc/rfc/rfc3629.txt + +2007-12-25 11:07:01 +0100 Stephan Bosch <stephan@rename-it.nl> (54f7acfd) + + Built a little more extensive tests for the encoded-character extension. + + +M sieve/tests/encoded-character.sieve +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/sieve-validator.c + +2007-12-24 16:11:33 +0100 Stephan Bosch <stephan@rename-it.nl> (56aa3902) + + Encoded character extension basicly works, but no unicode support is + implemented. + + +M sieve/tests/encoded-character.sieve +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c + +2007-12-19 14:51:36 +0100 Stephan Bosch <stephan@rename-it.nl> (688742fa) + + Implemented support for overriding default argument implementations of + number, string and string-list. + + +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/ext-encoded-character.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c + +2007-12-18 23:46:46 +0100 Stephan Bosch <stephan@rename-it.nl> (b8dc1073) + + Added sieve rfc and new sieve 3028bis to the doc/rfc directory. + + +A doc/rfc/draft-ietf-sieve-3028bis-13.txt +A doc/rfc/rfc3028.txt + +2007-12-18 23:46:00 +0100 Stephan Bosch <stephan@rename-it.nl> (0281b79a) + + Removed erroneous rfc file from new doc dir. + + +D doc/rfc + +2007-12-18 23:41:39 +0100 Stephan Bosch <stephan@rename-it.nl> (1a1dc484) + + Forgot to add new files. + + +A doc/rfc +A sieve/tests/encoded-character.sieve +A src/lib-sieve/ext-encoded-character.c + +2007-12-18 23:38:32 +0100 Stephan Bosch <stephan@rename-it.nl> (7823beb1) + + Updated documentation. + + +M README + +2007-12-18 23:34:08 +0100 Stephan Bosch <stephan@rename-it.nl> (b868111d) + + Started skeleton for the encoded-character extension. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/sieve-extensions.c + +2007-12-18 23:14:13 +0100 Stephan Bosch <stephan@rename-it.nl> (ab8d5d31) + + Updated TODO list. + + +M README + +2007-12-18 23:11:18 +0100 Stephan Bosch <stephan@rename-it.nl> (2274e9fe) + + Updated documentation. + + +M README +M src/lib-sieve/plugins/body/ext-body.c + +2007-12-18 23:00:47 +0100 Stephan Bosch <stephan@rename-it.nl> (93a757ca) + + Changed imapflags extension to use the message context instead of the + interpreter context. + + +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c + +2007-12-18 22:43:21 +0100 Stephan Bosch <stephan@rename-it.nl> (0cbc4a05) + + Changed body extension to use the message context instead of the interpreter + context. + + +M src/lib-sieve/plugins/body/ext-body-common.c + +2007-12-18 22:40:03 +0100 Stephan Bosch <stephan@rename-it.nl> (ef12c613) + + Introduced message context to give extensions the ability to associate + context data with the currently processed message. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h + +2007-12-18 21:39:31 +0100 Stephan Bosch <stephan@rename-it.nl> (3b8a1988) + + Updated documentation. + + +M README +M src/lib-sieve/plugins/body/ext-body.c + +2007-12-18 21:19:06 +0100 Stephan Bosch <stephan@rename-it.nl> (01f58520) + + Fixed minor bug in the body extension. + + +M src/lib-sieve/plugins/body/body.sieve +M src/lib-sieve/plugins/body/ext-body-common.c +M src/lib-sieve/plugins/body/tst-body.c + +2007-12-18 21:08:06 +0100 Stephan Bosch <stephan@rename-it.nl> (ddfd461e) + + Implemented evaluation for the body test introduced by the body extension. + + +M AUTHORS +M src/lib-sieve/plugins/body/Makefile.am +A src/lib-sieve/plugins/body/body.sieve +A src/lib-sieve/plugins/body/ext-body-common.c +A src/lib-sieve/plugins/body/ext-body-common.h +M src/lib-sieve/plugins/body/ext-body.c +A src/lib-sieve/plugins/body/tst-body.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/tst-header.c + +2007-12-18 16:41:42 +0100 Stephan Bosch <stephan@rename-it.nl> (0b27d776) + + Implemented validation and code generation for body extension. + + +M src/lib-sieve/plugins/body/ext-body.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h + +2007-12-18 15:11:24 +0100 Stephan Bosch <stephan@rename-it.nl> (345703f3) + + Started skeleton for the body extension. + + +M README +M configure.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/body/Makefile.am +A src/lib-sieve/plugins/body/draft-ietf-sieve-body-07.txt +A src/lib-sieve/plugins/body/ext-body.c + +2007-12-18 01:08:02 +0100 Stephan Bosch <stephan@rename-it.nl> (cad1f74f) + + Updated documentation. + + +M README +M src/lib-sieve/plugins/include/ext-include.c + +2007-12-18 00:38:58 +0100 Stephan Bosch <stephan@rename-it.nl> (1abd9f94) + + Implemented return command for include extension. + + +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/cmd-return.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/included2.sieve +M src/lib-sieve/sieve-binary.c + +2007-12-18 00:11:02 +0100 Stephan Bosch <stephan@rename-it.nl> (c661d5db) + + Basic include functionality seems to be working and if source scripts are + changed the binary is always recompiled. + + +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-error.c + +2007-12-16 18:35:04 +0100 Stephan Bosch <stephan@rename-it.nl> (c3ffb25d) + + Working towards proper dependency handling for sieve binaries. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve.c + +2007-12-16 00:49:46 +0100 Stephan Bosch <stephan@rename-it.nl> (56cb692d) + + Added support for lazy binary load. + + +M src/lib-sieve/sieve-binary.c + +2007-12-15 23:16:16 +0100 Stephan Bosch <stephan@rename-it.nl> (9f9ec317) + + Added internal support for different methods of loading a binary. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/sieve-binary.c + +2007-12-15 21:30:00 +0100 Stephan Bosch <stephan@rename-it.nl> (abe54c85) + + Working towards complete binary support for the include extension. + + +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve.c +M src/sieve-bin/sieved.c + +2007-12-14 18:34:02 +0100 Stephan Bosch <stephan@rename-it.nl> (898aa186) + + Updated documentation. + + +M README + +2007-12-14 02:20:41 +0100 Stephan Bosch <stephan@rename-it.nl> (d0171770) + + Fixed bug regarding stop command in combination with include extension. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/included2.sieve +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-interpreter.c + +2007-12-14 01:57:58 +0100 Stephan Bosch <stephan@rename-it.nl> (28ed01a2) + + Simplified the include loop a little. + + +M src/lib-sieve/plugins/include/ext-include-common.c + +2007-12-14 01:41:14 +0100 Stephan Bosch <stephan@rename-it.nl> (95ea119b) + + Implemented mostly untested deep-level include execution support. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/include.sieve +M src/lib-sieve/plugins/include/included2.sieve +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h + +2007-12-13 22:59:24 +0100 Stephan Bosch <stephan@rename-it.nl> (c061f389) + + First successful (single level) execution of four consecutive includes. + + +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve.c + +2007-12-13 17:45:38 +0100 Stephan Bosch <stephan@rename-it.nl> (67a5e20b) + + Added support for interrupting an interpreter and continuing execution + later. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h + +2007-12-13 13:23:41 +0100 Stephan Bosch <stephan@rename-it.nl> (5aa15bb3) + + Include extension now generates include opcode. Not executable yet though. + + +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include.c + +2007-12-13 11:58:17 +0100 Stephan Bosch <stephan@rename-it.nl> (db2a3ef0) + + Implemented the binary_free event for binary extensions. Script references + in the include extension are now properly released. + + +M src/lib-sieve/sieve-binary.c + +2007-12-13 11:42:50 +0100 Stephan Bosch <stephan@rename-it.nl> (9848bb77) + + Fixed behavior of binary object with respect to pre-loaded extensons. Broke + it with last change. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-common.h + +2007-12-13 01:20:59 +0100 Stephan Bosch <stephan@rename-it.nl> (fa295e4b) + + Changed binary object's extension linkage for extending the binary itself. + + +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h + +2007-12-11 12:44:57 +0100 Stephan Bosch <stephan@rename-it.nl> (ad733634) + + Doubly included scripts are no longer compiled and included multiple times. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h + +2007-12-11 11:23:53 +0100 Stephan Bosch <stephan@rename-it.nl> (1d9b48ba) + + Forgot to set the number of blocks in the binary header. + + +M src/lib-sieve/plugins/include/included1.sieve +M src/lib-sieve/sieve-binary.c + +2007-12-11 10:55:05 +0100 Stephan Bosch <stephan@rename-it.nl> (e1f26173) + + Re-established circular include detection for include extension. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/included1.sieve + +2007-12-11 11:38:42 +0100 Stephan Bosch <stephan@rename-it.nl> (f49a0473) + + Further developed the include extension to compile included scripts in + additional blocks of the binary. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/included1.sieve +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve.c + +2007-12-10 18:59:44 +0100 Stephan Bosch <stephan@rename-it.nl> (8d3d12c1) + + Further developed the binary format: binary can now contain multiple blocks + with arbitrary data. + + +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve.c + +2007-12-10 11:08:13 +0100 Stephan Bosch <stephan@rename-it.nl> (ee92eea1) + + Updated documentation: Changed priorities in TODO list. + + +M README + +2007-12-10 11:01:40 +0100 Stephan Bosch <stephan@rename-it.nl> (09775f2c) + + Updated documentation. + + +M README + +2007-12-09 23:22:33 +0100 Stephan Bosch <stephan@rename-it.nl> (4fccec75) + + Moved actual include operation from validator to generator stage. + + +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/include/included1.sieve +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c +M src/sieve-bin/sieved.c + +2007-12-09 19:59:47 +0100 Stephan Bosch <stephan@rename-it.nl> (beeed72c) + + Sieve executables now work with binaries too. + + +M .hgignore +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/sieve-bin/bin-common.c +M src/sieve-bin/bin-common.h +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c +M src/sieve-bin/sievec.c + +2007-12-09 17:42:36 +0100 Stephan Bosch <stephan@rename-it.nl> (c255daa0) + + Made a basic implementation of saving binaries to disk. + + +M .hgignore +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-script.c +M src/sieve-bin/Makefile.am +M src/sieve-bin/sievec.c +A src/sieve-bin/sieved.c + +2007-12-08 15:23:21 +0100 Stephan Bosch <stephan@rename-it.nl> (e7bb1789) + + Cleaned up ast implementation a little. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/include.sieve +M src/lib-sieve/plugins/include/included2.sieve +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve.c + +2007-12-08 14:11:04 +0100 Stephan Bosch <stephan@rename-it.nl> (d24e1789) + + Prevented more scripts from being included when errors have occured. + + +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/included2.sieve +M src/lib-sieve/plugins/include/included3.sieve +M src/lib-sieve/sieve.c + +2007-12-08 13:13:26 +0100 Stephan Bosch <stephan@rename-it.nl> (b01bd7c9) + + Properly implemented circular include detection for the include extension. + + +M src/lib-sieve/plugins/include/cmd-include.c +M src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/included3.sieve +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-script.c +M src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve.c + +2007-12-08 00:08:12 +0100 Stephan Bosch <stephan@rename-it.nl> (23ce5aba) + + First defined an encapsulating script object and implemented part of the + include extension. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/include/Makefile.am +M src/lib-sieve/plugins/include/cmd-include.c +A src/lib-sieve/plugins/include/ext-include-common.c +M src/lib-sieve/plugins/include/ext-include-common.h +M src/lib-sieve/plugins/include/ext-include.c +M src/lib-sieve/plugins/include/include.sieve +A src/lib-sieve/plugins/include/included1.sieve +A src/lib-sieve/plugins/include/included2.sieve +A src/lib-sieve/plugins/include/included3.sieve +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-parser.h +A src/lib-sieve/sieve-script.c +A src/lib-sieve/sieve-script.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h + +2007-12-07 01:17:48 +0100 Stephan Bosch <stephan@rename-it.nl> (c69e9040) + + Started skeleton implementation for the include extension. + + +M README +M configure.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/include/Makefile.am +A src/lib-sieve/plugins/include/cmd-include.c +A src/lib-sieve/plugins/include/cmd-return.c +A src/lib-sieve/plugins/include/draft-daboo-sieve-include-05.txt +A src/lib-sieve/plugins/include/ext-include-common.h +A src/lib-sieve/plugins/include/ext-include.c +A src/lib-sieve/plugins/include/include.sieve +M src/lib-sieve/sieve-extensions.c + +2007-12-07 00:22:48 +0100 Stephan Bosch <stephan@rename-it.nl> (cdefa5f4) + + Updated documentation. + + +M README +M src/lib-sieve/plugins/vacation/ext-vacation.c + +2007-12-06 23:13:25 +0100 Stephan Bosch <stephan@rename-it.nl> (97edb9ca) + + Added :addresses support to the vacation extension. + + +M sieve/tests/vacation.sieve +M src/lib-sieve/plugins/vacation/ext-vacation.c + +2007-12-06 22:47:44 +0100 Stephan Bosch <stephan@rename-it.nl> (e2e92dd6) + + Added support for reading an entire stringlist into memory. Also fixed + various identical bugs in stringlist-related error handling. + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c + +2007-12-06 22:15:56 +0100 Stephan Bosch <stephan@rename-it.nl> (80274dca) + + Added two TODO items. + + +M README + +2007-12-06 21:59:21 +0100 Stephan Bosch <stephan@rename-it.nl> (940ea3d7) + + Tiny update to documentation and removed a compiler warning. + + +M README +M src/lib-sieve/plugins/vacation/ext-vacation.c + +2007-12-06 21:48:44 +0100 Stephan Bosch <stephan@rename-it.nl> (03952bf0) + + Added :mime support to vacation extension. + + +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-generator.c + +2007-12-06 21:00:35 +0100 Stephan Bosch <stephan@rename-it.nl> (d24406e3) + + Renamed mail_environment to script_env. + + +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c + +2007-12-06 17:45:44 +0100 Stephan Bosch <stephan@rename-it.nl> (bddf8c83) + + Added mail-loop detection to the redirect action. + + +M README +M src/lib-sieve/cmd-redirect.c + +2007-12-06 17:22:16 +0100 Stephan Bosch <stephan@rename-it.nl> (bb78d0b1) + + Changed execution error handling a little. + + +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-bin/sieve-exec.c + +2007-12-06 15:43:47 +0100 Stephan Bosch <stephan@rename-it.nl> (289716f9) + + Adopted code to use Dovecot's new T_FRAME* macros. + + +M src/lib-sieve/ext-reject.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-validator.c + +2007-12-06 14:10:30 +0100 Stephan Bosch <stephan@rename-it.nl> (2e9603a5) + + Added proper ATTR_FORMAT to all functions that accept a string format and + fixed one bug in the process. + + +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-validator.h + +2007-12-06 12:42:45 +0100 Stephan Bosch <stephan@rename-it.nl> (66004fba) + + Further updated documentation and cleaned up the README file. + + +M README + +2007-12-06 02:48:02 +0100 Stephan Bosch <stephan@rename-it.nl> (38a72a86) + + Updated documentation. We are gettin closer to a first release. + + +M INSTALL +M README + +2007-12-06 02:26:57 +0100 Stephan Bosch <stephan@rename-it.nl> (df1bb287) + + Implemented implicit keep to execute when not canceled or when the + preceeding action execution fails. + + +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-result.c +M src/sieve-bin/bin-common.c +M src/sieve-bin/sieve-exec.c + +2007-12-05 23:07:44 +0100 Stephan Bosch <stephan@rename-it.nl> (ebc0485a) + + Fixed minor bugs in the error reporting. + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-interpreter.c + +2007-12-05 23:18:47 +0100 Stephan Bosch <stephan@rename-it.nl> (ff209a04) + + Fixed tiny bug in the error reporting in the lda-sieve plugin. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2007-12-05 22:48:16 +0100 Stephan Bosch <stephan@rename-it.nl> (8817dda5) + + Further developed the error handling. + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c + +2007-12-04 02:31:57 +0100 Stephan Bosch <stephan@rename-it.nl> (6f184ace) + + Added a little more error logging to the lda-sieve plugin. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2007-12-04 02:07:48 +0100 Stephan Bosch <stephan@rename-it.nl> (7dabf5bc) + + Implemented logfile error handler and assigned it to the lda-sieve plugin. + + +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2007-12-03 23:25:01 +0100 Stephan Bosch <stephan@rename-it.nl> (d688d73e) + + Further developed error handling. + + +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-bin/bin-common.c +M src/sieve-bin/sievec.c + +2007-12-02 23:37:52 +0100 Stephan Bosch <stephan@rename-it.nl> (3ccf3ebf) + + Forgot to initialize sieve library in lda-sieve plugin. It has now + successfully delivered its first message. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c + +2007-12-02 23:59:30 +0100 Stephan Bosch <stephan@rename-it.nl> (88560cef) + + Fixed misnamed module entry points for the lda-sieve plugin. + + +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/plugins/lda-sieve/lda-sieve-plugin.h + +2007-12-02 19:58:29 +0100 Stephan Bosch <stephan@rename-it.nl> (deb9f705) + + Included sieve plugin into the build process. + + +M configure.in +M src/Makefile.am +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/Makefile.am +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/plugins/lda-sieve/lda-sieve-plugin.h +M src/sieve-bin/bin-common.c + +2007-12-02 18:55:51 +0100 Stephan Bosch <stephan@rename-it.nl> (23953fce) + + Documentation updates. + + +M README +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/plugins/lda-sieve/lda-sieve-plugin.c +M src/sieve-bin/sievec.c + +2007-12-02 17:57:50 +0100 Stephan Bosch <stephan@rename-it.nl> (41c19809) + + Implemented sieve test binaries further. They now have proper command line + arguments. + + +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/sieve-bin/bin-common.c +M src/sieve-bin/bin-common.h +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c +M src/sieve-bin/sievec.c + +2007-12-02 15:34:38 +0100 Stephan Bosch <stephan@rename-it.nl> (5611ba3b) + + Updated and cleaned-up the sieve test binaries. + + +M src/sieve-bin/Makefile.am +M src/sieve-bin/bin-common.c +M src/sieve-bin/bin-common.h +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c +M src/sieve-bin/sievec.c + +2007-12-02 14:44:01 +0100 Stephan Bosch <stephan@rename-it.nl> (95803e31) + + Properly implemented the code dumper. Dumps are now printed in a stream. The + individual opcode and operand implementations no longer use printf()s. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-code-dumper.c +M src/lib-sieve/sieve-code-dumper.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c +M src/sieve-bin/sievec.c + +2007-12-02 12:04:41 +0100 Stephan Bosch <stephan@rename-it.nl> (ea987434) + + Forgot to add new files. + + +A src/lib-sieve/sieve-code-dumper.c +A src/lib-sieve/sieve-code-dumper.h + +2007-12-02 00:19:16 +0100 Stephan Bosch <stephan@rename-it.nl> (8fa2f53c) + + Exported sieve-code-dumper from sieve-interpreter containing all code + dumping related implementation. Now to remove all printfs.... + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c + +2007-12-01 21:11:47 +0100 Stephan Bosch <stephan@rename-it.nl> (b2168ea1) + + Fixed bug in handling optional operands to opcodes that have no mandatory + operands (0 is no longer a valid opcode) + + +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h + +2007-12-01 21:02:00 +0100 Stephan Bosch <stephan@rename-it.nl> (ba261b2d) + + Added conflict and duplicate checking to vacation and reject actions. + + +A sieve/errors/action-conflicts.sieve +A sieve/errors/action-duplicates.sieve +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-commands-private.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2007-12-01 19:06:18 +0100 Stephan Bosch <stephan@rename-it.nl> (750ccb61) + + Implemented actions reject and vacation. + + +M sieve/tests/vacation.sieve +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve.h +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c + +2007-12-01 14:59:35 +0100 Stephan Bosch <stephan@rename-it.nl> (60399b42) + + Fixed minor bug in envelope extension. + + +M src/lib-sieve/ext-envelope.c + +2007-11-30 21:56:55 +0100 Stephan Bosch <stephan@rename-it.nl> (2b6bc923) + + Further developed imapflags extension and added proper logging functions to + the result object. + + +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/imapflags.sieve +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve-validator.c + +2007-11-29 21:50:58 +0100 Stephan Bosch <stephan@rename-it.nl> (16f2ef46) + + The :flags tag introduced by the imapflags extension now attaches + side-effects to the appropriate action commands. + + +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-interpreter.c + +2007-11-29 18:02:05 +0100 Stephan Bosch <stephan@rename-it.nl> (44fe503f) + + Properly implemented handling of the implicit keep flag and fully + implemented the copy extension. + + +M README +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c + +2007-11-29 14:20:10 +0100 Stephan Bosch <stephan@rename-it.nl> (a2f1ad80) + + Added basic execution support to copy extension. Not completely functional + yet. + + +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2007-11-29 01:22:17 +0100 Stephan Bosch <stephan@rename-it.nl> (230cd1f3) + + Added support for reading side effect operands. + + +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code.c + +2007-11-29 00:40:42 +0100 Stephan Bosch <stephan@rename-it.nl> (20b47a0d) + + Added registration of side-effect extension into binary. + + +M src/lib-sieve/plugins/copy/ext-copy.c + +2007-11-29 00:35:22 +0100 Stephan Bosch <stephan@rename-it.nl> (169a3649) + + Defined side-effect object for the copy extension. + + +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h + +2007-11-29 00:14:14 +0100 Stephan Bosch <stephan@rename-it.nl> (08c97ffd) + + Incorporated the signedness of the id_code in the optional_read functions as + well + + +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/tst-header.c + +2007-11-28 23:31:50 +0100 Stephan Bosch <stephan@rename-it.nl> (19f30a5f) + + Changed id_code for optional operands to signed and fixed a + ext_my_id-related error in the vacation and copy extensions. + + +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/tst-size.c + +2007-11-28 22:35:05 +0100 Stephan Bosch <stephan@rename-it.nl> (90a67f1a) + + Added operand emission support for action side effects. + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-extensions.c + +2007-11-28 21:56:47 +0100 Stephan Bosch <stephan@rename-it.nl> (0a7f6dcd) + + Created pre-loaded action side effects 'extension'. + + +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h + +2007-11-28 21:11:05 +0100 Stephan Bosch <stephan@rename-it.nl> (21b41f04) + + Removed part of the code duplication between address-part, match-type and + comparator implementations. + + +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-match-types.c + +2007-11-28 20:28:21 +0100 Stephan Bosch <stephan@rename-it.nl> (317b1d33) + + Added untested support for side effects to result object. + + +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2007-11-27 23:42:04 +0100 Stephan Bosch <stephan@rename-it.nl> (5d26995a) + + Added :flags tag to the imapflags extension and fixed bug in the result + execution. + + +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/plugins/imapflags/Makefile.am +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/imapflags/imapflags.sieve +A src/lib-sieve/plugins/imapflags/tag-flags.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-result.c + +2007-11-27 23:00:32 +0100 Stephan Bosch <stephan@rename-it.nl> (90bfc52b) + + Updated documentation. + + +M README + +2007-11-27 22:50:22 +0100 Stephan Bosch <stephan@rename-it.nl> (99c169ae) + + Added support for externally adding tags to (possibly not yet registered) + command. The copy extension now adds such a tag to fileinto and redirect. + + +A src/lib-sieve/plugins/copy/copy.sieve +M src/lib-sieve/plugins/copy/ext-copy.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h + +2007-11-27 21:56:37 +0100 Stephan Bosch <stephan@rename-it.nl> (e7b84c64) + + Added skeleton for the copy extension. + + +M configure.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/copy/Makefile.am +A src/lib-sieve/plugins/copy/ext-copy.c +A src/lib-sieve/plugins/copy/rfc3894.txt +M src/lib-sieve/sieve-extensions.c +M src/sieve-bin/sieve-exec.c + +2007-11-27 21:09:46 +0100 Stephan Bosch <stephan@rename-it.nl> (5d73546c) + + Minor changes + + +M sieve/tests/actions.sieve +M src/lib-sieve/sieve-actions.c + +2007-11-27 19:38:26 +0100 Stephan Bosch <stephan@rename-it.nl> (78eaa955) + + Store action seems to work properly now. + + +M sieve/tests/actions.sieve +M src/lib-sieve/sieve-actions.c +M src/sieve-bin/sieve-exec.c + +2007-11-27 03:38:49 +0100 Stephan Bosch <stephan@rename-it.nl> (b7f741e7) + + Almost finished implementing the store action. But, I still get strange + errors when the mail transaction commits. Mail is stored though. + + +M sieve/tests/actions.sieve +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve.h +M src/sieve-bin/Makefile.am +M src/sieve-bin/mail-raw.c +M src/sieve-bin/mail-raw.h +A src/sieve-bin/namespaces.c +A src/sieve-bin/namespaces.h +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c + +2007-11-27 01:12:29 +0100 Stephan Bosch <stephan@rename-it.nl> (6cf3d1d3) + + Turned action execution into a transaction. + + +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/sieve-actions.c +M src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-result.c + +2007-11-27 00:25:12 +0100 Stephan Bosch <stephan@rename-it.nl> (385ce7aa) + + Added (not yet active) handling of implicit keep and adjusted commands + accordingly. + + +M README +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2007-11-27 00:07:12 +0100 Stephan Bosch <stephan@rename-it.nl> (26eefd04) + + Added TODO item. + + +M README + +2007-11-26 21:50:16 +0100 Stephan Bosch <stephan@rename-it.nl> (b4bbc93f) + + Added inbox location to mail environment and made keep command use it to + generate its store action. + + +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c + +2007-11-26 21:29:17 +0100 Stephan Bosch <stephan@rename-it.nl> (fcaeb9e7) + + Updated documentation. + + +M README +M src/lib-sieve/ext-fileinto.c + +2007-11-26 21:20:20 +0100 Stephan Bosch <stephan@rename-it.nl> (463ff297) + + Fileinto command now produces a store action which is now produced by the + keep command as well. + + +M sieve/tests/actions.sieve +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-fileinto.c +A src/lib-sieve/sieve-actions.c +A src/lib-sieve/sieve-actions.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2007-11-26 19:31:38 +0100 Stephan Bosch <stephan@rename-it.nl> (c445794f) + + Made discard command add discard action to the result. + + +A sieve/tests/actions.sieve +M src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-keep.c + +2007-11-26 19:19:16 +0100 Stephan Bosch <stephan@rename-it.nl> (c5ae8068) + + Exported discard command to its own separate file. + + +M src/lib-sieve/Makefile.am +A src/lib-sieve/cmd-discard.c +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/sieve-commands.c + +2007-11-26 19:04:10 +0100 Stephan Bosch <stephan@rename-it.nl> (0bde3903) + + Added support for detecting action conflicts. + + +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2007-11-26 17:18:57 +0100 Stephan Bosch <stephan@rename-it.nl> (94e4cfe6) + + Updated documentation. + + +M README + +2007-11-26 17:09:54 +0100 Stephan Bosch <stephan@rename-it.nl> (88c1edae) + + Added support for avoiding duplicate actions in the sieve result. + + +M sieve/tests/redirect.sieve +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h + +2007-11-26 16:52:04 +0100 Stephan Bosch <stephan@rename-it.nl> (55632704) + + Made keep command add keep action to the result. + + +M src/lib-sieve/cmd-keep.c +M src/lib-sieve/cmd-redirect.c + +2007-11-26 16:43:30 +0100 Stephan Bosch <stephan@rename-it.nl> (6dee82eb) + + Exported keep command to its own separate file. + + +M src/lib-sieve/Makefile.am +A src/lib-sieve/cmd-keep.c +M src/lib-sieve/sieve-commands-private.h +M src/lib-sieve/sieve-commands.c + +2007-11-25 16:59:01 +0100 Stephan Bosch <stephan@rename-it.nl> (ec4184ed) + + Minor changes to the executables. + + +M src/sieve-bin/bin-common.c +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c + +2007-11-25 16:13:48 +0100 Stephan Bosch <stephan@rename-it.nl> (14a07351) + + Added mail-file parameter to the sieve-test and sieve-exec binaries. + + +M README +M src/lib-sieve/sieve-interpreter.c +M src/sieve-bin/sieve-exec.c +M src/sieve-bin/sieve-test.c + +2007-11-25 11:54:54 +0100 Stephan Bosch <stephan@rename-it.nl> (77344245) + + Cleaned up implementation of sieve test binaries and added sieve-exec + + +M .hgignore +M sieve/tests/redirect.sieve +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/sieve-bin/Makefile.am +A src/sieve-bin/bin-common.c +A src/sieve-bin/bin-common.h +A src/sieve-bin/mail-raw.c +A src/sieve-bin/mail-raw.h +A src/sieve-bin/sieve-exec.c +A src/sieve-bin/sieve-test.c +D src/sieve-bin/sieve_test.c +M src/sieve-bin/sievec.c + +2007-11-25 00:09:35 +0100 Stephan Bosch <stephan@rename-it.nl> (52f9a47e) + + Removed spurious debug message. + + +M src/lib-sieve/sieve-match-types.c + +2007-11-24 23:54:41 +0100 Stephan Bosch <stephan@rename-it.nl> (9ebef39b) + + Added first action execution support. Redirect is the first command to + actually work. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/sieve-bin/Makefile.am +M src/sieve-bin/sieve_test.c + +2007-11-24 18:59:29 +0100 Stephan Bosch <stephan@rename-it.nl> (1788802c) + + Added TODO item. + + +M README + +2007-11-24 18:55:04 +0100 Stephan Bosch <stephan@rename-it.nl> (7bc6d514) + + Moved address-part, match-type and comparator code registries from + interpreter to binary where they belong. + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/relational/relational.sieve +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-header.c + +2007-11-24 17:48:38 +0100 Stephan Bosch <stephan@rename-it.nl> (53ff5113) + + Added extension context storage support to the sieve binary. + + +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-interpreter.c + +2007-11-24 17:35:48 +0100 Stephan Bosch <stephan@rename-it.nl> (ec61c8ea) + + Added binary_load event to the sieve extensions. + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-match-types.c + +2007-11-24 15:37:12 +0100 Stephan Bosch <stephan@rename-it.nl> (4d14341a) + + Grouped runtime parameters into a single runtime environment and started + implementation of result composition/execution. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-result.h +M src/lib-sieve/sieve.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c + +2007-11-24 13:04:37 +0100 Stephan Bosch <stephan@rename-it.nl> (ef8d3cc5) + + Changed interpreter in the event of an unimplemented opcode. + + +M src/lib-sieve/sieve-interpreter.c + +2007-11-24 13:00:16 +0100 Stephan Bosch <stephan@rename-it.nl> (ff44b78d) + + Updated documentation. + + +M README +M src/lib-sieve/plugins/imapflags/ext-imapflags.c + +2007-11-24 02:05:39 +0100 Stephan Bosch <stephan@rename-it.nl> (dd0ffe54) + + Implemented hasflag command interpretation for the imapflags extension. + + +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/imapflags-2.sieve +M src/lib-sieve/plugins/imapflags/tst-hasflag.c + +2007-11-23 23:56:31 +0100 Stephan Bosch <stephan@rename-it.nl> (4bad5e4c) + + Added actual flag management to the imapflags extension. Addflag, removeflag + and setflag now do what they should do. + + +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +A src/lib-sieve/plugins/imapflags/imapflags-2.sieve +M src/lib-sieve/plugins/imapflags/imapflags.sieve +M src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/tst-size.c + +2007-11-23 13:34:55 +0100 Stephan Bosch <stephan@rename-it.nl> (cb095ead) + + Finished i;ascii-numeric comparator and fixed a segfault bug in the process. + + +M README +M src/lib-sieve/cmd-if.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/relational/relational.sieve +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c + +2007-11-23 12:35:20 +0100 Stephan Bosch <stephan@rename-it.nl> (84c99223) + + Added hasflag test to the imapflags extension. + + +M README +M src/lib-sieve/plugins/imapflags/Makefile.am +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/imapflags/imapflags-errors.sieve +M src/lib-sieve/plugins/imapflags/imapflags.sieve +A src/lib-sieve/plugins/imapflags/tst-hasflag.c +M src/lib-sieve/tst-header.c + +2007-11-23 00:37:41 +0100 Stephan Bosch <stephan@rename-it.nl> (ccf4377f) + + Implemented code generation and interpretation for the commands introduced + by the imapflags extension. + + +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/imapflags/imapflags.sieve +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h + +2007-11-23 00:18:17 +0100 Stephan Bosch <stephan@rename-it.nl> (bac51d56) + + Upgraded opcode extension support to handle more than one opcode per + extension. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/imapflags/cmd-addflag.c +M src/lib-sieve/plugins/imapflags/cmd-removeflag.c +M src/lib-sieve/plugins/imapflags/cmd-setflag.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c + +2007-11-22 20:20:28 +0100 Stephan Bosch <stephan@rename-it.nl> (62efe088) + + imapflags: Added (dummy) check for the existance of the variables extension. + + +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +M src/lib-sieve/plugins/imapflags/imapflags.sieve + +2007-11-22 20:02:57 +0100 Stephan Bosch <stephan@rename-it.nl> (4e603ce4) + + Implemented validation for the commands introduced by the imapflags + extension. + + +M src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +A src/lib-sieve/plugins/imapflags/imapflags-errors.sieve +M src/lib-sieve/sieve-validator.c + +2007-11-22 19:35:44 +0100 Stephan Bosch <stephan@rename-it.nl> (60770a2a) + + Created skeletons for the commands introduced by the imapflags extension. + + +M src/lib-sieve/plugins/imapflags/Makefile.am +A src/lib-sieve/plugins/imapflags/cmd-addflag.c +A src/lib-sieve/plugins/imapflags/cmd-removeflag.c +A src/lib-sieve/plugins/imapflags/cmd-setflag.c +A src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +A src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +M src/lib-sieve/plugins/imapflags/ext-imapflags.c +A src/lib-sieve/plugins/imapflags/imapflags.sieve +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-validator.c + +2007-11-22 17:17:25 +0100 Stephan Bosch <stephan@rename-it.nl> (91669a17) + + Started skeleton for the imapflags extension. + + +M configure.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/imapflags/Makefile.am +A src/lib-sieve/plugins/imapflags/draft-ietf-sieve-imapflags-05.txt +A src/lib-sieve/plugins/imapflags/ext-imapflags.c + +2007-11-22 16:57:48 +0100 Stephan Bosch <stephan@rename-it.nl> (a2c51b31) + + Cleaned up make process and included the 'plugins' into the main sieve + library archive. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/Makefile.am +M src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.am +M src/lib-sieve/plugins/regex/Makefile.am +M src/lib-sieve/plugins/relational/Makefile.am +M src/lib-sieve/plugins/subaddress/Makefile.am +M src/lib-sieve/plugins/vacation/Makefile.am +M src/sieve-bin/Makefile.am + +2007-11-22 13:19:43 +0100 Stephan Bosch <stephan@rename-it.nl> (441a81d5) + + Updated documentation. + + +M README +M src/lib-sieve/sieve-commands.c + +2007-11-22 13:00:17 +0100 Stephan Bosch <stephan@rename-it.nl> (8c021fd9) + + Removed unecessary jump after commands like stop. + + +M sieve/examples/vivil.sieve +A sieve/tests/stop.sieve +M src/lib-sieve/cmd-if.c +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h + +2007-11-22 11:56:32 +0100 Stephan Bosch <stephan@rename-it.nl> (6e5638ce) + + Debugged :matches match type and no more bugs are currently known. + + +M sieve/tests/matches.sieve +M src/lib-sieve/sieve-match-types.c + +2007-11-22 00:41:00 +0100 Stephan Bosch <stephan@rename-it.nl> (6a6b3409) + + Made first buggy implementation of :matches match type. + + +A sieve/tests/matches.sieve +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-match-types.c + +2007-11-21 16:18:36 +0100 Stephan Bosch <stephan@rename-it.nl> (def18c3b) + + Updated documentation with respect to extensions. + + +M README + +2007-11-21 16:16:17 +0100 Stephan Bosch <stephan@rename-it.nl> (e22e8718) + + Added dummy execution support to reject extension. + + +A sieve/tests/reject.sieve +M src/lib-sieve/ext-reject.c + +2007-11-21 16:04:49 +0100 Stephan Bosch <stephan@rename-it.nl> (cf64e6d4) + + Updated documentation. + + +M README +M src/lib-sieve/plugins/vacation/ext-vacation.c + +2007-11-21 15:45:23 +0100 Stephan Bosch <stephan@rename-it.nl> (9b1b731c) + + Implemented dummy execution for vacation extension. + + +A sieve/tests/vacation.sieve +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h + +2007-11-21 14:22:17 +0100 Stephan Bosch <stephan@rename-it.nl> (d2eee94d) + + Resolved compiler warning in envelope extension. + + +M src/lib-sieve/ext-envelope.c + +2007-11-21 14:21:14 +0100 Stephan Bosch <stephan@rename-it.nl> (01b80d1a) + + Added test script for redirect command. + + +A sieve/tests/redirect.sieve + +2007-11-21 14:20:51 +0100 Stephan Bosch <stephan@rename-it.nl> (95738f98) + + Properly implemented stop command and associated opcode. + + +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h + +2007-11-21 14:11:13 +0100 Stephan Bosch <stephan@rename-it.nl> (ea70ff34) + + Added status message to sieve_test to indicate successful script run. + + +M src/sieve-bin/sieve_test.c + +2007-11-21 14:06:56 +0100 Stephan Bosch <stephan@rename-it.nl> (21e78107) + + Created dummy interpretation support for the redirect command. + + +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-interpreter.h + +2007-11-21 12:54:14 +0100 Stephan Bosch <stephan@rename-it.nl> (966324cd) + + Created dummy interpretation support for the fileinto extension. + + +A sieve/tests/fileinto.sieve +M src/lib-sieve/ext-fileinto.c + +2007-11-21 12:42:05 +0100 Stephan Bosch <stephan@rename-it.nl> (56a07d5a) + + Removed debug lines in envelope extension. + + +M src/lib-sieve/ext-envelope.c + +2007-11-21 12:37:59 +0100 Stephan Bosch <stephan@rename-it.nl> (b4777986) + + Made ext_envelope_get_fields cleaner. + + +M src/lib-sieve/ext-envelope.c + +2007-11-21 12:32:12 +0100 Stephan Bosch <stephan@rename-it.nl> (e0f6bd8a) + + Updated documentation. + + +M README +M src/lib-sieve/ext-envelope.c + +2007-11-21 12:26:35 +0100 Stephan Bosch <stephan@rename-it.nl> (b18527bd) + + Made basic execution implementation of the envelope extension. + + +A sieve/tests/envelope.sieve +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve.h +M src/lib-sieve/tst-address.c +M src/sieve-bin/sieve_test.c + +2007-11-21 11:53:44 +0100 Stephan Bosch <stephan@rename-it.nl> (8c0c5a98) + + Added envelope data to the interpreter environment. + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c +M src/sieve-bin/sieve_test.c + +2007-11-21 04:11:47 +0100 Stephan Bosch <stephan@rename-it.nl> (d951cfec) + + Completed implementation of the relational extension. + + +M README +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/relational/relational.sieve +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-header.c + +2007-11-21 02:46:30 +0100 Stephan Bosch <stephan@rename-it.nl> (0ee0dd7d) + + Improved match handling and started implementing the interpretation of the + relational match type. + + +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/regex.sieve +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h + +2007-11-20 23:53:15 +0100 Stephan Bosch <stephan@rename-it.nl> (2f3561f5) + + Implemented context validation for :contains match type. + + +M sieve/errors/match-type-errors.sieve +M sieve/tests/match-type.sieve +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-match-types.c + +2007-11-20 23:02:37 +0100 Stephan Bosch <stephan@rename-it.nl> (eb4b1f97) + + Updated documentation with respect to regex externsion and match-type + support. + + +M README +M src/lib-sieve/plugins/regex/ext-regex.c + +2007-11-20 22:42:31 +0100 Stephan Bosch <stephan@rename-it.nl> (fbc4e037) + + Last commit broke execution of match types other than :regex...fixed. + + +M src/lib-sieve/sieve-match-types.c + +2007-11-20 22:18:07 +0100 Stephan Bosch <stephan@rename-it.nl> (19f3572d) + + Implemented regex match execution. + + +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/regex.sieve +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-header.c + +2007-11-20 16:51:03 +0100 Stephan Bosch <stephan@rename-it.nl> (71661efa) + + Fixed missing require in sanjay.sieve example + + +M sieve/examples/sanjay.sieve + +2007-11-20 16:43:53 +0100 Stephan Bosch <stephan@rename-it.nl> (9845a640) + + Forgot to handle stringlists in :regex validation. + + +M src/lib-sieve/plugins/regex/ext-regex.c + +2007-11-20 16:09:59 +0100 Stephan Bosch <stephan@rename-it.nl> (9d4dce9c) + + Implemented :regex match validation. + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/regex/regex-errors.sieve +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-header.c + +2007-11-20 14:26:33 +0100 Stephan Bosch <stephan@rename-it.nl> (05545fa1) + + Implemented detection of duplicate optional arguments. + + +A sieve/errors/address-part-errors.sieve +M sieve/errors/interesting.sieve +A sieve/errors/match-type-errors.sieve +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-validator.c + +2007-11-20 12:29:58 +0100 Stephan Bosch <stephan@rename-it.nl> (f32edce2) + + Made regex match complaint about comparators other than i;octet or + i;ascii-casemap + + +M src/lib-sieve/plugins/regex/ext-regex.c +A src/lib-sieve/plugins/regex/regex-errors.sieve +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-validator.c + +2007-11-20 11:57:46 +0100 Stephan Bosch <stephan@rename-it.nl> (f4a19c3d) + + Added support for match-type argument context validation. + + +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h + +2007-11-20 11:42:10 +0100 Stephan Bosch <stephan@rename-it.nl> (f8ecf182) + + Added support for argument context validation. + + +M src/lib-sieve/sieve-validator.c + +2007-11-20 11:27:17 +0100 Stephan Bosch <stephan@rename-it.nl> (fcc318e3) + + Added validat_context method to command arguments for the to-be-implemented + argument context validation. + + +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/tst-size.c + +2007-11-20 11:14:22 +0100 Stephan Bosch <stephan@rename-it.nl> (2f2a00b7) + + Changed argument generator function prototype to assign responsibility of + advancing to the next argument to the generator itself. + + +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-match-types.c + +2007-11-20 11:01:03 +0100 Stephan Bosch <stephan@rename-it.nl> (8884f55d) + + Removed i_unreached() at inappropriate location. + + +M src/lib-sieve/sieve-commands.c + +2007-11-20 10:57:46 +0100 Stephan Bosch <stephan@rename-it.nl> (8cfba719) + + Removed code duplication in validator: merged command and test validation in + one function. + + +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-validator.c + +2007-11-20 10:29:40 +0100 Stephan Bosch <stephan@rename-it.nl> (422a8f7b) + + Fixed bug in the command validation. + + +M src/lib-sieve/sieve-validator.c + +2007-11-20 10:23:42 +0100 Stephan Bosch <stephan@rename-it.nl> (2c111bd4) + + Improved validation of command placement for if and require commands. + + +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/sieve-commands.h + +2007-11-20 01:22:22 +0100 Stephan Bosch <stephan@rename-it.nl> (523c5df3) + + Changed validator's command syntax validation such that command + implementations don't have to call the argument, test and block validation + functions explicitly. + + +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-commands-private.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c + +2007-11-19 22:54:21 +0100 Stephan Bosch <stephan@rename-it.nl> (8065de38) + + Changed argument validation to record the first positional argument into the + command context by default. Also furter improved validator's error handling. + + +M src/lib-sieve/cmd-if.c +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-not.c +M src/lib-sieve/tst-size.c + +2007-11-19 21:21:27 +0100 Stephan Bosch <stephan@rename-it.nl> (fd8b7199) + + Revised positional argument checking and fixed the validator's error + handling. + + +M sieve/errors/address-errors.sieve +M sieve/errors/header-errors.sieve +M src/lib-sieve/cmd-redirect.c +M src/lib-sieve/cmd-require.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/subaddress/subaddress.sieve +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c + +2007-11-19 18:50:55 +0100 Stephan Bosch <stephan@rename-it.nl> (689e982a) + + Prevent unimplemented match type from causing a segfault. + + +M src/lib-sieve/sieve-match-types.c + +2007-11-19 01:36:23 +0100 Stephan Bosch <stephan@rename-it.nl> (3c0b20dd) + + Implemented match type execution and activated match types :is and + :contains. + + +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-header.c + +2007-11-17 16:25:53 +0100 Stephan Bosch <stephan@rename-it.nl> (b7e09b56) + + Minor updates to the documentation. + + +M README +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c + +2007-11-17 16:19:24 +0100 Stephan Bosch <stephan@rename-it.nl> (4fc3387f) + + Fixed code generation for relational extension. + + +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/plugins/relational/relational.sieve +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h + +2007-11-17 15:24:41 +0100 Stephan Bosch <stephan@rename-it.nl> (7b940591) + + Implemented support for additional parameters to match-types and implemented + validation for the relational extension. + + +M src/lib-sieve/plugins/regex/ext-regex.c +M src/lib-sieve/plugins/relational/ext-relational.c +M src/lib-sieve/sieve-match-types.c +M src/lib-sieve/sieve-match-types.h + +2007-11-17 14:14:19 +0100 Stephan Bosch <stephan@rename-it.nl> (72477bab) + + Created skeletons for regex and relational extensions. These are to be + developed simultaneously with the match-type support in general. + + +M configure.in +M sieve/tests/match-type.sieve +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/regex/Makefile.am +A src/lib-sieve/plugins/regex/draft-murchison-sieve-regex-07.txt +A src/lib-sieve/plugins/regex/ext-regex.c +A src/lib-sieve/plugins/regex/regex.sieve +A src/lib-sieve/plugins/relational/Makefile.am +A src/lib-sieve/plugins/relational/ext-relational.c +A src/lib-sieve/plugins/relational/relational.sieve +A src/lib-sieve/plugins/relational/rfc3431.txt +M src/lib-sieve/sieve-extensions.c +M src/sieve-bin/Makefile.am + +2007-11-17 12:57:36 +0100 Stephan Bosch <stephan@rename-it.nl> (aaa72172) + + Started implementation of match-type support and fixed compilation error. + + +M README +A sieve/tests/match-type.sieve +M src/lib-sieve/Makefile.am +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-interpreter.c +A src/lib-sieve/sieve-match-types.c +A src/lib-sieve/sieve-match-types.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-header.c + +2007-11-17 11:50:15 +0100 Stephan Bosch <stephan@rename-it.nl> (30c80502) + + Updated README and a few minor cosmetic changes to the code. + + +M README +M src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-comparators.c + +2007-11-17 03:38:50 +0100 Stephan Bosch <stephan@rename-it.nl> (d2ea3b30) + + Implemented comparator-i;ascii-numeric extension and activated comparator + extension support. + + +M configure.in +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.am +A src/lib-sieve/plugins/comparator-i-ascii-numeric/cmp-i-ascii-numeric.sieve +A src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +A src/lib-sieve/plugins/comparator-i-ascii-numeric/rfc2244.txt +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-header.c +M src/sieve-bin/Makefile.am + +2007-11-17 00:14:30 +0100 Stephan Bosch <stephan@rename-it.nl> (332ee54f) + + Added dummy extensions for core comparators. + + +M src/lib-sieve/sieve-extensions.c + +2007-11-17 00:07:37 +0100 Stephan Bosch <stephan@rename-it.nl> (fc6b817e) + + A few small cosmetic changes in addr-part code and generic extension + support. + + +M sieve/tests/extensions.sieve +M src/lib-sieve/cmd-require.c +M src/lib-sieve/sieve-address-parts.c + +2007-11-16 23:36:03 +0100 Stephan Bosch <stephan@rename-it.nl> (3bd3f8c4) + + Finished implementation of subaddress extension. + + +M src/lib-sieve/plugins/subaddress/ext-subaddress.c +M src/lib-sieve/plugins/subaddress/subaddress.sieve +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-common.h + +2007-11-16 19:35:58 +0100 Stephan Bosch <stephan@rename-it.nl> (2fbe78be) + + Implemented support for the subaddress extension and fixed extension support + to work properly. + + +M configure.in +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/subaddress/Makefile.am +A src/lib-sieve/plugins/subaddress/ext-subaddress.c +A src/lib-sieve/plugins/subaddress/rfc3598.txt +A src/lib-sieve/plugins/subaddress/subaddress.sieve +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-size.c +M src/sieve-bin/Makefile.am + +2007-11-14 00:47:06 +0100 Stephan Bosch <stephan@rename-it.nl> (f940ef27) + + Implemented address part execution support. + + +M sieve/tests/address-part.sieve +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/tst-address.c + +2007-11-13 22:28:04 +0100 Stephan Bosch <stephan@rename-it.nl> (0b1a8c86) + + Activated address-part code generation support. + + +A sieve/tests/address-part.sieve +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/tst-address.c + +2007-11-13 20:26:03 +0100 Stephan Bosch <stephan@rename-it.nl> (b00f75d9) + + Lots of cosmetic changes + + +M src/lib-sieve/sieve-address-parts.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands-private.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-error.c +M src/lib-sieve/sieve-error.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-lexer.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-validator.h + +2007-11-13 16:49:23 +0100 Stephan Bosch <stephan@rename-it.nl> (c1013f0d) + + Added a little documentation to the README file. + + +M INSTALL +M README + +2007-11-13 00:39:35 +0100 Stephan Bosch <stephan@rename-it.nl> (1f797b35) + + Removed unused static pre-declaration from validator. + + +M src/lib-sieve/sieve-validator.c + +2007-11-13 00:09:18 +0100 Stephan Bosch <stephan@rename-it.nl> (2a192d0d) + + Rewrote large parts of the extension support and added partial address-part + implementation. + + +M sieve/tests/comparator.sieve +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-require.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +A src/lib-sieve/sieve-address-parts.c +A src/lib-sieve/sieve-address-parts.h +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-header.c +M src/sieve-bin/sieve_test.c +M src/sieve-bin/sievec.c + +2007-11-11 21:11:54 +0100 Stephan Bosch <stephan@rename-it.nl> (85e7a741) + + Upgraded sieve_test to 1.1.beta8 + + +M src/sieve-bin/Makefile.am +M src/sieve-bin/sieve_test.c + +2007-11-11 18:01:57 +0100 Stephan Bosch <stephan@rename-it.nl> (acc9246f) + + Enabled comparator execution support. + + +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-header.c + +2007-11-11 17:19:01 +0100 Stephan Bosch <stephan@rename-it.nl> (e25f3baf) + + Added support for optional operators to the byte code implementation. + + +M sieve/tests/comparator.sieve +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c + +2007-11-09 01:23:12 +0100 Stephan Bosch <stephan@rename-it.nl> (4e793fea) + + Started implementation of comparator execution support. + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h + +2007-11-08 19:33:00 +0100 Stephan Bosch <stephan@rename-it.nl> (9ac7cd5d) + + Changed string-list single-string handling for coded list. + + +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h + +2007-11-08 17:34:37 +0100 Stephan Bosch <stephan@rename-it.nl> (95b2627e) + + Properly implemented opcode and operand handing and moved code to more + appropriate units. + + +M src/lib-sieve/cmd-if.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c + +2007-11-01 10:23:03 +0100 Stephan Bosch <stephan@rename-it.nl> (d5819c6a) + + A few minor changes + + +M sieve/examples/sieve_examples.sieve +D sieve/examples/stephan.sieve +D sieve/examples/unparsed-elvey.sieve +M src/lib-sieve/sieve-code.h + +2007-11-01 10:10:36 +0100 Stephan Bosch <stephan@rename-it.nl> (320022d2) + + Added sieve example and documented the others with author and the url where + I found them. + + +M sieve/examples/elvey.sieve +A sieve/examples/jerry.sieve +M sieve/examples/mjohnson.sieve +M sieve/examples/mklose.sieve +M sieve/examples/sanjay.sieve +M sieve/examples/vivil.sieve + +2007-10-27 04:25:17 +0200 Stephan Bosch <stephan@rename-it.nl> (5135e910) + + Moved literall access functions from interpreter to binary. + + +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h + +2007-10-27 03:15:31 +0200 Stephan Bosch <stephan@rename-it.nl> (8c99880d) + + Implemented comparator support towards code generation, interpretation is + not possible yet. + + +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-comparators.c +M src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h + +2007-10-27 02:31:18 +0200 Stephan Bosch <stephan@rename-it.nl> (286046df) + + Changed argument to operand processing to be much more flexible. + + +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c + +2007-10-26 22:43:55 +0200 Stephan Bosch <stephan@rename-it.nl> (c5d1b547) + + Moved literal emission functions from generator to binary source. + + +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h + +2007-10-26 22:13:41 +0200 Stephan Bosch <stephan@rename-it.nl> (b0868f2e) + + First steps towards implementing code generation and interpretation for + proper comperators. + + +A sieve/tests/comparator.sieve +M src/lib-sieve/Makefile.am +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-ast.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.h +M src/lib-sieve/sieve-common.h +A src/lib-sieve/sieve-comparators.c +A src/lib-sieve/sieve-comparators.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/tst-size.c + +2007-10-26 01:29:34 +0200 Stephan Bosch <stephan@rename-it.nl> (685d4195) + + Extremely minor cosmetic change. + + +M src/lib-sieve/tst-exists.c + +2007-10-26 01:24:07 +0200 Stephan Bosch <stephan@rename-it.nl> (57cdd9b8) + + Removed files with intermittent compilation results from the repository + (oops) + + +D src/lib-sieve/plugins/Makefile +D src/lib-sieve/plugins/Makefile.in + +2007-10-26 01:20:31 +0200 Stephan Bosch <stephan@rename-it.nl> (d039e98e) + + Made header and exists tests executable. + + +M sieve/tests/basic.sieve +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c + +2007-10-25 22:43:53 +0200 Stephan Bosch <stephan@rename-it.nl> (cc7a4672) + + Made address and size tests executable and fixed minor bug regarding the + lexer. + + +M sieve/tests/basic.sieve +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve.c +M src/lib-sieve/sieve.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-size.c +M src/sieve-bin/Makefile.am +M src/sieve-bin/sieve_test.c +M src/sieve-bin/sievec.c + +2007-10-25 12:26:52 +0200 Stephan Bosch <stephan@rename-it.nl> (34b986f5) + + Created libsieve interface and started the sieve_test binary. + + +M .hgignore +M src/lib-sieve/Makefile.am +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-parser.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +A src/lib-sieve/sieve.c +A src/lib-sieve/sieve.h +D src/sieve-bin/Makefile +M src/sieve-bin/Makefile.am +D src/sieve-bin/Makefile.in +A src/sieve-bin/sieve_test.c +D src/sieve-bin/sievec +M src/sieve-bin/sievec.c +D src/sieve-bin/sievec.o + +2007-10-24 22:48:57 +0200 Stephan Bosch <stephan@rename-it.nl> (58177948) + + Upgraded from dovecot-1.0 to dovecot-1.1 (array changes and various _unref + differences) + + +M src/lib-sieve/cmd-if.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/Makefile +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-ast.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-lexer.c +M src/lib-sieve/sieve-parser.c +M src/lib-sieve/sieve-result.c +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-size.c +M src/sieve-bin/Makefile +M src/sieve-bin/Makefile.am +M src/sieve-bin/Makefile.in +M src/sieve-bin/sievec +M src/sieve-bin/sievec.o + +2007-10-24 19:24:42 +0200 Stephan Bosch <stephan@rename-it.nl> (580d9522) + + Exported sievec binary to separate directory called sieve-bin. + + +M configure.in +R100 src/lib-sieve/scripts/errors/address-errors.sieve sieve/errors/address-errors.sieve +R100 src/lib-sieve/scripts/errors/header-errors.sieve sieve/errors/header-errors.sieve +R100 src/lib-sieve/scripts/errors/if-errors.sieve sieve/errors/if-errors.sieve +R100 src/lib-sieve/scripts/errors/interesting.sieve sieve/errors/interesting.sieve +R100 src/lib-sieve/scripts/errors/keep-errors.sieve sieve/errors/keep-errors.sieve +R100 src/lib-sieve/scripts/errors/parse-errors.sieve sieve/errors/parse-errors.sieve +R100 src/lib-sieve/scripts/errors/require-errors.sieve sieve/errors/require-errors.sieve +R100 src/lib-sieve/scripts/errors/size-errors.sieve sieve/errors/size-errors.sieve +R100 src/lib-sieve/scripts/errors/stop-errors.sieve sieve/errors/stop-errors.sieve +R100 src/lib-sieve/scripts/errors/tag-errors.sieve sieve/errors/tag-errors.sieve +R100 src/lib-sieve/scripts/examples/elvey.sieve sieve/examples/elvey.sieve +R100 src/lib-sieve/scripts/examples/mjohnson.sieve sieve/examples/mjohnson.sieve +R100 src/lib-sieve/scripts/examples/mklose.sieve sieve/examples/mklose.sieve +R100 src/lib-sieve/scripts/examples/rfc3028.sieve sieve/examples/rfc3028.sieve +R100 src/lib-sieve/scripts/examples/sanjay.sieve sieve/examples/sanjay.sieve +R100 src/lib-sieve/scripts/examples/sieve_examples.sieve sieve/examples/sieve_examples.sieve +R100 src/lib-sieve/scripts/examples/stephan.sieve sieve/examples/stephan.sieve +R100 src/lib-sieve/scripts/examples/unparsed-elvey.sieve sieve/examples/unparsed-elvey.sieve +R100 src/lib-sieve/scripts/examples/vacation.sieve sieve/examples/vacation.sieve +R100 src/lib-sieve/scripts/examples/vivil.sieve sieve/examples/vivil.sieve +A sieve/tests/basic.sieve +R100 src/lib-sieve/scripts/tests/extensions.sieve sieve/tests/extensions.sieve +R100 src/lib-sieve/scripts/tests/if.sieve sieve/tests/if.sieve +M src/Makefile.am +M src/lib-sieve/Makefile.am +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-result.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c +A src/sieve-bin/Makefile +A src/sieve-bin/Makefile.am +A src/sieve-bin/Makefile.in +A src/sieve-bin/sievec +R096 src/lib-sieve/sievec.c src/sieve-bin/sievec.c +A src/sieve-bin/sievec.o + +2007-10-23 23:19:33 +0200 Stephan Bosch <stephan@rename-it.nl> (205c43b3) + + Started first support for actual execution of sieve script. + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-if.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/plugins/vacation/Makefile.am +M src/lib-sieve/plugins/vacation/ext-vacation.c +M src/lib-sieve/sieve-binary.c +M src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-common.h +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +A src/lib-sieve/sieve-result.c +A src/lib-sieve/sieve-result.h +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c + +2007-10-23 19:32:31 +0200 Stephan Bosch <stephan@rename-it.nl> (639b71a3) + + * Minor changes to the extension implementation * Started the lda plugin + source + + +M src/lib-sieve/Makefile.am +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/sieve-interpreter.h +A src/plugins/Makefile.am +A src/plugins/lda-sieve/Makefile.am +A src/plugins/lda-sieve/lda-sieve-plugin.c +A src/plugins/lda-sieve/lda-sieve-plugin.h + +2007-10-22 14:40:01 +0200 Stephan Bosch <stephan@rename-it.nl> (06b238a1) + + Changed (currently unused) sieve-address.c to use dovecot rfc822 parser. + + +M src/lib-sieve/sieve-address.c + +2007-10-22 12:54:02 +0200 Stephan Bosch <stephan@rename-it.nl> (b2bf1705) + + Added draft RFC for vacation extension. + + +A src/lib-sieve/plugins/vacation/draft-ietf-sieve-vacation-07.txt + +2007-10-22 12:32:53 +0200 Stephan Bosch <stephan@rename-it.nl> (1b2660d2) + + * Further developed the extension support * Added plugins as static + libraries (for now) + + +M configure.in +M src/lib-sieve/Makefile.am +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +A src/lib-sieve/plugins/Makefile +A src/lib-sieve/plugins/Makefile.am +A src/lib-sieve/plugins/Makefile.in +D src/lib-sieve/plugins/comparator-i;ascii-numeric.c +D src/lib-sieve/plugins/copy.c +A src/lib-sieve/plugins/vacation/Makefile.am +A src/lib-sieve/plugins/vacation/ext-vacation.c +A src/lib-sieve/plugins/vacation/vacation.sieve +M src/lib-sieve/scripts/tests/extensions.sieve +M src/lib-sieve/sieve-extensions.c + +2007-10-22 01:04:14 +0200 Stephan Bosch <stephan@rename-it.nl> (a5bb7080) + + Renamed reject.sieve to extensions.sieve for generic extensions testing. + + +A src/lib-sieve/scripts/tests/extensions.sieve +D src/lib-sieve/scripts/tests/reject.sieve + +2007-10-22 01:02:02 +0200 Stephan Bosch <stephan@rename-it.nl> (468f75b2) + + * Added generation support to the fileinto extension. * Fixed a bug in the + require command generation. + + +M src/lib-sieve/cmd-require.c +M src/lib-sieve/ext-fileinto.c + +2007-10-22 00:38:55 +0200 Stephan Bosch <stephan@rename-it.nl> (a3f9de83) + + Added basic extension support to generator and interpreter. + + +M .hgignore +M src/lib-sieve/Makefile.am +M src/lib-sieve/cmd-require.c +M src/lib-sieve/ext-envelope.c +M src/lib-sieve/ext-fileinto.c +M src/lib-sieve/ext-reject.c +A src/lib-sieve/scripts/tests/reject.sieve +M src/lib-sieve/sieve-ast.h +A src/lib-sieve/sieve-binary.c +A src/lib-sieve/sieve-binary.h +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-extensions.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/sieve-interpreter.h +M src/lib-sieve/sieve-validator.c +M src/lib-sieve/sieve-validator.h +M src/lib-sieve/sievec.c + +2007-10-21 18:55:38 +0200 Stephan Bosch <stephan@rename-it.nl> (36338359) + + Initial commit didn't compile because it was comitted in the middle of a new + feature. + + +M src/lib-sieve/cmd-if.c +M src/lib-sieve/ext-reject.c +M src/lib-sieve/sieve-code.c +M src/lib-sieve/sieve-code.h +M src/lib-sieve/sieve-commands-private.h +M src/lib-sieve/sieve-commands.c +M src/lib-sieve/sieve-extensions.h +M src/lib-sieve/sieve-generator.c +M src/lib-sieve/sieve-generator.h +M src/lib-sieve/sieve-interpreter.c +M src/lib-sieve/tst-address.c +M src/lib-sieve/tst-allof.c +M src/lib-sieve/tst-anyof.c +M src/lib-sieve/tst-exists.c +M src/lib-sieve/tst-header.c +M src/lib-sieve/tst-size.c + +2007-10-21 16:49:08 +0200 Stephan Bosch <stephan@rename-it.nl> (5775c74c) + + Added autogen.sh from the dovecot project (removed doc/wiki code) + + +A autogen.sh + +2007-10-21 16:31:24 +0200 stephan <stephan@flappie> (d9ba5172) + + Added -config files to the hgignore and removed them from the repository + + +M .hgignore +D libsieve-config.h.in + +2007-10-21 16:23:07 +0200 stephan <stephan@flappie> (ef67ede6) + + First entered libsieve into new Hg repository + + +A .hgignore +A AUTHORS +A COPYING.LGPL +A INSTALL +A Makefile.am +A NEWS +A README +A configure.in +A libsieve-config.h.in +A src/Makefile.am +A src/lib-sieve/Makefile.am +A src/lib-sieve/cmd-if.c +A src/lib-sieve/cmd-redirect.c +A src/lib-sieve/cmd-require.c +A src/lib-sieve/ext-envelope.c +A src/lib-sieve/ext-fileinto.c +A src/lib-sieve/ext-reject.c +A src/lib-sieve/plugins/comparator-i;ascii-numeric.c +A src/lib-sieve/plugins/copy.c +A src/lib-sieve/scripts/errors/address-errors.sieve +A src/lib-sieve/scripts/errors/header-errors.sieve +A src/lib-sieve/scripts/errors/if-errors.sieve +A src/lib-sieve/scripts/errors/interesting.sieve +A src/lib-sieve/scripts/errors/keep-errors.sieve +A src/lib-sieve/scripts/errors/parse-errors.sieve +A src/lib-sieve/scripts/errors/require-errors.sieve +A src/lib-sieve/scripts/errors/size-errors.sieve +A src/lib-sieve/scripts/errors/stop-errors.sieve +A src/lib-sieve/scripts/errors/tag-errors.sieve +A src/lib-sieve/scripts/examples/elvey.sieve +A src/lib-sieve/scripts/examples/mjohnson.sieve +A src/lib-sieve/scripts/examples/mklose.sieve +A src/lib-sieve/scripts/examples/rfc3028.sieve +A src/lib-sieve/scripts/examples/sanjay.sieve +A src/lib-sieve/scripts/examples/sieve_examples.sieve +A src/lib-sieve/scripts/examples/stephan.sieve +A src/lib-sieve/scripts/examples/unparsed-elvey.sieve +A src/lib-sieve/scripts/examples/vacation.sieve +A src/lib-sieve/scripts/examples/vivil.sieve +A src/lib-sieve/scripts/tests/if.sieve +A src/lib-sieve/sieve-address.c +A src/lib-sieve/sieve-ast.c +A src/lib-sieve/sieve-ast.h +A src/lib-sieve/sieve-code.c +A src/lib-sieve/sieve-code.h +A src/lib-sieve/sieve-commands-private.h +A src/lib-sieve/sieve-commands.c +A src/lib-sieve/sieve-commands.h +A src/lib-sieve/sieve-common.h +A src/lib-sieve/sieve-error.c +A src/lib-sieve/sieve-error.h +A src/lib-sieve/sieve-extensions.c +A src/lib-sieve/sieve-extensions.h +A src/lib-sieve/sieve-generator.c +A src/lib-sieve/sieve-generator.h +A src/lib-sieve/sieve-interpreter.c +A src/lib-sieve/sieve-interpreter.h +A src/lib-sieve/sieve-lexer.c +A src/lib-sieve/sieve-lexer.h +A src/lib-sieve/sieve-parser.c +A src/lib-sieve/sieve-parser.h +A src/lib-sieve/sieve-validator.c +A src/lib-sieve/sieve-validator.h +A src/lib-sieve/sievec.c +A src/lib-sieve/tst-address.c +A src/lib-sieve/tst-allof.c +A src/lib-sieve/tst-anyof.c +A src/lib-sieve/tst-exists.c +A src/lib-sieve/tst-header.c +A src/lib-sieve/tst-not.c +A src/lib-sieve/tst-size.c +A stamp.h.in diff --git a/pigeonhole/INSTALL b/pigeonhole/INSTALL new file mode 100644 index 0000000..eca1360 --- /dev/null +++ b/pigeonhole/INSTALL @@ -0,0 +1,903 @@ +Compiling +========= + +If you downloaded the sources using Mercurial, you will need to execute +./autogen.sh first to build the automake structure in your source tree. This +process requires autotools and libtool to be installed. + +If you installed Dovecot from sources, Pigeonhole's configure script should be +able to find the installed dovecot-config automatically: + +./configure +make +sudo make install + +If your system uses a $prefix different than the default /usr/local, the +configure script can still find the installed dovecot-config automatically when +supplied with the proper --prefix argument: + +./configure --prefix=/usr +make +sudo make install + +If this doesn't work, you can use --with-dovecot=<path> configure option, where +the path points to a directory containing dovecot-config file. This can point to +an installed file: + +./configure --with-dovecot=/usr/local/lib/dovecot +make +sudo make install + +or to a Dovecot source directory that is already compiled: + +./configure --with-dovecot=../dovecot-2.1.0 +make +sudo make install + +The following additional parameters may be of interest for the configuration of +the Pigeonhole build: + + --with-managesieve=yes + Controls whether Pigeonhole ManageSieve is compiled and installed, which is + the default. + + --with-unfinished-features=no + Controls whether unfinished features and extensions are built. Enabling this + will enable the compilation of code that is considered unfinished and highly + experimental and may therefore introduce bugs and unexpected behavior. + In fact, it may not compile at all. Enable this only when you are eager to + test some of the new development functionality. + + --with-ldap=no + Controls wether Sieve LDAP support is built. This allows retrieving Sieve + scripts from an LDAP database. When set to `yes', support is built in. When + set to `plugin', LDAP support is compiled into a Sieve plugin called + `sieve_storage_ldap'. + +Configuration +============= + +The Pigeonhole package provides the following items: + + - The Sieve interpreter plugin for Dovecot's Local Delivery Agent (LDA): This + facilitates the actual Sieve filtering upon delivery. + + - The ManageSieve Service: This implements the ManageSieve protocol through + which users can remotely manage Sieve scripts on the server. + +The functionality of these items is described in more detail in the README file. +In this file and in this section their configuration is described. Example +configuration files are provided in the doc/example-config directory of this +package. + +Sieve Interpreter - Script Locations +------------------------------------ + +The Sieve interpreter can retrieve Sieve scripts from several types of +locations. The default `file' location type is a local filesystem path pointing +to a Sieve script file or a directory containing multiple Sieve script files. +More complex setups can use other location types such as `ldap' or `dict' to +fetch Sieve scripts from remote databases. + +All settings that specify the location of one ore more Sieve scripts accept the +following syntax: + +location = [<type>:]path[;<option>[=<value>][;...]] + +The following script location types are implemented by default: + + file - The location path is a file system path pointing to the script file + or a directory containing script files with names structured as + `<script-name>.sieve'. Read doc/locations/file.txt for more + information and examples. + + dict - The location path is a Dovecot dict uri. Read doc/locations/dict.txt + for more information and examples. + + ldap - LDAP database lookup. The location path is a configuration file with + LDAP options. Read doc/locations/ldap.txt for more information + and examples. + +If the type prefix is omitted, the script location type is 'file' and the +location is interpreted as a local filesystem path pointing to a Sieve script +file or directory. + +The following options are defined for all location types: + + name=<script-name> + Set the name of the Sieve script that this location points to. If the name + of the Sieve script is not contained in the location path and the + location of a single script is specified, this option is required + (e.g. for dict locations that must point to a particular script). + If the name of the script is contained in the location path, the value of + the name option overrides the name retrieved from the location. If the Sieve + interpreter explicitly queries for a specific name (e.g. to let the Sieve + "include" extension retrieve a script from the sieve_global= location), + this option has no effect. + + bindir=<dirpath> + Points to the directory where the compiled binaries for this script location + are stored. This directory is created automatically if possible. If this + option is omitted, the behavior depends on the location type. For `file' + type locations, the binary is then stored in the same directory as where the + script file was found if possible. For `dict' type locations, the binary is + not stored at all in that case. Don't specify the same directory for + different script locations, as this will result in undefined behavior. + Multiple mail users can share a single script directory if the script + location is the same and all users share the same system credentials (uid, + gid). + +Sieve Interpreter - Basic Configuration +--------------------------------------- + +To use Sieve, you will first need to make sure you are using Dovecot LDA +or Dovecot LMTP for delivering incoming mail to users' mailboxes. Then, you need +to enable the Sieve interpreter plugin for LDA/LMTP in your dovecot.conf: + +protocol lda { +.. + mail_plugins = sieve # ... other plugins like quota +} + +protocol lmtp { +.. + mail_plugins = sieve # ... other plugins like quota +} + +The Sieve interpreter recognizes the following configuration options in the +plugin section of the config file (default values are shown if applicable): + + sieve = file:~/sieve;active=~/.dovecot.sieve + The location of the user's main Sieve script or script storage. The LDA + Sieve plugin uses this to find the active script for Sieve filtering at + delivery. The "include" extension uses this location for retrieving + :personal" scripts. + + This location is also where the ManageSieve service will store the user's + scripts, if supported by the location type. For the 'file' location type, the + location will then be the path to the storage directory for all the user's + personal Sieve scripts. ManageSieve maintains a symbolic link pointing to + the currently active script (the script executed at delivery). The location + of this symbolic link can be configured using the `;active=<path>' option. + + sieve_default = + The location of the default personal sieve script file, which gets executed + ONLY if user's private Sieve script does not exist, e.g. + /var/lib/dovecot/default.sieve. This is usually a global script, so be sure + to pre-compile this script manually using the sievec command line tool, as + explained in the README file. This setting used to be called + `sieve_global_path', but that name is now deprecated. + + sieve_default_name = + The name by which the default Sieve script is visible to ManageSieve + clients. Normally, it is not visible at all. See "Visible Default Script" + section below for more information. + + sieve_global = + Location for :global include scripts for the Sieve include extension. This + setting used to be called `sieve_global_dir', but that name is now + deprecated. + + sieve_discard = + The location of a Sieve script that is run for any message that is about to + be discarded; i.e., it is not delivered anywhere by the normal Sieve + execution. This only happens when the "implicit keep" is canceled, by e.g. + the "discard" action, and no actions that deliver the message are executed. + This "discard script" can prevent discarding the message, by executing + alternative actions. If the discard script does nothing, the message is still + discarded as it would be when no discard script is configured. + + sieve_extensions = + Which Sieve language extensions are available to users. By default, all + supported extensions are available, except for deprecated extensions or those + that are still under development. Some system administrators may want to + disable certain Sieve extensions or enable those that are not available by + default. This setting can use '+' and '-' to specify differences relative to + the default. For example `sieve_extensions = +imapflags' will enable the + deprecated imapflags extension in addition to all extensions were already + enabled by default. + + sieve_global_extensions = + Which Sieve language extensions are ONLY avalable in global scripts. This can + be used to restrict the use of certain Sieve extensions to administrator + control, for instance when these extensions can cause security concerns. This + setting has higher precedence than the `sieve_extensions' setting (above), + meaning that the extensions enabled with this setting are never available to + the user's personal script no matter what is specified for the + `sieve_extensions' setting. The syntax of this setting is similar to + the `sieve_extensions' setting, with the difference that extensions are + enabled or disabled for exclusive use in global scripts. Currently, no + extensions are marked as such by default. + + sieve_implicit_extensions = + Which Sieve language extensions are implicitly available to users. The + extensions listed in this setting do not need to be enabled explicitly using + the Sieve "require" command. This behavior directly violates the Sieve + standard, but can be necessary for compatibility with some existing + implementations of Sieve (notably jSieve). Do not use this setting unless you + really need to! The syntax and semantics of this setting are otherwise + identical to the `sieve_extensions' setting + + sieve_plugins = + The Pigeonhole Sieve interpreter can have plugins of its own. Using this + setting, the used plugins can be specified. Check the Dovecot wiki + (wiki2.dovecot.org) or the pigeonhole website (http://pigeonhole.dovecot.org) + for available plugins. The `sieve_extprograms' plugin is included in this + release. LDAP support may also be compiled as a plugin called + `sieve_storage_ldap'. + + sieve_user_email = + The primary e-mail address for the user. This is used as a default when no + other appropriate address is available for sending messages. If this setting + is not configured, either the postmaster or null "<>" address is used as a + sender, depending on the action involved. This setting is important when + there is no message envelope to extract addresses from, such as when the + script is executed in IMAP. + + sieve_user_log = + The path to the file where the user log file is written. If not configured, a + default location is used. If the main user's personal Sieve (as configured + with sieve=) is a file, the logfile is set to <filename>.log by default. If + it is not a file, the default user log file is ~/.dovecot.sieve.log. + + recipient_delimiter = + + The separator that is expected between the :user and :detail address parts + introduced by the subaddress extension. This may also be a sequence of + characters (e.g. '--'). The current implementation looks for the separator + from the left of the localpart and uses the first one encountered. The :user + part is left of the separator and the :detail part is right. This setting is + also used by Dovecot's LMTP service. + + sieve_redirect_envelope_from = sender + Specifies what envelope sender address is used for redirected messages. + Normally, the Sieve "redirect" command copies the sender address for the + redirected message from the processed message. So, the redirected message + appears to originate from the original sender. The following values are + supported for this setting: + + "sender" - The sender address is used (default). + "recipient" - The final recipient address is used. + "orig_recipient" - The original recipient is used. + "user_email" - The user's primary address is used. This is + configured with the "sieve_user_email" setting. If + that setting is unconfigured, "user_mail" is equal to + "sender" (the default). + "postmaster" - The postmaster_address configured for the LDA. + "<user@domain>" - Redirected messages are always sent from user@domain. + The angle brackets are mandatory. The null "<>" address + is also supported. + + When the envelope sender of the processed message is the null address "<>", + the envelope sender of the redirected message is also always "<>", + irrespective of what is configured for this setting. + + sieve_redirect_duplicate_period = 12h + In an effort to halt potential mail loops, the Sieve redirect action records + identifying information for messages it has forwarded. If a duplicate message + is seen, it is not redirected and the message is discarded; i.e., the + implicit keep is canceled. This setting configures the period during which + the identifying information is recorded. If an account forwards many + messages, it may be necessary to lower this setting to prevent the + ~/.dovecot.lda-dupes database file (in which these are recorded) from growing + to an impractical size. + +For example: + +plugin { +... + # The include extension fetches the :personal scripts from this + # directory. When ManageSieve is used, this is also where scripts + # are uploaded. + sieve = file:~/sieve + + # If the user has no personal active script (i.e. if the location + # indicated in sieve= settings does have and active script or does not exist), + # use this one: + sieve_default = /var/lib/dovecot/sieve/default.sieve + + # The include extension fetches the :global scripts from this + # directory. + sieve_global = /var/lib/dovecot/sieve/global/ +} + +Sieve Interpreter - Configurable Limits +--------------------------------------- + +The settings that specify a period are specified in s(econds), unless followed +by a d(ay), h(our), or m(inute) specifier character. + + sieve_max_script_size = 1M + The maximum size of a Sieve script. The compiler will refuse to compile any + script larger than this limit. If set to 0, no limit on the script size is + enforced. + + sieve_max_actions = 32 + The maximum number of actions that can be performed during a single script + execution. If set to 0, no limit on the total number of actions is enforced. + + sieve_max_redirects = 4 + The maximum number of redirect actions that can be performed during a single + script execution. If set to 0, no redirect actions are allowed. + + sieve_max_cpu_time = 30s + The maximum amount of CPU time that a Sieve script is allowed to use while + executing. If the execution exceeds this resource limit, the script ends with + an error, causing the implicit "keep" action to be executed. This limit is + not only enforced for a single script execution, but also cumulatively for + the last executions within a configurable timeout + (see sieve_resource_usage_timeout). + + sieve_resource_usage_timeout = 1h + To prevent abuse, the Sieve interpreter can record resource usage of a Sieve + script execution in the compiled binary if it is significant. Currently, this + happens when CPU system + user time exceeds 1.5 seconds for one execution. + Such high resource usage is summed over time in the binary and once that + cumulative resource usage exceeds the limits (sieve_max_cpu_time), the Sieve + script is disabled in the binary for future execution, even if an individual + execution exceeded no limits. If the last time high resource usage was + recorded is older than sieve_resource_usage_timeout, the resource usage in + the binary is reset. This means that the Sieve script is only disabled when + the limits are cumulatively exceeded within this timeout. With the default + configuration this means that the Sieve script is only disabled when the + total CPU time of Sieve executions that lasted more than 1.5 seconds exceeds + 30 seconds in the last hour. A disabled Sieve script can be reactivated by + the user by uploading a new version of the Sieve script after the excessive + resource usage times out. An administrator can force reactivation by forcing + a script compile (e.g. using the sievec command line tool). + +Sieve Interpreter - Per-user Sieve Script Location +-------------------------------------------------- + +By default, the Pigeonhole LDA Sieve plugin looks for the user's Sieve script +file in the user's home directory (~/.dovecot.sieve). This requires that the +home directory is set for the user. + +If you want to store the script elsewhere, you can override the default using +the sieve= setting, which specifies the location of the user's script file. This +can be done in two ways: + + 1. Define the sieve setting in the plugin section of dovecot.conf. + 2. Return sieve extra field from userdb extra fields. + +For example, to use a Sieve script file named <username>.sieve in +/var/sieve-scripts, use: + +plugin { +... + + sieve = /var/sieve-scripts/%u.sieve +} + +You may use templates like %u, as shown in the example. Refer to +http://wiki.dovecot.org/Variables for more information. + +A relative path (or just a filename) will be interpreted to point under the +user's home directory. + +Sieve Interpreter - Executing Multiple Scripts Sequentially +----------------------------------------------------------- + +Pigeonhole's Sieve interpreter allows executing multiple Sieve scripts +sequentially. The extra scripts can be executed before and after the user's +private script. For example, this allows executing global Sieve policies before +the user's script. The following settings in the plugin section of the Dovecot +config file control the execution sequence: + + sieve_before = + sieve_before2 = + sieve_before3 = (etc..) + Location Sieve of scripts that need to be executed before the user's personal + script. If a 'file' location path points to a directory, all the Sieve + scripts contained therein (with the proper `.sieve' extension) are executed. + The order of execution within that directory is determined by the file names, + using a normal 8bit per-character comparison. + + Multiple script locations can be specified by appending an increasing number + to the setting name. The Sieve scripts found from these locations are added + to the script execution sequence in the specified order. Reading the numbered + sieve_before settings stops at the first missing setting, so no numbers may + be skipped. + + sieve_after = + sieve_after2 = + sieve_after3 = (etc..) + Identical to sieve_before, but the specified scripts are executed after the + user's script (only when keep is still in effect, as explained below). + +The script execution ends when the currently executing script in the sequence +does not yield a "keep" result: when the script terminates, the next script is +only executed if an implicit or explicit "keep" is in effect. Thus, to end all +script execution, a script must not execute keep and it must cancel the implicit +keep, e.g. by executing "discard; stop;". This means that the command "keep;" +has different semantics when used in a sequence of scripts. For normal Sieve +execution, "keep;" is equivalent to "fileinto "INBOX";", because both cause the +message to be stored in INBOX. However, in sequential script execution, it only +controls whether the next script is executed. Storing the message into INBOX +(the default folder) is not done until the last script in the sequence executes +(implicit) keep. To force storing the message into INBOX earlier in the +sequence, the fileinto command can be used (with ":copy" or together with +"keep;"). + +Apart from the keep action, all actions triggered in a script in the sequence +are executed before continuing to the next script. This means that when a script +in the sequence encounters an error, actions from earlier executed scripts are +not affected. The sequence is broken however, meaning that the script execution +of the offending script is aborted and no further scripts are executed. An +implicit keep is executed instead if necessary, meaning that the interpreter +makes sure that the message is at least stored in the default folder (INBOX). + +Just as for executing a single script the normal way, the Pigeonhole LDA Sieve +plugin takes care never to duplicate deliveries, forwards or responses. When +vacation actions are executed multiple times in different scripts, the usual +error is not triggered: the subsequent duplicate vacation actions are simply +discarded. + +For example: + +plugin { +... + # Global scripts executed before the user's personal script. + # E.g. handling messages marked as dangerous + sieve_before = /var/lib/dovecot/sieve/discard-virusses.sieve + + # Domain-level scripts retrieved from LDAP + sieve_before2 = ldap:/etc/dovecot/sieve-ldap.conf;name=ldap-domain + + # User-specific scripts executed before the user's personal script. + # E.g. a vacation script managed through a non-ManageSieve GUI. + sieve_before3 = /var/vmail/%d/%n/sieve-before + + # User-specific scripts executed after the user's personal script. + # (if keep is still in effect) + # E.g. user-specific default mail filing rules + sieve_after = /var/vmail/%d/%n/sieve-after + + # Global scripts executed after the user's personal script + # (if keep is still in effect) + # E.g. default mail filing rules. + sieve_after2 = /var/lib/dovecot/sieve/after.d/ +} + +IMPORTANT: The scripts specified by sieve_before and sieve_after are often +located in global locations to which the Sieve interpreter has no write access +to store the compiled binaries. In that case, be sure to manually pre-compile +those scripts using the sievec tool, as explained in the README file. + +Sieve Interpreter - Visible Default Script +------------------------------------------ + +The `sieve_default=' setting specifies the location of a default script that +is executed when the user has no active personal script. Normally, this +default script is invisible to the user; i.e., it is not listed in ManageSieve. +To give the user the ability to see and read the default script, it is possible +to make it visible under a specific configurable name using the +`sieve_default_name' setting. + +ManageSieve will magically list the default script under that name, even though +it does not actually exist in the user's normal script storage location. This +way, the ManageSieve client can see that it exists and it can retrieve its +contents. If no normal script is active, the default is always listed as active. +The user can replace the default with a custom script, by uploading it under the +default script's name. If that custom script is ever deleted, the default script +will reappear from the shadows implicitly. + +This way, ManageSieve clients will not need any special handling for this +feature. If the name of the default script is equal to the name the client uses +for the main script, it will initially see and read the default script when the +user account is freshly created. The user can edit the script, and when the +edited script is saved through the ManageSieve client, it will will override the +default script. If the user ever wants to revert to the default, the user only +needs to delete the edited script and the default will reappear. + +The name by which the default script will be known is configured using the +`sieve_default_name' setting. Of course, the `sieve_default' setting needs to +point to a valid script location as well for this to work. If the default script +does not exist at the indicated location, it is not shown. + +For example: + +plugin { +... + sieve = file:~/sieve;active=~/.dovecot.sieve + + sieve_default = /var/lib/dovecot/sieve/default.sieve + sieve_default_name = roundcube +} + +Sieve Interpreter - Extension Configuration +------------------------------------------- + +- Editheader extension: + + The editheader extension [RFC5293] enables sieve scripts to interact with + other components that consume or produce header fields by allowing the script + to delete and add header fields. + + The editheader extension requires explicit configuration and is not enabled + for use by default. Refer to doc/extensions/editheader.txt for configuration + information. + +- Vacation extension: + + The Sieve vacation extension [RFC5230] defines a mechanism to generate + automatic replies to incoming email messages. + + The vacation extension is available by default, but it has its own specific + configuration options. Refer to doc/extensions/vacation.txt for settings + specific to the vacation extension. + +- Variables extension: + + The Sieve variables extension [RFC5229] adds the concept of variables to the + Sieve language. + + The variables extension is available by default, but it has its own specific + configuration options. Refer to doc/extensions/variables.txt for settings + specific to the variables extension. + +- Include extension: + + The Sieve include extension (draft) permits users to include one Sieve script + into another. + + The include extension is available by default, but it has its own specific + configuration options. Refer to doc/extensions/include.txt for settings + specific to the include extension. + +- Spamtest and virustest extensions: + + Using the spamtest and virustest extensions (RFC 5235), the Sieve language + provides a uniform and standardized command interface for evaluating spam and + virus tests performed on the message. Users no longer need to know what headers + need to be checked and how the scanner's verdict is represented in the header + field value. They only need to know how to use the spamtest (spamtestplus) and + virustest extensions. This also gives GUI-based Sieve editors the means to + provide a portable and easy to install interface for spam and virus filter + configuration. + + The spamtest, spamtestplus and virustest extensions require explicit + configuration and are not enabled for use by default. Refer to + doc/extensions/spamtest-virustest.txt for configuration information. + +- Duplicate extension: + + The duplicate extension augments the Sieve filtering implementation with a + test that facilitates detecting and handling duplicate message deliveries, + e.g. as caused by mailinglists when people reply both to the mailinglist and + the user directly. + + Refer to doc/extensions/vnd.dovecot.duplicate.txt for configuration + information. + +- Dovecot environment extension: + + The vnd.dovecot.environment extension builds on the standard environment + extension. It adds a few extra environment items that are useful for Sieve + scripts used by Dovecot. + + Refer to doc/extensions/vnd.dovecot.environment.txt for more information. + +- Extprograms plugin; + vnd.dovovecot.pipe, vnd.dovecot.filter, vnd.dovecot.execute extensions: + + The "sieve_extprograms" plugin provides extensions to the Sieve filtering + language adding new action commands for invoking a predefined set of external + programs. Messages can be piped to or filtered through those programs and + string data can be input to and retrieved from those programs. + + This plugin and the extensions it provides require explicit configuration and + are not enabled for use by default. Refer to doc/plugins/sieve_extprograms.txt + for more information. + +- Imapsieve plugins + + The "sieve_imapsieve" Sieve plugin and the "imap_sieve" IMAP plugin add Sieve + support to IMAP. + + Refer to doc/plugins/imapsieve.txt for more information. + +- IMAP Filter Sieve plugin + + The "imap_filter_sieve" plugin adds the ability to manually invoke Sieve + filtering in IMAP. + + Refer to doc/plugins/imap_filter_sieve.txt for more information. + +Sieve Interpreter - Trace Debugging +----------------------------------- + +Trace debugging provides detailed insight in the operations performed by +the Sieve script. Messages about what the Sieve script is doing are written +to the specified directory. + +WARNING: On a busy server, this functionality can quickly fill up the trace +directory with a lot of trace files. Enable this only temporarily and as +selective as possible. + +The following settings apply to both the LDA Sieve plugin and the IMAPSIEVE +plugin: + + sieve_trace_dir = + The directory where trace files are written. Trace debugging is disabled if + this setting is not configured or if the directory does not exist. If the + path is relative or it starts with "~/" it is interpreted relative to the + current user's home directory. + + sieve_trace_level = + The verbosity level of the trace messages. Trace debugging is disabled if + this setting is not configured. Possible values are: + + "actions" - Only print executed action commands, like keep, fileinto, + reject and redirect. + "commands" - Print any executed command, excluding test commands. + "tests" - Print all executed commands and performed tests. + "matching" - Print all executed commands, performed tests and the values + matched in those tests. + + sieve_trace_debug = no + Enables highly verbose debugging messages that are usually only useful for + developers. + + sieve_trace_addresses = no + Enables showing byte code addresses in the trace output, rather than only + the source line numbers. + +Sieve Interpreter - Migration from CMUSieve (Dovecot v1.0/v1.1) +--------------------------------------------------------------- + +For the most part, migration from CMUSieve to the Pigeonhole LDA Sieve plugin is +just a matter of changing the used plugin name from 'cmusieve' to 'sieve' in the +mail_plugins option in the protocol lda section of the config file (as explained +above). However, there are a few important differences: + + * The imapflags extension is now called imap4flags. The CMUSieve implementation + is based on an old draft specification that is not completely compatible. + Particularly, the mark and unmark commands were removed from the new + specification. For backwards compatibility, support for the old imapflags + extension can be enabled using the sieve_extensions setting (as explained + above). This is disabled by default. + + * The notify extension is now called enotify. The CMUSieve implementation is + based on an old draft specification that is not completely compatible. + Particularly, the denotify command and $text$ substitutions were removed from + the new specification. For backwards compatibility, support for the old + imapflags extension can be enabled using the sieve_extensions setting (as + explained above). This is disabled by default. + + * The include extension now requires your script file names to end with + ".sieve". This means that ` include :personal "myscript"; ' won't work unless + you rename "myscript" to "myscript.sieve" + +Sieve Interpreter - Migration from Dovecot Sieve v0.1.x (Dovecot v1.2) +---------------------------------------------------------------------- + + * Dovecot v2.0 adds support for LMTP. Much like the Dovecot LDA, it can make + use of the Pigeonhole Sieve plugin. Since the LMTP service has its own + prototocol lmtp section in the config file, you need to add the Sieve plugin + to the mail_plugins setting there too when you decide to use LMTP. + * The 'sieve_subaddress_sep' setting for the Sieve subaddress extension is now + known as 'recipient_delimiter'. Although sieve_subaddress_sep is still + recognized for backwards compatibility, it is recommended to update the + setting to the new name, since the LMTP service also uses the + recipient_delimiter setting. + +ManageSieve Service - Basic Configuration +----------------------------------------- + +IMPORTANT: + + If you have used the LDA Sieve plugin without ManageSieve before and you have + .dovecot.sieve files in user directories, you are advised to make a backup + before installing ManageSieve. Although the ManageSieve service takes care to + move these files to the Sieve directory before it is substituted with a + symbolic link, this is not a very well tested operation, meaning that there is + a slim possibility that existing Sieve scripts get lost. + +Just like all other binaries that Dovecot uses, the managesieve and +managesieve-login binaries are installed during make install. + +There are two things that have be done to activate the ManageSieve support in +Dovecot: + + * The first step is to add `sieve' to the protocols= configuration line in + your dovecot.conf. + + * The next step is specifying an additional service type for the ManageSieve + service. This could be done in Dovecot's conf.d/master.conf or you can use + the 20-managesieve.conf file from the doc/example-config/conf.d directory of + this package. + + For example: + + service managesieve-login { + inet_listener sieve { + port = 4190 + } + } + +Because the implementation of the ManageSieve daemon is largely based on the +original IMAP implementation, it is very similar in terms of configuration. The +following settings can be configured in the 'protocol sieve' section: + + managesieve_max_line_length = 65536 + The maximum ManageSieve command line length in bytes. This setting is + directly borrowed from IMAP. But, since long command lines are very unlikely + with ManageSieve, changing this will not be very useful. + + managesieve_logout_format = bytes=%i/%o + Specifies the string pattern used to compose the logout message of an + authenticated session. The following substitutions are available: + + %i - total number of bytes read from client + %o - total number of bytes sent to client + + managesieve_implementation_string = Dovecot Pigeonhole + To fool ManageSieve clients that are focused on CMU's timesieved, you can + specify the IMPLEMENTATION capability that the Dovecot reports to clients + (e.g. 'Cyrus timsieved v2.2.13'). + + managesieve_max_compile_errors = 5 + The maximum number of compile errors that are returned to the client upon + script upload or script verification. + + managesieve_sieve_capability = + managesieve_notify_capability = + Respectively the SIEVE and NOTIFY capabilities reported by the ManageSieve + service before authentication. If left unassigned these will be assigned + dynamically according to what the Sieve interpreter supports by default + (after login this may differ depending on the authenticated user). + +Additionally, the ManageSieve service uses the following settings from the +plugin section of the config file. These settings are the same ones used by +the LDA Sieve plugin. + + sieve = file:~/sieve;active=~/.dovecot.sieve + This specifies the location where the scripts that are uploaded through + ManageSieve are stored. During delivery, the LDA Sieve plugin uses this + location setting to find the active script for Sieve filtering. The Sieve + "include" extension uses this location for retrieving ":personal" scripts. + If the location type does not allow uploading scripts, the ManageSieve + service cannot be used. Currently, only the 'file' location type supports + ManageSieve. + + For the 'file' location type: + + * The location is the path to the storage directory for all the user's + personal Sieve scripts. Scripts are stored as separate files with + extension .sieve. All other files are ignored when scripts are listed + by a ManageSieve client. The storage directory is always generated + automatically if it does not exist (as far as the system permits the + user to do so; no root privileges are used). This is similar to the + behavior of the mail daemons regarding the mail_location configuration. + + * ManageSieve maintains a symbolic link pointing to the currently active + script (the script executed at delivery). The location of this symbolic + link can be configured using the ;active=<path> option. If a regular + file already exists at the location specified by in the ;active=<path> + location option, it is moved to the storage directory before the + symbolic link is installed. It is renamed to dovecot.orig.sieve and + therefore listed as dovecot.orig by a ManageSieve client. + + NOTE: It is not wise to place this active symbolic link inside your + mail store, as it may be mistaken for a mail folder. Inside a + maildir for instance, the default .dovecot.sieve would show up + as phantom folder /dovecot/sieve in your IMAP tree. + + For Pigeonhole versions before v0.3.1, this setting can only be a + filesystem path pointing to a script file, or - when ManageSieve is used - + it is the location of the symbolic link pointing to the active script in + the storage directory. That storage directory is then configured using the + deprecated `sieve_dir' setting. + +The following provides an example configuration for Sieve and ManageSieve. Only +sections and settings relevant to ManageSieve are shown. Refer to +20-managesieve.conf in the doc/example-config/conf.d directory for a full +example with comments, but don't forget to configure Sieve and add sieve to the +'protocols = ...' setting if you use it. + +# *** conf.d/20-managesieve.conf *** + +service managesieve-login { + inet_listener sieve { + # Bind the daemon only to the specified address(es) + # (default: *, ::) + address = 127.0.0.1 + # Specify an alternative port the daemon must listen on + # (default: 4190) + port = 2000 + } +} + +protocol sieve { + managesieve_max_compile_errors = 10 +} + +# *** conf.d/90-sieve.conf *** + +plugin { + sieve=file:~/sieve;active=~/.dovecot.sieve +} + +# *** dovecot.conf *** + +# .... (other config items) + +# Start imap, pop3, lmtp and managesieve services +protocols = imap pop3 lmtp sieve + +# .... (other config items) + +ManageSieve Service - Quota Support +----------------------------------- + +By default, users can manage an unlimited number of Sieve scripts on the server +through ManageSieve. However, ManageSieve can be configured to enforce limits on +the number of personal Sieve scripts per user and/or the amount of disk storage +used by these scripts. The maximum size of individual uploaded scripts is +dictated by the configuration of the Sieve plugin. The limits are configured in +the plugin section of the Dovecot configuration as follows: + + sieve_max_script_size = 1M + The maximum size of a Sieve script. If set to 0, no limit on the script size + is enforced. + + sieve_quota_max_scripts = 0 + The maximum number of personal Sieve scripts a single user can have. If set + to 0, no limit on the number of scripts is enforced. + + sieve_quota_max_storage = 0 + The maximum amount of disk storage a single user's scripts may occupy. If set + to 0, no limit on the used amount of disk storage is enforced. + +ManageSieve Service - Proxying +------------------------------ + +Like Dovecot's imapd, the ManageSieve login daemon supports proxying to multiple +backend servers. Although the underlying code is copied from the imapd sources +for the most part, it has some ManageSieve-specifics that have not seen much +testing. + +The proxy configuration wiki page for POP3 and IMAP should apply to ManageSieve +as well: + +http://wiki.dovecot.org/PasswordDatabase/ExtraFields/Proxy + +ManageSieve Service - Migration +------------------------------- + +The following has changed since the ManageSieve releases for Dovecot v1.x: + + * For Dovecot v1.0 and v1.1, the sieve_dir setting used by ManageSieve was + called sieve_storage. Also, the sieve and sieve_storage settings were located + inside the 'protocol managesieve' section of the configuration. As per + Dovecot v1.2, these settings are shared with the Sieve plugin and located in + the 'plugin' section of the configuration. Make sure you have updated the + name of the sieve_dir setting and the location of both these settings if you + are upgrading from ManageSieve for Dovecot v1.0/v1.1. + * Pigeonhole ManageSieve does not use the mail_location configuration as a + fall-back anymore to determine a default location for storing Sieve scripts. + It always uses the sieve_dir setting, with default value ~/sieve. + * The Pigeonhole ManageSieve service now binds to TCP port 4190 by default due + to the IANA port assignment for the ManageSieve service. When upgrading from + v1.x, this should be taken into account. For a smooth transition, the service + can be configured manually to listen on both port 2000 and port 4190, as + demonstrated in the example above. + * The Dovecot configuration now calls the ManageSieve protocol 'sieve' instead + of 'managesieve' because it is registered as such with IANA. The binaries and + the services are still called 'managesieve' and 'managesieve-login'. The + example above demonstrates how this affects the configuration. + +Test Suite +========== + +This package includes a test suite to verify the basic processing of the Sieve +interpreter on your particular platform. Note that the test suite is not +available when this package is compiled against the Dovecot headers only. The +test suite executes a list of test cases and halts when one of them fails. If it +executes all test cases successfully, the test suite finishes. You can execute +the basic test suite using `make test`, which does not include the plugins. You +can test the plugins using `make test-plugins`. + +A failing test case is always a bug and a report is greatly appreciated. + + diff --git a/pigeonhole/Makefile.am b/pigeonhole/Makefile.am new file mode 100644 index 0000000..1dfb0e6 --- /dev/null +++ b/pigeonhole/Makefile.am @@ -0,0 +1,227 @@ +aclocaldir = $(datadir)/aclocal + +if BUILD_DOCS +DOCS = doc +endif + +SUBDIRS = \ + . \ + src \ + $(DOCS) + +ACLOCAL_AMFLAGS = -I m4 + +EXTRA_DIST = \ + tests \ + examples \ + COPYING.LGPL \ + ChangeLog \ + update-version.sh + +dist-hook: + rm -rf `find $(distdir)/tests -type f -name '*.svbin'` + +pkginc_libdir=$(dovecot_pkgincludedir)/sieve +dist_pkginc_lib_HEADERS = \ + pigeonhole-version.h +nodist_pkginc_lib_HEADERS = \ + pigeonhole-config.h + +ChangeLog: + git log --name-status \ + --pretty="format:%ai %aN <%aE> (%h)%n%n%w(80,4,4)%s%n%n%b" > ChangeLog \ + || rm -f ChangeLog + +dist_aclocal_DATA = dovecot-pigeonhole.m4 + +pigeonhole-version.h: noop + $(SHELL) $(top_srcdir)/update-version.sh $(top_srcdir) $(top_builddir) + +noop: + +DISTCLEANFILES = \ + $(top_builddir)/pigeonhole-version.h \ + $(top_builddir)/run-test.sh + +# Testsuite tests (FIXME: ugly) + +TESTSUITE_BIN = $(top_builddir)/src/testsuite/testsuite $(TESTSUITE_OPTIONS) + +TEST_BIN = $(RUN_TEST) $(TESTSUITE_BIN) + +if BUILD_UNFINISHED +test_unfinished = +else +test_unfinished = +endif + +test_cases = \ + tests/testsuite.svtest \ + tests/control-if.svtest \ + tests/control-stop.svtest \ + tests/test-allof.svtest \ + tests/test-anyof.svtest \ + tests/test-exists.svtest \ + tests/test-header.svtest \ + tests/test-address.svtest \ + tests/test-size.svtest \ + tests/compile/compile.svtest \ + tests/compile/errors.svtest \ + tests/compile/warnings.svtest \ + tests/compile/recover.svtest \ + tests/execute/errors.svtest \ + tests/execute/errors-cpu-limit.svtest \ + tests/execute/actions.svtest \ + tests/execute/smtp.svtest \ + tests/execute/mailstore.svtest \ + tests/execute/address-normalize.svtest \ + tests/execute/examples.svtest \ + tests/lexer.svtest \ + tests/comparators/i-octet.svtest \ + tests/comparators/i-ascii-casemap.svtest \ + tests/match-types/is.svtest \ + tests/match-types/contains.svtest \ + tests/match-types/matches.svtest \ + tests/multiscript/basic.svtest \ + tests/multiscript/conflicts.svtest \ + tests/extensions/encoded-character.svtest \ + tests/extensions/envelope.svtest \ + tests/extensions/variables/basic.svtest \ + tests/extensions/variables/match.svtest \ + tests/extensions/variables/modifiers.svtest \ + tests/extensions/variables/quoting.svtest \ + tests/extensions/variables/string.svtest \ + tests/extensions/variables/errors.svtest \ + tests/extensions/variables/regex.svtest \ + tests/extensions/include/errors.svtest \ + tests/extensions/include/variables.svtest \ + tests/extensions/include/once.svtest \ + tests/extensions/include/twice.svtest \ + tests/extensions/include/optional.svtest \ + tests/extensions/include/rfc.svtest \ + tests/extensions/include/execute.svtest \ + tests/extensions/imap4flags/basic.svtest \ + tests/extensions/imap4flags/hasflag.svtest \ + tests/extensions/imap4flags/execute.svtest \ + tests/extensions/imap4flags/multiscript.svtest \ + tests/extensions/imap4flags/flagstring.svtest \ + tests/extensions/imap4flags/flagstore.svtest \ + tests/extensions/body/basic.svtest \ + tests/extensions/body/errors.svtest \ + tests/extensions/body/raw.svtest \ + tests/extensions/body/content.svtest \ + tests/extensions/body/text.svtest \ + tests/extensions/body/match-values.svtest \ + tests/extensions/regex/basic.svtest \ + tests/extensions/regex/match-values.svtest \ + tests/extensions/regex/errors.svtest \ + tests/extensions/reject/execute.svtest \ + tests/extensions/reject/smtp.svtest \ + tests/extensions/relational/basic.svtest \ + tests/extensions/relational/rfc.svtest \ + tests/extensions/relational/errors.svtest \ + tests/extensions/relational/comparators.svtest \ + tests/extensions/subaddress/basic.svtest \ + tests/extensions/subaddress/rfc.svtest \ + tests/extensions/subaddress/config.svtest \ + tests/extensions/vacation/errors.svtest \ + tests/extensions/vacation/execute.svtest \ + tests/extensions/vacation/message.svtest \ + tests/extensions/vacation/smtp.svtest \ + tests/extensions/vacation/utf-8.svtest \ + tests/extensions/vacation/reply.svtest \ + tests/extensions/enotify/basic.svtest \ + tests/extensions/enotify/encodeurl.svtest \ + tests/extensions/enotify/valid_notify_method.svtest \ + tests/extensions/enotify/notify_method_capability.svtest \ + tests/extensions/enotify/errors.svtest \ + tests/extensions/enotify/execute.svtest \ + tests/extensions/enotify/mailto.svtest \ + tests/extensions/environment/basic.svtest \ + tests/extensions/environment/rfc.svtest \ + tests/extensions/mailbox/errors.svtest \ + tests/extensions/mailbox/execute.svtest \ + tests/extensions/date/basic.svtest \ + tests/extensions/date/date-parts.svtest \ + tests/extensions/date/zones.svtest \ + tests/extensions/index/basic.svtest \ + tests/extensions/index/errors.svtest \ + tests/extensions/spamvirustest/spamtest.svtest \ + tests/extensions/spamvirustest/virustest.svtest \ + tests/extensions/spamvirustest/spamtestplus.svtest \ + tests/extensions/spamvirustest/errors.svtest \ + tests/extensions/ihave/execute.svtest \ + tests/extensions/ihave/errors.svtest \ + tests/extensions/ihave/restrictions.svtest \ + tests/extensions/editheader/addheader.svtest \ + tests/extensions/editheader/deleteheader.svtest \ + tests/extensions/editheader/alternating.svtest \ + tests/extensions/editheader/utf8.svtest \ + tests/extensions/editheader/protected.svtest \ + tests/extensions/editheader/errors.svtest \ + tests/extensions/editheader/execute.svtest \ + tests/extensions/duplicate/errors.svtest \ + tests/extensions/duplicate/execute.svtest \ + tests/extensions/duplicate/execute-vnd.svtest \ + tests/extensions/metadata/execute.svtest \ + tests/extensions/metadata/errors.svtest \ + tests/extensions/mime/errors.svtest \ + tests/extensions/mime/header.svtest \ + tests/extensions/mime/exists.svtest \ + tests/extensions/mime/address.svtest \ + tests/extensions/mime/execute.svtest \ + tests/extensions/mime/content-header.svtest \ + tests/extensions/mime/foreverypart.svtest \ + tests/extensions/mime/extracttext.svtest \ + tests/extensions/mime/calendar-example.svtest \ + tests/extensions/special-use/errors.svtest \ + tests/extensions/special-use/execute.svtest \ + tests/extensions/vnd.dovecot/debug/execute.svtest \ + tests/extensions/vnd.dovecot/environment/basic.svtest \ + tests/extensions/vnd.dovecot/environment/variables.svtest \ + tests/extensions/vnd.dovecot/report/errors.svtest \ + tests/extensions/vnd.dovecot/report/execute.svtest \ + tests/deprecated/notify/basic.svtest \ + tests/deprecated/notify/mailto.svtest \ + tests/deprecated/notify/errors.svtest \ + tests/deprecated/notify/execute.svtest \ + tests/deprecated/notify/denotify.svtest \ + tests/deprecated/imapflags/execute.svtest \ + tests/deprecated/imapflags/errors.svtest \ + $(test_unfinished) + +$(test_cases): + @$(TEST_BIN) $(top_srcdir)/$@ + +failure_test_cases = \ + tests/failures/fuzz1.svtest \ + tests/failures/fuzz2.svtest \ + tests/failures/fuzz3.svtest \ + tests/failures/mailbox-bad-utf8.svtest + +$(failure_test_cases): + @$(TEST_BIN) -F $(top_srcdir)/$@ + +TEST_EXTPROGRAMS_BIN = NOCHILDREN=yes $(TEST_BIN) \ + -P src/plugins/sieve-extprograms/.libs/sieve_extprograms + +extprograms_test_cases = \ + tests/plugins/extprograms/errors.svtest \ + tests/plugins/extprograms/pipe/command.svtest \ + tests/plugins/extprograms/pipe/errors.svtest \ + tests/plugins/extprograms/pipe/execute.svtest \ + tests/plugins/extprograms/filter/command.svtest \ + tests/plugins/extprograms/filter/errors.svtest \ + tests/plugins/extprograms/filter/execute.svtest \ + tests/plugins/extprograms/execute/command.svtest \ + tests/plugins/extprograms/execute/errors.svtest \ + tests/plugins/extprograms/execute/execute.svtest + +$(extprograms_test_cases): + @$(TEST_EXTPROGRAMS_BIN) $(top_srcdir)/$@ + +.PHONY: test test-plugins $(test_cases) $(failure_test_cases) $(extprograms_test_cases) +test: all-am $(test_cases) $(failure_test_cases) +test-plugins: all-am $(extprograms_test_cases) + +check: check-am test diff --git a/pigeonhole/Makefile.in b/pigeonhole/Makefile.in new file mode 100644 index 0000000..ce81b2d --- /dev/null +++ b/pigeonhole/Makefile.in @@ -0,0 +1,1233 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(dist_aclocal_DATA) \ + $(dist_pkginc_lib_HEADERS) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = dummy-config.h pigeonhole-config.h +CONFIG_CLEAN_FILES = stamp.h +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(aclocaldir)" \ + "$(DESTDIR)$(pkginc_libdir)" "$(DESTDIR)$(pkginc_libdir)" +DATA = $(dist_aclocal_DATA) +HEADERS = $(dist_pkginc_lib_HEADERS) $(nodist_pkginc_lib_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + cscope distdir distdir-am dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ + dummy-config.h.in pigeonhole-config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +DIST_SUBDIRS = . src doc +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/dummy-config.h.in \ + $(srcdir)/pigeonhole-config.h.in $(srcdir)/stamp.h.in AUTHORS \ + COPYING ChangeLog INSTALL NEWS README TODO compile \ + config.guess config.rpath config.sub install-sh ltmain.sh \ + missing +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +DIST_TARGETS = dist-gzip +# Exists only to be overridden by the user if desired. +AM_DISTCHECK_DVI_TARGET = dvi +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +aclocaldir = $(datadir)/aclocal +@BUILD_DOCS_TRUE@DOCS = doc +SUBDIRS = \ + . \ + src \ + $(DOCS) + +ACLOCAL_AMFLAGS = -I m4 +EXTRA_DIST = \ + tests \ + examples \ + COPYING.LGPL \ + ChangeLog \ + update-version.sh + +pkginc_libdir = $(dovecot_pkgincludedir)/sieve +dist_pkginc_lib_HEADERS = \ + pigeonhole-version.h + +nodist_pkginc_lib_HEADERS = \ + pigeonhole-config.h + +dist_aclocal_DATA = dovecot-pigeonhole.m4 +DISTCLEANFILES = \ + $(top_builddir)/pigeonhole-version.h \ + $(top_builddir)/run-test.sh + + +# Testsuite tests (FIXME: ugly) +TESTSUITE_BIN = $(top_builddir)/src/testsuite/testsuite $(TESTSUITE_OPTIONS) +TEST_BIN = $(RUN_TEST) $(TESTSUITE_BIN) +@BUILD_UNFINISHED_FALSE@test_unfinished = +@BUILD_UNFINISHED_TRUE@test_unfinished = +test_cases = \ + tests/testsuite.svtest \ + tests/control-if.svtest \ + tests/control-stop.svtest \ + tests/test-allof.svtest \ + tests/test-anyof.svtest \ + tests/test-exists.svtest \ + tests/test-header.svtest \ + tests/test-address.svtest \ + tests/test-size.svtest \ + tests/compile/compile.svtest \ + tests/compile/errors.svtest \ + tests/compile/warnings.svtest \ + tests/compile/recover.svtest \ + tests/execute/errors.svtest \ + tests/execute/errors-cpu-limit.svtest \ + tests/execute/actions.svtest \ + tests/execute/smtp.svtest \ + tests/execute/mailstore.svtest \ + tests/execute/address-normalize.svtest \ + tests/execute/examples.svtest \ + tests/lexer.svtest \ + tests/comparators/i-octet.svtest \ + tests/comparators/i-ascii-casemap.svtest \ + tests/match-types/is.svtest \ + tests/match-types/contains.svtest \ + tests/match-types/matches.svtest \ + tests/multiscript/basic.svtest \ + tests/multiscript/conflicts.svtest \ + tests/extensions/encoded-character.svtest \ + tests/extensions/envelope.svtest \ + tests/extensions/variables/basic.svtest \ + tests/extensions/variables/match.svtest \ + tests/extensions/variables/modifiers.svtest \ + tests/extensions/variables/quoting.svtest \ + tests/extensions/variables/string.svtest \ + tests/extensions/variables/errors.svtest \ + tests/extensions/variables/regex.svtest \ + tests/extensions/include/errors.svtest \ + tests/extensions/include/variables.svtest \ + tests/extensions/include/once.svtest \ + tests/extensions/include/twice.svtest \ + tests/extensions/include/optional.svtest \ + tests/extensions/include/rfc.svtest \ + tests/extensions/include/execute.svtest \ + tests/extensions/imap4flags/basic.svtest \ + tests/extensions/imap4flags/hasflag.svtest \ + tests/extensions/imap4flags/execute.svtest \ + tests/extensions/imap4flags/multiscript.svtest \ + tests/extensions/imap4flags/flagstring.svtest \ + tests/extensions/imap4flags/flagstore.svtest \ + tests/extensions/body/basic.svtest \ + tests/extensions/body/errors.svtest \ + tests/extensions/body/raw.svtest \ + tests/extensions/body/content.svtest \ + tests/extensions/body/text.svtest \ + tests/extensions/body/match-values.svtest \ + tests/extensions/regex/basic.svtest \ + tests/extensions/regex/match-values.svtest \ + tests/extensions/regex/errors.svtest \ + tests/extensions/reject/execute.svtest \ + tests/extensions/reject/smtp.svtest \ + tests/extensions/relational/basic.svtest \ + tests/extensions/relational/rfc.svtest \ + tests/extensions/relational/errors.svtest \ + tests/extensions/relational/comparators.svtest \ + tests/extensions/subaddress/basic.svtest \ + tests/extensions/subaddress/rfc.svtest \ + tests/extensions/subaddress/config.svtest \ + tests/extensions/vacation/errors.svtest \ + tests/extensions/vacation/execute.svtest \ + tests/extensions/vacation/message.svtest \ + tests/extensions/vacation/smtp.svtest \ + tests/extensions/vacation/utf-8.svtest \ + tests/extensions/vacation/reply.svtest \ + tests/extensions/enotify/basic.svtest \ + tests/extensions/enotify/encodeurl.svtest \ + tests/extensions/enotify/valid_notify_method.svtest \ + tests/extensions/enotify/notify_method_capability.svtest \ + tests/extensions/enotify/errors.svtest \ + tests/extensions/enotify/execute.svtest \ + tests/extensions/enotify/mailto.svtest \ + tests/extensions/environment/basic.svtest \ + tests/extensions/environment/rfc.svtest \ + tests/extensions/mailbox/errors.svtest \ + tests/extensions/mailbox/execute.svtest \ + tests/extensions/date/basic.svtest \ + tests/extensions/date/date-parts.svtest \ + tests/extensions/date/zones.svtest \ + tests/extensions/index/basic.svtest \ + tests/extensions/index/errors.svtest \ + tests/extensions/spamvirustest/spamtest.svtest \ + tests/extensions/spamvirustest/virustest.svtest \ + tests/extensions/spamvirustest/spamtestplus.svtest \ + tests/extensions/spamvirustest/errors.svtest \ + tests/extensions/ihave/execute.svtest \ + tests/extensions/ihave/errors.svtest \ + tests/extensions/ihave/restrictions.svtest \ + tests/extensions/editheader/addheader.svtest \ + tests/extensions/editheader/deleteheader.svtest \ + tests/extensions/editheader/alternating.svtest \ + tests/extensions/editheader/utf8.svtest \ + tests/extensions/editheader/protected.svtest \ + tests/extensions/editheader/errors.svtest \ + tests/extensions/editheader/execute.svtest \ + tests/extensions/duplicate/errors.svtest \ + tests/extensions/duplicate/execute.svtest \ + tests/extensions/duplicate/execute-vnd.svtest \ + tests/extensions/metadata/execute.svtest \ + tests/extensions/metadata/errors.svtest \ + tests/extensions/mime/errors.svtest \ + tests/extensions/mime/header.svtest \ + tests/extensions/mime/exists.svtest \ + tests/extensions/mime/address.svtest \ + tests/extensions/mime/execute.svtest \ + tests/extensions/mime/content-header.svtest \ + tests/extensions/mime/foreverypart.svtest \ + tests/extensions/mime/extracttext.svtest \ + tests/extensions/mime/calendar-example.svtest \ + tests/extensions/special-use/errors.svtest \ + tests/extensions/special-use/execute.svtest \ + tests/extensions/vnd.dovecot/debug/execute.svtest \ + tests/extensions/vnd.dovecot/environment/basic.svtest \ + tests/extensions/vnd.dovecot/environment/variables.svtest \ + tests/extensions/vnd.dovecot/report/errors.svtest \ + tests/extensions/vnd.dovecot/report/execute.svtest \ + tests/deprecated/notify/basic.svtest \ + tests/deprecated/notify/mailto.svtest \ + tests/deprecated/notify/errors.svtest \ + tests/deprecated/notify/execute.svtest \ + tests/deprecated/notify/denotify.svtest \ + tests/deprecated/imapflags/execute.svtest \ + tests/deprecated/imapflags/errors.svtest \ + $(test_unfinished) + +failure_test_cases = \ + tests/failures/fuzz1.svtest \ + tests/failures/fuzz2.svtest \ + tests/failures/fuzz3.svtest \ + tests/failures/mailbox-bad-utf8.svtest + +TEST_EXTPROGRAMS_BIN = NOCHILDREN=yes $(TEST_BIN) \ + -P src/plugins/sieve-extprograms/.libs/sieve_extprograms + +extprograms_test_cases = \ + tests/plugins/extprograms/errors.svtest \ + tests/plugins/extprograms/pipe/command.svtest \ + tests/plugins/extprograms/pipe/errors.svtest \ + tests/plugins/extprograms/pipe/execute.svtest \ + tests/plugins/extprograms/filter/command.svtest \ + tests/plugins/extprograms/filter/errors.svtest \ + tests/plugins/extprograms/filter/execute.svtest \ + tests/plugins/extprograms/execute/command.svtest \ + tests/plugins/extprograms/execute/errors.svtest \ + tests/plugins/extprograms/execute/execute.svtest + +all: dummy-config.h pigeonhole-config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +dummy-config.h: stamp-h1 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + +stamp-h1: $(srcdir)/dummy-config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status dummy-config.h +$(srcdir)/dummy-config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +pigeonhole-config.h: stamp-h2 + @test -f $@ || rm -f stamp-h2 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h2 + +stamp-h2: $(srcdir)/pigeonhole-config.h.in $(top_builddir)/config.status + @rm -f stamp-h2 + cd $(top_builddir) && $(SHELL) ./config.status pigeonhole-config.h + +distclean-hdr: + -rm -f dummy-config.h stamp-h1 pigeonhole-config.h stamp-h2 +stamp.h: $(top_builddir)/config.status $(srcdir)/stamp.h.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt +install-dist_aclocalDATA: $(dist_aclocal_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_aclocal_DATA)'; test -n "$(aclocaldir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(aclocaldir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(aclocaldir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(aclocaldir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(aclocaldir)" || exit $$?; \ + done + +uninstall-dist_aclocalDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_aclocal_DATA)'; test -n "$(aclocaldir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(aclocaldir)'; $(am__uninstall_files_from_dir) +install-dist_pkginc_libHEADERS: $(dist_pkginc_lib_HEADERS) + @$(NORMAL_INSTALL) + @list='$(dist_pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkginc_libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkginc_libdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkginc_libdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkginc_libdir)" || exit $$?; \ + done + +uninstall-dist_pkginc_libHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(dist_pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkginc_libdir)'; $(am__uninstall_files_from_dir) +install-nodist_pkginc_libHEADERS: $(nodist_pkginc_lib_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nodist_pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkginc_libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkginc_libdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkginc_libdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkginc_libdir)" || exit $$?; \ + done + +uninstall-nodist_pkginc_libHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkginc_libdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-zstd: distdir + tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + *.tar.zst*) \ + zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) $(HEADERS) dummy-config.h pigeonhole-config.h +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(aclocaldir)" "$(DESTDIR)$(pkginc_libdir)" "$(DESTDIR)$(pkginc_libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr \ + distclean-libtool distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-dist_aclocalDATA \ + install-dist_pkginc_libHEADERS \ + install-nodist_pkginc_libHEADERS + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-dist_aclocalDATA \ + uninstall-dist_pkginc_libHEADERS \ + uninstall-nodist_pkginc_libHEADERS + +.MAKE: $(am__recursive_targets) all install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--refresh check check-am clean clean-cscope clean-generic \ + clean-libtool cscope cscopelist-am ctags ctags-am dist \ + dist-all dist-bzip2 dist-gzip dist-hook dist-lzip dist-shar \ + dist-tarZ dist-xz dist-zip dist-zstd distcheck distclean \ + distclean-generic distclean-hdr distclean-libtool \ + distclean-tags distcleancheck distdir distuninstallcheck dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dist_aclocalDATA \ + install-dist_pkginc_libHEADERS install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man \ + install-nodist_pkginc_libHEADERS install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-dist_aclocalDATA \ + uninstall-dist_pkginc_libHEADERS \ + uninstall-nodist_pkginc_libHEADERS + +.PRECIOUS: Makefile + + +dist-hook: + rm -rf `find $(distdir)/tests -type f -name '*.svbin'` + +ChangeLog: + git log --name-status \ + --pretty="format:%ai %aN <%aE> (%h)%n%n%w(80,4,4)%s%n%n%b" > ChangeLog \ + || rm -f ChangeLog + +pigeonhole-version.h: noop + $(SHELL) $(top_srcdir)/update-version.sh $(top_srcdir) $(top_builddir) + +noop: + +$(test_cases): + @$(TEST_BIN) $(top_srcdir)/$@ + +$(failure_test_cases): + @$(TEST_BIN) -F $(top_srcdir)/$@ + +$(extprograms_test_cases): + @$(TEST_EXTPROGRAMS_BIN) $(top_srcdir)/$@ + +.PHONY: test test-plugins $(test_cases) $(failure_test_cases) $(extprograms_test_cases) +test: all-am $(test_cases) $(failure_test_cases) +test-plugins: all-am $(extprograms_test_cases) + +check: check-am test + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/NEWS b/pigeonhole/NEWS new file mode 100644 index 0000000..8c09177 --- /dev/null +++ b/pigeonhole/NEWS @@ -0,0 +1,1841 @@ +v0.5.21 2023-08-15 Aki Tuomi <aki.tuomi@open-xchange.com> + + - sieve: Using the deleteheader action on a message with a broken/invalid + header can cause the Sieve interpreter to crash with an assert panic. + This can happen e.g. when the message is missing the empty EOH line + between the headers and the body of the message. Fixes: + Panic: file edit-mail.c: line 820 (edit_mail_headers_parse): + assertion failed: (body_offset > 0). + - sieve: Pigeonhole added an extra Message-ID header during mail + forwarding when the existing one was invalid. Now it adds the + Message-ID only if it is entirely missing. Existing Message-ID(s) are + left unchanged. + +v0.5.20 2022-12-12 Aki Tuomi <aki.tuomi@open-xchange.com> + + * No changes - release done to keep version numbers synced. + +v0.5.19 2022-05-10 Aki Tuomi <aki.tuomi@open-xchange.com> + + * No changes - release done to keep version numbers synced. + +v0.5.18 2022-02-03 Aki Tuomi <aki.tuomi@open-xchange.com> + + - duplicate: Users without a home directory can crash with Sieve when + using duplicate database. v2.3.17 regression. + - imapsieve: When mail was expunged when processing imapsieve events, a + crash could occur. Fixes Panic: file mail-index-map.c: + line 558 (mail_index_map_lookup_seq_range): assertion failed: (first_uid > 0) + - managesieve-login: Proxy didn't support forwarding the forward_* passdb fields. + - redirect: Sieve would crash if redirect after keep-equivalent action failed. + - sieve: Interpreter crashes when the Sieve index extension is used with + index zero. + - vnd.dovecot.filter: Envelope sender string may become corrupted when + Sieve scripts are using vnd.dovecot.filter. This could end up + corrupting mbox's From line and return wrong envelope sender string in + Sieve tests. + +v0.5.17.1 2021-12-07 Aki Tuomi <aki.tuomi@open-xchange.com> + + - managesieve: Dovecot failed to start if ssl_ca was too large. + - lib-sieve-tool: Binaries failed to run if ssl_ca was too large. + +v0.5.17 2021-10-28 Aki Tuomi <aki.tuomi@open-xchange.com> + + - duplicate: The Sieve duplicate test is prone to false negatives when + the user receives many e-mails concurrently, meaning that duplicate + deliveries can still occur. + - fileinto: v2.3.16 regression: Sieve delivery crashes if mail is + delivered to non-existing and existing folder. + - imap-filter-sieve: v2.3.15 regression: The CPU limits on Sieve + execution are too easily exceeded in IMAP context (the IMAPSieve and + FILTER=SIEVE capabilities). Changed the default to unlimited CPU time + for IMAP context, since similar excessive resource usage can be caused + by other means as well. The CPU limits on Sieve scripts executed at + LDA/LMTP delivery are still enforced by default. + - redirect: The Sieve redirect action has protections against users + triggering mail loops. Unfortunately, the detection of a redirect mail + loop sometimes causes the message to get lost if no other Sieve action + is applied that delivers the message somewhere else. + - redirect: v2.3.16 regression: With certain Sieve scripts if redirect + fails due to temporary failure, the lmtp process may crash after the + delivery. Fixes: + Panic: file mail-user.c: line 229 (mail_user_deinit): + assertion failed: ((*user)->refcount == 1). + +v0.5.16 2021-08-06 Timo Sirainen <timo.sirainen@open-xchange.com> + + * .dovecot.sieve.log file now includes year in the header. + * Change Sieve script result execution to delay definitive action + execution to the end of a successful Sieve script execution session. + This is part of an effort to solve problems with the Sieve duplicate + test. As a side-effect, some rare temporary-error cases yield + different results, in which partial failure is more likely. + +v0.5.15 2021-06-21 Aki Tuomi <aki.tuomi@open-xchange.com> + + * CVE-2020-28200: Sieve interpreter is not protected against abusive + scripts that claim excessive resource usage. Fixed by limiting the + user CPU time per single script execution and cumulatively over + several script runs within a configurable timeout period. Sufficiently + large CPU time usage is summed in the Sieve script binary and execution + is blocked when the sum exceeds the limit within that time. The block + is lifted when the script is updated after the resource usage times out. + * Disconnection log messages are now more standardized across services. + They also always now start with "Disconnected" prefix. + - managesieve: Commands pipelined together with and just after the + authenticate command cause these commands to be executed twice. + +v0.5.14 2021-03-04 Aki Tuomi <aki.tuomi@open-xchange.com> + + * IMAP FILTER command: cmd-filter-sieve - Do not allow NIL as + script name argument. + +v0.5.13 2021-01-04 Aki Tuomi <aki.tuomi@open-xchange.com> + + - duplicate: The test was handled badly in a multiscript (sieve_before, + sieve_after) scenario in which an earlier script in the sequence with + a duplicate test succeeded, while a later script caused a runtime + failure. In that case, the message is recorded for duplicate tracking, + while the message may not actually have been delivered in the end. + - editheader: Sieve interpreter entered infinite loop at startup when + the "editheader" configuration listed an invalid header name. This + problem can only be triggered by the administrator. + - relational: The Sieve relational extension can cause a segfault at + compile time. This is triggered by invalid script syntax. The segfault + happens when this match type is the last argument of the test command. + This situation is not possible in a valid script; positional arguments + are normally present after that, which would prevent the segfault. + - sieve: For some Sieve commands the provided mailbox name is not + properly checked for UTF-8 validity, which can cause assert crashes at + runtime when an invalid mailbox name is encountered. This can be + caused by the user by writing a bad Sieve script involving the + affected commands ("mailboxexists", "specialuse_exists"). + This can be triggered by the remote sender only when the user has + written a Sieve script that passes message content to one of the + affected commands. + - sieve: Large sequences of 8-bit octets passed to certain Sieve + commands that create or modify message headers that allow UTF-8 text + (vacation, notify and addheader) can cause the delivery or IMAP + process (when IMAPSieve is used) to enter a memory-consuming + semi-infinite loop that ends when the process exceeds its memory + limits. Logged in users can cause these hangs only for their own + processes. + +v0.5.11 2020-08-12 Aki Tuomi <aki.tuomi@open-xchange.com> + + * managesieve: managesieve_max_line_length setting is now a "size" type + instead of just number of bytes. This allows using e.g. "64k" as the + value. + - lib-sieve: When folding white space is used in the Message-ID header, + it is not stripped away correctly before the message ID value is used, + causing e.g. garbled log lines at delivery. + +v0.5.10 2020-03-06 Aki Tuomi <aki.tuomi@open-xchange.com> + + * imap_sieve_filter: Change result action logging to include IMAP UID + - vacation: Addresses were compared case-sensitively. + +v0.5.9 2019-12-04 Aki Tuomi <aki.tuomi@open-xchange.com> + + + Added events for Sieve and ManageSieve, see + https://doc.dovecot.org/admin_manual/list_of_events/#pigeonhole + + Pigeonhole: Implement the Sieve "special-use" extension described in + RFC 8579. + - duplicate: Test only compared the handles which would cause + different values to be cached as the same duplicate test. Fix to also + compare the actual hashes. + - imap_sieve_filter: IMAP FILTER Command had various bugs in error + handling. Errors may have been duplicated for each email, errors + may have been missing entirely, command tag and ERRORS/WARNINGS + parameters were swapped. + +v0.5.8 2019-10-08 Aki Tuomi <aki.tuomi@open-xchange.com> + + - Sieve may leak resources in rare cases when a redirect, vacation or + report action fails to send the message. This mainly applies when + Sieve is executed in IMAP context; i.e., for the IMAPSIEVE or + FILTER=SIEVE capabilities. + +v0.5.7.1 2019-07-23 Timo Sirainen <timo.sirainen@open-xchange.com> + + - dsync: Sieve script syncing failed if mailbox attributes weren't + enabled. + +v0.5.7 2019-07-12 Aki Tuomi <aki.tuomi@open-xchange.com> + + + vacation: Made the subject for the automatic response message produced + by the Sieve vacation action configurable. Both the default subject + (if the script defines none) and the subject template (e.g. used to + add a subject prefix) can be configured. + - dsync: dsync-replication does not synchronize Sieve scripts. + - imap_sieve_filter: Reduce FILTER=SIEVE verbosity over IMAP connection. + - testsuite: Pigeonhole testsuite segfaulted if it was compiled with + GCC 9 + +v0.5.6 2019-04-30 Aki Tuomi <aki.tuomi@open-xchange.com> + + + sieve: Redirect loop prevention is sometimes ineffective. Improve + existing loop detection by also recognizing the + X-Sieve-Redirected-From header in incoming messages and dropping + redirect actions when it points to the sending account. This header + is already added by the redirect action, so this improvement only + adds an additional use of this header. + - sieve: Prevent execution of implicit keep upon temporary failure + occurring at runtime. + +v0.5.5 2019-03-05 Stephan Bosch <stephan@rename-it.nl> + + + IMAPSieve: Add new plugin/imapsieve_expunge_discarded setting which + causes messages discarded by an IMAPSieve script to be expunged + immediately, rather than only being marked as "\Deleted" (which is + still the default behavior). + - IMAPSieve: Fix panic crash occurring when a COPY command copies + messages from a virtual mailbox where the source messages originate + from more than a single real mailbox. + - imap4flags extension: Fix deleting all keywords. When the action + resulted in all keywords being removed, no changes were actually + applied. + - variables extension: Fix truncation of UTF-8 variable content. The + maximum size of Sieve variables was enforced by truncating the + variable string content bluntly at the limit, but this does not + consider UTF-8 code point boundaries. This resulted in broken UTF-8 + strings. This problem also surfaced for variable modifiers, such as + the ":encodeurl" modifier provided by the Sieve "enotify" extension. + In that case, the resulting URI escaping could also be truncated + inappropriately. + - IMAPSieve, IMAP FILTER=SIEVE: Fix replacing a modified message. Sieve + scripts running in IMAPSIEVE or IMAP FILTER=SIEVE context that + modify the message, stored the message a second time, rather than + replacing the originally stored unmodified message. + - Fix segmentation fault occurring when both the sieve_extprograms + plugin (for the Sieve interpreter) and the imap_filter_sieve plugin + (for IMAP) are loaded at the same time. A symbol was defined by both + plugins, causing a clash when both were loaded. + +v0.5.4 2018-11-23 Stephan Bosch <stephan@rename-it.nl> + + * Adjustments to several changes in Dovecot v2.3.4 make this Pigeonhole + release dependent on that Dovecot release; it will not compile against + older Dovecot versions. And, conversely, you need to upgrade + Pigeonhole when upgrading Dovecot to v2.3.4. + * The changes regarding the default postmaster_address in Dovecot v2.3.4 + mainly apply to Pigeonhole. The new default should work for all + existing installations, thereby fixing several reported v2.3/v0.5 + migration problems. + - IMAP FILTER=SIEVE capability: Fix assert crash occurring when running + UID FILTER on a Sieve script with errors. + +v0.5.3 2018-10-01 Stephan Bosch <stephan@rename-it.nl> + + - Fix assertion panic occurring when managesieve service fails to open + INBOX while saving a Sieve script. This was caused by a lack of + cleanup after failure. + - Fix specific messages causing an assert panic with actions that + compose a reply (e.g. vacation). With some rather weird input from the + original message, the header folding algorithm (as used for composing + the References header for the reply) got confused, causing the panic. + - IMAP FILTER=SIEVE capability: Fix FILTER SIEVE SCRIPT command parsing. + After finishing reading the Sieve script, the command parsing + sometimes didn't continue with the search arguments. This is a time- + critical bug that likely only occurs when the Sieve script is sent in + the next TCP frame. + +v0.5.2 2018-06-29 Stephan Bosch <stephan@rename-it.nl> + + + Implement plugin for the a vendor-defined IMAP capability called + "FILTER=SIEVE". It adds the ability to manually invoke Sieve filtering + in IMAP. More information can be found in + doc/plugins/imap_filter_sieve.txt. + - The Sieve addess test caused an assertion panic for invalid addresses + with UTF-8 codepoints in the localpart. Fixed by properly detecting + invalid addresses with UTF-8 codepoints in the localpart and skipping + these like other invalid addresses while iterating addresses for the + address test. + - Make the length of the subject header for the vacation response + configurable and enforce the limit in UTF-8 codepoints rather than + bytes. The subject header for a vacation response was statically + truncated to 256 bytes, which is too limited for multi-byte UTF-8 + characters. + - Sieve editheader extension: Fix assertion panic occurring when it is + used to manipulate a message header with a very large header field. + - Properly abort execution of the sieve_discard script upon error. + Before, the LDA Sieve plugin attempted to execute the sieve_discard + script when an error occurs. This can lead to the message being lost. + - Fix the interaction between quota and the sieve_discard script. When + quota was used together with a sieve_discard script, the message + delivery did not bounce when the quota was exceeded. + +v0.5.1 28-03-2018 Stephan Bosch <stephan@rename-it.nl> + + - Explicitly disallow UTF-8 in localpart in addresses parsed from Sieve + script. + - editheader extension: Corrected the stream position calculations + performed while making the modified message available as a stream. + Pigeonhole Sieve crashed in LMTP with an assertion panic when the + Sieve editheader extension was used before the message was redirected. + Experiments indicate that the problem occurred only with LMTP and that + LDA is not affected. + - fileinto extension: Fix assert panic occurring when fileinto is used + without being listed in the require line, while the copy extension is + listed there. This is a very old bug. + - imapsieve plugin: Do not assert crash or log an error for messages + that disappear concurrently while applying Sieve scripts. This event + is now logged as a debug message. + - Sieve extprograms plugin: Large output from "execute" command crashed + delivery. Fixed buffering issue in code that handles output from the + external program. + +v0.5.0.1 05-01-2018 Stephan Bosch <stephan@rename-it.nl> + + - imap4flags extension: Fix binary corruption occurring when + setflag/addflag/removeflag flag-list is a variable. + - sieve-extprograms plugin: Fix segfault occurring when used in + IMAPSieve context. + +v0.5.0 24-12-2017 Stephan Bosch <stephan@rename-it.nl> + + * editheader extension: The implementation of header modifications is + heavily updated. Although the functionality has not changed, the + underlying code was updated to address several static analysis + warnings, runtime integer arithmetic warnings (Clang), and to match + updates in the Dovecot stream API. + + variables extension: Made the maximum scope and variable size + configurable. + + subaddress: Support multiple recipient_delimiters. + - enotify extension: mailto method: Fixed parsing of mailto URI with + only a header part. + - enotify plugin: mailto method: Make sure the "From:" header is set to + a usable address and not "(null)". + - Fixed writing address headers to outgoing messages. Sometimes headers + were MIME-encoded twice, yielding invalid results. + +v0.4.23 20-03-2018 Stephan Bosch <stephan@rename-it.nl> + + - editheader extension: Corrected the stream position calculations + performed while making the modified message available as a stream. + Pigeonhole Sieve crashed in LMTP with an assertion panic when the + Sieve editheader extension was used before the message was redirected. + Experiments indicate that the problem occurred only with LMTP and that + LDA is not affected. + - fileinto extension: Fix assert panic occurring when fileinto is used + without being listed in the require line, while the copy extension is + listed there. This is a very old bug. + - imapsieve plugin: Do not log an error for messages that disappear + concurrently while applying Sieve scripts. This is a further + improvement on the imapsieve fix in the previous release (which fixed + a panic). This event is now logged as a debug message. + +v0.4.22 01-03-2018 Stephan Bosch <stephan@rename-it.nl> + + - Fixed filesystem path handling problem: sieve plugin could have + assert-crashed with specific path lengths with: "Panic: file + realpath.c: line 86 (path_normalize): assertion failed: (npath_pos + + 1 < npath + asize)". + - Sieve extprograms plugin: Large output from "execute" command crashed + delivery. Fixed buffering issue in code that handles output from the + external program. + - editheader extension: Extensively reworked the low-level + implementation of adding and removing headers. This solves a few + integer arithmetic problems reported by Clang runtime checks, but also + improves code structure and reliability in general. + - imapsieve: Fix assert crash occurring when selected messages are + expunged concurrently by the time Sieve filter is to be applied. + - imap4flags extension: Fix binary byte-code corruption occurring when + the setflag, addflag, or removeflag command's flag-list is a variable. + - enotify extension: mailto method: Fixed parsing of mailto URI with + only a header part. + - enotify extension: mailto method: Make sure "From:" header is set to a + usable address and not "(null)". + - Fixed writing address headers to outgoing messages. It sometimes + erroneously applied another layer of MIME header encoding. + +v0.4.21 12-10-2017 Stephan Bosch <stephan@rename-it.nl> + + * redirect action: Always set the X-Sieve-Redirected-From header to + sieve_user_email if configured. Before, it would use the envelope recipient + instead if available, which makes no sense if the primary e-mail address is + available. + + vacation extension: Allow ignoring the envelope sender while composing the + "To:" header for the reply. Normally, the "To:" header is composed from + the address found in the "Sender", "Resent-From" or "From" headers that is + equal to the envelope sender. If none is then found, the bare envelope + sender is used. This change adds a new setting + "sieve_vacation_to_header_ignore_envelope". With this setting enabled, the + "To:" header is always composed from those headers in the source message. + The new setting thus allows ignoring the envelope, which is useful e.g. + when SRS is used. + + vacation extension: Compose the "To:" header from the full sender address + found in the first "Sender:", "From:" or "Resent-From:" header. Before, it + would create a "To:" header without a phrase part. The new behavior is + nicer, since the reply will be addressed to the sender by name if possible. + - LDA Sieve plugin: Fixed sequential execution of LDAP-based scripts. A + missing LDAP-based script could cause the script sequence to exit earlier. + - sieve-filter: Removed the (now) duplicate utf8 to mutf7 mailbox name + conversion. This caused problems with mailbox names containing UTF-8 + characters. The Dovecot API was changed years ago, but apparently + sieve-filter was never updated. + +v0.4.20 27-08-2017 Stephan Bosch <stephan@rename-it.nl> + + + Made the retention period for redirect duplicate identifiers configurable. + For accounts that perform many redirects, the lda-dupes database could grow + to impractical sizes. Changed the default retention period from 24 to 12 + hours. + - sieve-filter: Fixed memory leak: forgot to clean up script binary at end of + execution. Normally, this would merely be an inconsequential memory leak. + However, when the script comes from an LDAP storage, this would cause io + leak warnings. + - managesieve-login: Fixed handling of AUTHENTICATE command. A second + authenticate command would be parsed wrong. This problem was caused by + changes in the previous release. + - LDA Sieve plugin: Fixed minor memory leak caused by not cleaning up the + sieve_discard script. + +v0.4.19 26-06-2017 Stephan Bosch <stephan@rename-it.nl> + + * This release adjusts Pigeonhole to several changes in the Dovecot API, + making it depend on Dovecot v2.2.31. Previous versions of Pigeonhole will + produce compile warnings with the recent Dovecot releases (but still work + ok). + - Fixed bug in handling of implicit keep in some cases. Implicit side-effects, + such as assigned flags, were not always applied correctly. This is in + essence a very old bug, but it was exposed by recent changes. + - include extension: Fixed segfault that (sometimes) occurred when the global + script location was left unconfigured. + +v0.4.18 12-04-2017 Stephan Bosch <stephan@rename-it.nl> + + + imapsieve plugin: Implemented the copy_source_after rule action. When this + is enabled for a mailbox rule, the specified Sieve script is executed for + the message in the source mailbox during a "COPY" event. This happens only + after the Sieve script that is executed for the corresponding message in the + destination mailbox finishes running successfully. + + imapsieve plugin: Added non-standard Sieve environment items for the source + and destination mailbox. + - multiscript: The execution of the discard script had an implicit "keep", + rather than an implicit "discard". + +v0.4.17 26-02-2017 Stephan Bosch <stephan@rename-it.nl> + + - LDA Sieve plugin: Fixed handling of an early explicit keep during + multiscript execution. Action side-effects and the message snapshot would be + lost at the final stage where the implicit keep is evaluated. This could + result in the IMAP flags assigned to the message to be forgotten or that + headers modified by the "editheader" extension would revert to their + original state. + - file script storage: Amended the up-to-date time stamp comparison for + on-disk binaries to include nanoseconds. This will fix problems occurring + when both binary and script are saved within the same second. This fix is + ineffective on older systems that have no support for nanoseconds in stat() + timestamps, which should be pretty rare nowadays. + - file script storage: Improve saving and listing permission error to include + more details. + - imapsieve plugin: Make sure "INBOX" is upper case in static mailbox rules. + Otherwise, the mailbox name would never match, since matching is performed + case-sensitively and Dovecot only returns the upper-cased "INBOX". + - imapsieve plugin: Fixed assert failure occurring when used with virtual + mailboxes. + - doveadm sieve plugin: Fixed crash when setting Sieve script via attribute's + string value. + +v0.4.16 30-10-2016 Stephan Bosch <stephan@rename-it.nl> + + * Part of the Sieve extprograms implementation was moved to Dovecot, which + means that this release depends on Dovecot v2.2.26+. + * ManageSieve: The PUTSCRIPT command now allows uploading empty Sieve scripts. + There was really no good reason to disallow doing that. + + Sieve vnd.dovecot.report extension: + + Added a Dovecot-Reporting-User field to the report body, which contains + the e-mail address of the user sending the report. + + Added support for configuring the "From:" address used in the report. + + LDA sieve plugin: Implemented support for a "discard script" that is run + when the message is going to be discarded. This allows doing something other + than throwing the message away for good. + + Sieve vnd.dovecot.environment extension: Added vnd.dovecot.config.* + environment items. These environment items map to sieve_env_* settings from + the plugin {} section in the configuration. Such values can of course also + be returned from userdb. + + Sieve vacation extension: Use the Microsoft X-Auto-Response-Suppress header + to prevent unwanted responses from and to (older) Microsoft products. + + ManageSieve: Added rawlog_dir setting to store ManageSieve traffic logs. + This replaces at least partially the rawlog plugin (mimics similar IMAP/POP3 + change). + - doveadm sieve plugin: synchronization: Prevent setting file timestamps to + unix epoch time. This occurred when Dovecot passed the timestamp as + 'unknown' during synchronization. + - Sieve exprograms plugin: Fixed spurious '+' sometimes returned at the end + of socket-based program output. + - imapsieve plugin: Fixed crash occurring in specific situations. + - Performed various fixes based on static analysis and Clang warnings. + +v0.4.15 07-07-2016 Stephan Bosch <stephan@rename-it.nl> + + * vacation extension: The sieve_user_email setting is now used in the check + for implicit delivery. + - imapsieve plugin: For any mail transaction, the mailbox was opened a second + time, even if no mailbox rule matched. This was unintentional, useless and + caused problems when the imapsieve plugin was used with other plugins like + acl. + - extprograms plugin: Significantly improved error handling. No stream errors + were logged. + - extprograms plugin: Fixed bug in handling of result code from remote program + (script service). + - extprograms plugin: Connection to remote program service was not retried. + - Several small fixes based on static analysis. + - Fixed handling of quoted string localparts in email addresses. + +v0.4.14 26-04-2016 Stephan Bosch <stephan@rename-it.nl> + + * The address test now allows specifying the X-Original-To header. + + Implemented the Sieve imapsieve extension and its IMAP counterpart + (RFC 6785) as a set of plugins. This allows running Sieve scripts at IMAP + activity, rather than at delivery. There are also facilities for the + familiar sieve_before/sieve_after administrator scripts. A user script is + defined for a mailbox using an IMAP METADATA entry, whereas administrator + scripts are configured using mailbox matching rules defined in the plugin + settings. + + Adjusted the Sieve ihave extension to allow capability tests to be performed + at runtime. This way, scripts can be written that work both at delivery and + from IMAP. + + Implemented support for runtime trace debugging. This means that detailed + information about which commands, actions and tests are performed is written + to a file. That file is created in the configured directory, but only if + that directory exists. This way, a particular user can be easily singled out + for debugging. This works much like the Dovecot rawlog facility. The trace + output is identical to what is produced using sieve-test with its "-t" + command line option. + + Added a "sieve_user_email" setting that configures the user's primary email + address. This is mainly useful to have a user email address available in + IMAP, where envelope data is unavailable. + + Implemented the dovecot-specific "vnd.dovecot.report" extension. This allows + sending report messages in the Message Abuse Reporting Format (RFC 5965). + - extprograms plugin: Fixed epoll() panic caused by closing the output FD + before the output stream. + - Made sure that the local part of a mail address is encoded properly using + quoted string syntax when it is not a dot-atom. + +v0.4.13 18-03-2016 Stephan Bosch <stephan@rename-it.nl> + + * redirect action: Added the list-id header to the duplicate ID for mail loop + prevention. This means that the message sent directly to the user and the + message coming through the mailing list itself are treated as different + messages by the loop detection of the redirect command, even though their + Message-ID may be identical. + * Changed the Sieve number type to uint64_t, which means that Sieve numbers + can now technically range up to 2^64. Some other Sieve implementation + allowed this, making this change necessary for successful migration. + + Implemented the sieve_implicit_extensions setting. The extensions listed in + this setting do not need to be enabled explicitly using the Sieve "require" + command. This behavior directly violates the standard, but can be necessary + for compatibility with some existing implementations of Sieve. Do not use + this setting unless you really need to! + - redirect action: Made mail loop detection more robust by forcibly adding a + Message-ID header if it is missing. + - Prevent logging a useless "script not found" error message for LDAP scripts + for which the entry exists but no attribute containing a script. This is not + necessarily an error. + - extprograms plugin: Changed the communication channel between parent and + child process for a directly forked program from a socketpair to a double + pipe. Linux does not support /dev/stdin, /dev/stdout and friends for + sockets. For some shell program authors this may be confusing, so that is + why it is changed. When using the script service, these device nodes are + still not usable though. + +v0.4.12 06-02-2016 Stephan Bosch <stephan@rename-it.nl> + + + Implemented the Sieve extracttext extension (RFC 5703; Section 7). It is now + possible to extract body text from a message into a variable. + * Increased ABI version due to changes in the Sieve interpreter's object + definitions. + - multiscript: Fixed bug in handling of (implicit) keep; final keep action was + always executed as though there was a failure. This caused the keep action + to revert back to the initial message, causing editheader actions to be + ignored. + - managesieve-login: Fixed proxy to allow SASL mechanisms other than PLAIN. + Before, the proxy would fail if the server did not support the PLAIN + mechanism. + - ldap storage: Prevent segfault occurring when assigning certain (global) + configuration options. + +v0.4.11 08-01-2016 Stephan Bosch <stephan@rename-it.nl> + + - Sieve mime extension: Fixed the header :mime :anychild test to work properly + outside a foreverypart loop. + - Several fixes in message body part handling: + - Fixed assert failure occurring when text extraction is attempted on a + empty or broken text part. + - Fixed assert failure in handling of body parts that are converted to text. + - Fixed header unfolding for (mime) headers parsed from any mime part. + - Fixed trimming for (mime) headers parsed from any mime part. + - Fixed erroneous changes to the message part tree structure performed when + re-parsing the message. + - LDA Sieve plugin: Fixed logging of actions; sometimes the configured log + format was not followed. + - LDA Sieve plugin: Fixed bug in error handling of script storage + initialization. + - Sieve Extprograms plugin: Ignored ENOTCONN error in shutdown(fd, SHUT_WR) + call. + - Fixed duplication of discard actions in the script result. Each discard was + counted as a separate action, which means that action limit would be crossed + too early. + - Made sure that quota errors never get logged as errors in syslog. + - Fixed handling of implicit keep for a partially executed transaction that + yielded a temporary failure. + - Fixed handling of global errors. If master and user error handler were + identical, in some cases the log message could be lost. + - Fixed AIX compile issue in message body parser. + +v0.4.10 13-12-2015 Stephan Bosch <stephan@rename-it.nl> + + + Implemented the Sieve mime and foreverypart extensions (RFC 5703). These + are fully implemented. The interaction with the editheader extension needs + some work, but this should not influence most uses; i.e., changes by the + editheader extension are not always visible using foreverypart/mime. + + Sieve body extension: Properly implemented the `:text' body transform. It + now extracts text for HTML message parts. + + Sieve enotify extension: mailto method: Implemented the + sieve_notify_mailto_envelope_from setting. This allows configuring the + source of the notification sender address for e-mail notifications. This is + similar to what already can be configured for redirect. + + Added a sieve_enabled (defaults to 'yes') setting that allows explicitly + disabling Sieve processing for particular users. This used to be possible by + setting `sieve=', but ever since the sieve_before, sieve_after and + sieve_default settings were added, this method was not reliable anymore. + - variables extension: Fixed handling of empty string by the `:length' set + modifier. An empty string yielded an empty string rather than "0". + - Fixed memory leak in the Sieve script byte code dumping facility. Extension + contexts were never actually freed. + - Fixed handling of implicit keep when the last Sieve script is a global one. + In that case the implicit keep action was executed in global context, which + could mean that trivial (quota) errors ended up in the system log file, + rather than the user log file. + - doveadm sieve plugin: Fixed crashes caused by incorrect context allocation + in the sieve command implementations. + +v0.4.9 04-10-2015 Stephan Bosch <stephan@rename-it.nl> + + * Properly implemented checking of ABI version for Sieve interpreter plugins, + much like Dovecot itself does for plugins. This will prevent plugin ABI + mismatches. + + Implemented a vnd.dovecot.environment extension. This builds upon the + standard environment extension and adds a few more environment items, such + as username and default mailbox. It also creates a variables namespace so + that environment items can be accessed directly. I am still thinking about + more environment items that can be added. + + Sieve extprograms plugin: Made line endings of the input passed to the + external programs configurable. This can be configured separately for each + of the three extensions. + + ManageSieve: Implemented proxy XCLIENT support. This allows the proxy to + pass client information to the back-end. + - ManageSieve: Fixed an assert failure occurring when a client disconnects + during the GETSCRIPT command. + - doveadm sieve plugin: Fixed incorrect initialization of mail user. This + caused a few memory leaks. + - sieve-filter command line tool: Fixed handling of failure-related implicit + keep when there is an explicit default destination folder. This caused + message duplication. + - lib-sieve: Fixed bug in RFC5322 header folding. Words longer than the + optimal line length caused empty lines in the output, which would break the + resulting message header. This surfaced in References: headers with very + long message IDs. + +v0.4.8 15-05-2015 Stephan Bosch <stephan@rename-it.nl> + + * LDA Sieve plugin: Dovecot changed the deliver_log_format setting to include + %{delivery_time}. This prompted changes in Pigeonhole that make this release + dependent on Dovecot v2.2.17. + + Implemented magic to make sieve_default script visible from ManageSieve + under a configurable name. This way, users can see the default rules, edit + them and store a private adjusted version. This could also be achieved by + copying the default script into the user's script storage, but updates to + the global sieve_default script would be ignored that way. + + ManageSieve: Implemented support for reporting command statistics at + disconnect. Statistics include the number of bytes and scripts uploaded/ + downloaded/checked and the number of scripts deleted/renamed. + - Fixed problem in address test: erroneously decoded mime-encoded words in + address headers. + - extprograms plugin: Fixed failure occurring when connecting to script + service without the need to read back the output from the external program. + - Fixed bug in script storage path normalization occurring with relative + symbolic links below root. + - Fixed and updated various parts of the documentation + - ManageSieve: Used "managesieve" rather than "sieve" as login service name, + which means that all managesieve-specific settings where ignored. + - Managesieve: Storage quota was not always enforced properly for scripts + uploaded as quoted string. Nobody uses that, but it is allowed in the + specification and we support it, so it should work properly. + +v0.4.7 19-03-2015 Stephan Bosch <stephan@rename-it.nl> + + * editheader extension: Made protection against addition and deletion of + headers configurable separately. Also, the `Received' and `Auto-Submitted' + headers are no longer protected against addition by default. + * Turned message envelope address parse errors into warnings. + * The interpreter now accepts non-standard domain names, e.g. containing '_'. + + Implemented the Sieve index extension (RFC 5260). + + Implemented support for the mboxmetadata and servermetadata extensions + (RFC 5490). + + Implemented new sieve commands for the doveadm command line utility. These + commands are currently limited to ManageSieve operations, but the other + current sieve tools will be migrated to doveadm in the near future as well. + + Added more debug output about binary up-to-date checking. + + Added script metadata to binary dump output. + - Fixed Sieve script binary up-to-date checking by normalizing the script + location. + - The Sieve interpreter now flushes the duplicate database during start phase + of result execution rather than commit phase. This makes sure locks on the + duplicate database are released as soon as possible, preventing contention. + - Performed a few optimizations in the lexical scanner of the language. + - Fixed bug in `:matches' match-type that made a pattern without + wildcards match as if there were a '*' at the beginning. + - Fixed crash in validation of the string parameter of the comparator tag. + - extprograms extension: Made sure supplemental group privileges are also + dropped. This was a problem reported by Debian lintian. + - Fixed bug in handling of binary errors for action side-effects and message + overrides. + - file script storage: Restructured storage initialization to address + backwards compatibility issues. + - dict script storage: Fixed small memory allocation bug. + +v0.4.6 02-11-2014 Stephan Bosch <stephan@rename-it.nl> + + - After make distclean the distributed tarball would fail to recompile. + This causes problems for some distribution builds. + +v0.4.5 30-10-2014 Stephan Bosch <stephan@rename-it.nl> + + + Added a Pigeonhole version banner to doveconf output. This way, future + bug reports will also include Pigeonhole version information. + - Fixed handling of implicit keep. Last version erroneously reported that + implicit keep succeeded after an earlier failure, while it in fact had + failed. Particularly occurred for mailbox quota errors. + - Fixed segfault occurring on SunOS systems when there is no active script. + +v0.4.4 28-10-2014 Stephan Bosch <stephan@rename-it.nl> + + * Added support for Japanese mail addresses with dots at non-standard places + in localpart. + * Changed handling of ENOSPACE into a normal temporary failure and added + handling of ENOQUOTA as a user error. + * Restructured result execution, so that all actions which involve mail + storage are always committed before all others. + + Implemented support for generic Sieve storages. Using alternative storages + now also possible for sieve_before/sieve_after. + + Implemented storage driver for retrieving Sieve scripts from LDAP. This + currently cannot be used with ManageSieve. + + Implemented sieve_redirect_envelope_from setting, which allows configuring + the envelope sender of redirected messages. + - Fixed handling of mail storage errors occurring while evaluating the input + message. + - managesieve-login: + - Removed bogus ALERT response code returned for AUTHENTICATE command. + - Fixed handling of invalid initial response argument to AUTHENTICATE + command. + - Fixed handling of stream errors in lexical scanner. + - Fixed handling of SMTP errors. Permanent and temporary errors were mixed up. + - Fixed several problems reported by CLang 3.4. + - duplicate extension: Fixed erroneous compile error about conflicting tags + when `:handle' argument was used last. + - relational extension: Fixed error handling of `:value' match. + - editheader extension: Fixed header unfolding and header iteration. + - mailbox extension: Fixed the `:create' tag, which erroneously subscribed an + existing folder. + - extprograms plugin: Fixed handling of error codes. + - doveadm-sieve plugin: Fixed several bugs. Synchronization of symbolic link + in the file storage should now also work properly. + +v0.4.3 12-05-2014 Stephan Bosch <stephan@rename-it.nl> + + * Editheader extension: Made control characters allowed for editheader, except + NUL. Before, this would cause a runtime error. + + Upgraded Dovecot-specific Sieve "vnd.dovecot.duplicate" extension to match + the new draft "duplicate" extension. + - Fixed sieve_result_global_log_error to log only as i_info in administrator + log (syslog) if executed from multiscript context. + - Sieve redirect extension: Adjusted loop detection to show leniency to resent + messages. + - Sieve include extension: Fixed problem with handling of duplicate includes + with different parameters :once or :optional. + - Sieve spamtest/virustest extensions: Tests were erroneously performed + against the original message. When used together with extprograms filter to + add the spam headers, the changes were not being used by the spamtest and + virustest extensions. + - Deprecated Sieve notify extension: Fixed segfault problems in message string + substitution. + - ManageSieve: Fixed active link verification to handle redundant path slashes + correctly. + - Sieve vacation extension: + - Fixed interaction of sieve_vacation_dont_check_recipient with + sieve_vacation_send_from_recipient setting. + - Fixed log message for discarded response. + - Sieve extprograms plugin: + - Forgot to disable the alarm() timeouts set for script execution. + - Fixed fd leak and handling of output shutdown. + - Fixed 'Bad filedescriptor' error occurring when disconnecting script + client. + - Made sure that programs are never forked with root privileges. + +v0.4.2 26-09-2013 Stephan Bosch <stephan@rename-it.nl> + + * Incompatible change in Sieve doveadm plugin: the root attribute for + Sieve scripts is changed. Make sure that you update both sides of a dsync + setup simultaneously when Sieve is involved, otherwise synchronization will + likely fail. + + Added support for sending Sieve vacation replies with an actual sender, + rather than the default <> sender. Check the updated + doc/extensions/vacation.txt for more information. + - Fixed a binary code read problem in the `set' command of the Sieve variables + extension. Using the set command with a modifier and an empty string value + would cause code corruption problems while running the script. + - Various fixes for doveadm-sieve plugin, mostly crashes. These include a fix + for the `Invalid value for default sieve attribute' problem. + - Various fixes for compiler and static analyzer warnings, e.g. as reported + by CLang and on 32 bit systems. + - Fixed the implementation of the new :options flag for the Sieve include + extension. + - Fixed potential segfault bug at deinitialization of the lda-sieve plugin. + - Fixed messed up hex output for sieve-dump tool. + +v0.4.1 03-06-2013 Stephan Bosch <stephan@rename-it.nl> + + + Added support for handling temporary failures. These are passed back to + LDA/LTMP to produce an appropriate response towards the MTA. + - Sieve storage: Removed PATH_MAX limitation for active symlink. This caused + problems for GNU/Hurd. + - Fixed line endings in X-Sieve headers added by redirect command. + - ManageSieve: Fixed '[' ']' stupidity for response codes (only happened + before login). + - Fixed setting name in example-config/conf.d/20-managesieve.conf. + - Sieve extprograms plugin: Fixed interaction between pipe command and remote + script service. The output from the script service was never read, causing a + broken pipe error at the script service. Apparently, this was broken since + the I/O handling for extprograms was last revised. + - Fixed assertion failure due to datastack problem in message header + composition. + +v0.4.0 09-05-2013 Stephan Bosch <stephan@rename-it.nl> + + + Added doveadm-sieve plugin that provides the possibility to synch Sieve + scripts using doveadm sync along with the user's mailboxes. + + Added the Sieve extprograms plugin to the main Pigeonhole package. It is + still a plugin, but it is now included so that a separate compile is no + longer necessary and distributors are likely to include it. The extprograms + plugin provides Sieve language extensions that allows executing + (administrator-controlled) external programs for message delivery, + message filtering and string manipulation. Refer to + doc/plugins/sieve_extprograms.txt for more information. + + Added debug message showing Pigeonhole version at initialization. Makes it + very clear that the plugin is properly loaded. + + Finished implementation of the Sieve include extension. It should now + fully conform to RFC 6609. The main addition is the new :optional tag which + makes the include command ignore missing included scripts without an error. + + Finished implementation of the Sieve environment extension as much as + possible. Environment items "location", "phase" and "domain" now also + return a usable value. + +v0.3.6 26-09-2013 Stephan Bosch <stephan@rename-it.nl> + + - Fixed a binary code read problem in the `set' command of the Sieve variables + extension. Using the set command with a modifier and an empty string value + would cause code corruption problems while running the script. + - Various fixes for compiler and static analyzer warnings, as reported + by CLang. + - ManageSieve: Fixed '[' ']' stupidity for response codes (only happened + before login). + - Fixed setting name in example-config/conf.d/20-managesieve.conf. + - Fixed messed up hex output for sieve-dump tool. + +v0.3.5 09-05-2013 Stephan Bosch <stephan@rename-it.nl> + + - Sieve editheader extension: fixed interaction with the Sieve body extension. + If used together, the deleteheader action could fail after a body test was + performed. + - Test suite: fixed a time zone dependency in the Sieve date extension tests. + +v0.3.4 06-04-2013 Stephan Bosch <stephan@rename-it.nl> + + * Changed error handling to be less of a nuisance for administrators. Strictly + user-caused errors are only reported in user log. Some errors are logged as + info instead. + * Sieve: Changed behavior of redirect in case of a duplicate message delivery + or a mail loop. If a duplicate is detected the implicit keep is canceled, + as though the redirect was successful. This prevents getting local + deliveries. The original SMTP recipient is used when it is available to + augment the entry in the LDA duplicate database. This way, duplicates are + only detected when (initially) addressed to the same recipient. + + Sieve vnd.dovecot.duplicate extension: added new features to the duplicate + test, making it possible to manually compose the key value for duplicate + checking. This extension is in the process of being standardized + (https://tools.ietf.org/html/draft-bosch-sieve-duplicate-01). + + Sieve date extension: generate warning when invalid date part is specified. + - Sieve editheader extension: fixed crash occurring when addheader :last was + used. + - Sieve include extension: fixed missing error cleanup that caused a resource + leak. + - Sieve vacation extension: fixed determination of From: address for when + sieve_vacation_dont_check_recipient is active. + - Sieve tools: the -D option wasn't enabled and documented for all tools. + - Siev dict script storage: fixed potential segfault occurring when dict + initialization fails. + - ManageSieve: fixed bug in skipping of CRLF at end of AUTHENTICATE command. + - ManageSieve: fixed handling of unkown commands pre-login. + - Fixed compile on Mageia Linux. + +v0.3.3 18-09-2012 Stephan Bosch <stephan@rename-it.nl> + + - Fixed compile against installed Dovecot headers. This was broken by the + ld.gold fix in the previous release. + +v0.3.2 18-09-2012 Stephan Bosch <stephan@rename-it.nl> + + + sieve-refilter tool: improved man page documentation by explicitly + specifying the syntax used for mailbox arguments. + + Sieve: spamtest and virustest extensions: improved trace debugging of score + calculation. + + Sieve: made error messages about exceeding the maximum number of actions + more verbose. + - Sieve tools: fixed problems with running as root: sievec and sieve-dump now + ignore mail_uid and mail_gid settings when run as root. + - Sieve: fixed bug in action accounting (for limit checking): increase action + instance count only when an action is actually created. + - Sieve: include extension: fixed namespace separation of :global and + :personal scripts. + - ManageSieve: fixed segfault bug triggered by CHECKSCRIPT command. + - Fixed linking with ld.gold. + - Fixed several Clang compile warnings and a few potential bugs. + +v0.3.1 25-05-2012 Stephan Bosch <stephan@rename-it.nl> + + * Added support for retrieving Sieve scripts from dict lookup. This means that + Sieve scripts can now be downloaded from a database. Compiled script + binaries are still put on disk somewhere if used. The INSTALL documentation + is updated with information on this new feature and the + (backwards-compatible) changes to the configuration. Note that his feature + is currently not supported for sieve_before/sieve_after or script management + through ManageSieve. + + Incorporated the sieve_duplicate plugin into main Pigeonhole tree as a + normal extension (vnd.dovecot.duplicate). This Dovecot-specific extension + adds the ability to check for duplicate deliveries based on message ID. + Specification can be found in: doc/rfc/spec-bosch-sieve-duplicate.txt + + Added support for specifying multiple sieve_before and sieve_after paths. + This adds much more flexibility to the multiscript configuration. One + application is to have user-specific Sieve scripts outside the user's + normal control through ManageSieve. + + Added a "session ID" string for managesieve connections, available in + %{session} variable (analogous to Dovecot change). + - Fixed several small issues, including a few potential segfault bugs, based + on static source code analysis. + - ManageSieve: changed use of EPROTO error to EIO in ManageSieve string stream + implementation because it is apparently not known in BSD. + - Gave stamp.h.in (needed for autotools) some content to prevent it from + disappearing in patch files. + - Fixed bug that caused a SunStudio CC compile failure (reported by Piotr + Tarnowski). + +v0.3.0 16-02-2012 Stephan Bosch <stephan@rename-it.nl> + + * Renamed sieve_global_path setting to sieve_default for clarity. Old name is + still recognized for backwards compatibility. Support for the ancient (pre + v1.1) name for this setting "global_script_path" is now dropped. + * Added means to prohibit use of redirect action. Setting sieve_max_redirects + to 0 now means that redirect is disallowed instead of unlimited. Default + value remains four. + * Fixed interaction of Sieve include extension with ManageSieve. It is updated + to match new requirements in the draft include specification. Missing + included scripts are no longer an error at upload time. + * Updated RFC2822 header field body verification to exclude non-printing + characters (RFC5322). Only Sieve actions that can create unstructured header + values (currently enotify/mailto and editheader) are affected by this + change. + + Completed sieve-filter tool to a useful state. The sieve-filter tool + provides a means to (re)filter messages in a mailbox through a Sieve script. + + Implemented the Sieve editheader extension. It is now possible to add and + remove message headers from within Sieve. + + ManageSieve: added support for reading quoted and literal strings as a + stream. Fixes support for handing large SASL responses (analogous to similar + changes in Dovecot). It is now also allowed to use a quoted string for the + PUTSCRIPT script argument. + + Added code to cleanup tmp directory in Sieve storage directory (sieve_dir) + every once in a while. + + Added support for substituting the entire message during Sieve processing. + This is used for the filter action provided by the new sieve_extprograms + plugin (provided separately for now). The filter action allows passing the + message through an external program. + + Added support for restricting certain Sieve language extensions to + (admin-controled) global scripts. Restricted extensions can be configured + using the new sieve_global_extensions setting. This is particularly useful + for some of the Dovecot-specific (plugin-based) Sieve extensions, that can + be somewhat hazardous when under direct control of users (e.g. + sieve_extprograms). + +v0.2.6 13-02-2012 Stephan Bosch <stephan@rename-it.nl> + + * This release fixes unintentional behavior of the include extension. Included + scriptnames with a name like "name.sieve" would implicitly map to a script + file called "name.sieve" and not "name.sieve.sieve". Keep in mind that the + .sieve file extension has no meaning from within the Sieve language. A Sieve + script is always stored with an appended .sieve file extension, also when + the name already ends with a .sieve suffix. + IMPORTANT: Some installations have relied on this unintentional feature, so + check your script includes for issues before upgrading. + * Matched changes regarding auth_verbose setting in Dovecot. This means that + this release will only compile against Dovecot v2.0.18. + - Fixed problem in ManageSieve that caused it to omit a WARNINGS response code + when the uploaded script compiled with warnings. + - Made sure that locations of Sieve error never report `line 0'. + - Fixed potential segfault occurring when interpreter initialization fails. + +v0.2.5 19-11-2011 Stephan Bosch <stephan@rename-it.nl> + + + Sieve vacation extension: made discard message for implicit delivery more + verbose + - The sieve-test tool: mixed up original and final envelope recipient in + implementation of command line arguments. + - Sieve vacation extension: resolved FIXME regarding the use of variables in + the :handle argument. Variables are now handled correctly. + - Sieve body extension: fixed handling of :content "message/rfc822". This now + yields the headers of the embedded message as required by the specification. + Handling of :content "multipart" remains to be fixed. + - LDA Sieve plugin: fixed problem with recipient_delimiter configuration. Now + falls back to global recipient_delimiter setting if + plugin/recipient_delimiter is not set. + +v0.2.4 13-09-2011 Stephan Bosch <stephan@rename-it.nl> + + + Vacation extension: finally added support for using the original recipient + in vacation address check. It is also possible to disable the recipient + address check entirely. Check doc/vacation.txt for configuration + information. + + Include extension: made limits on the include depth and the total number of + included scripts configurable. Check doc/include.txt for configuration + information. + + Implemented ihave extension. This allows checking for the availability + of Sieve language extensions at 'runtime'. Actually, this is checked + at compile time. At runtime the interpreter checks whether extensions + that were not previously available are still unavailable. If the situation + changed, the script is re-compiled and the ihave tests are evaluated again. + + Sieve: optimized compilation of tests that yield constant results (i.e. + known at compile tme), such as 'true' and 'false'. No code is produced + anymore for script sections that are never executed. Also, semantics + are not verified anymore in uncompiled script sections. + + Made vnd.dovecot.debug extension available to the LDA plugin instead of + only the command line tools. + + Sieve: redirect action now adds X-Sieve-Redirected-From header (mainly for + people using SPF/SRS). + - Sieve: fixed bug in handling flags and keywords; in case of error an + assertion was triggered. + - Script storage: improved handling of unconfigured user home directory. + Originally this would produce an unhelpful error message. + - Imap4flags extension: prevent forcibly enabling imap4flags when imapflags + is enabled. + - Fixed various -Wunused-but-set-variable compiler warnings. + - Include extension: forgot to check variable identifier syntax for 'global' + command. + - Sieve: fixed debug mode; no messages were logged in some situations. + - sievec tool: forgot to enable -D (debug) parameter. + +v0.2.3 14-04-2011 Stephan Bosch <stephan@rename-it.nl> + + * Sieve filter tool: finished implementing basic functionality. It is not + quite ready yet, but it is available for those willing to experiment + with it (needs --with-unfinished-features config to compile). Also + includes man page. + + Vacation extension now inhibits replies to messages from sender listed + in :addresses, thus preventing replies to one of the user's other known + addresses. + + Vacation extension: implemented the (draft) vacation-seconds extension. + This also adds min/max period configuration settings. Refer to + doc/vacation.txt for configuration information. + - ManageSieve: fixed bug in UTF-8 checking of string values. This is done + by discarding the original implementation and migrating to the Dovecot + API's UTF-8 functionality. + - Sieve command line tools now avoid initializing the mail store unless + necessary. This prevents sievec and sieve-dump from failing when + executed by root for example. + - Enotify extension: fixed inappropriate return type in mailto URI parse + function, also fixing ARM compiler warning. + - Vacation extension: fixed handling of sendmail errors. It produced an + additional confusing success message in case of error. + - Removed header MIME-decoding to fix erroneous address parsing. Applies to + address test and vacation command. + - Fixed segfault bug in extension configuration, triggered when unknown + extension is mentioned in sieve_extensions setting. + +v0.2.2 06-12-2010 Stephan Bosch <stephan@rename-it.nl> + + * LDA Sieve plugin: started using Dovecot LDA reject API for the reject + extension. This means that the LDA reject_reason and reject_subject + settings now also work for Pigeonhole's LDA Sieve plugin. + * Did some work on the new sieve-filter tool. It is mostly functional, but + it is not finished yet. + * Dovecot change: services' default vsz_limits weren't being enforced + correctly in earlier v2.0 releases. Now that they are enforced, you might + notice that the default limits are too low and you need to increase them. + This problem will show up in logs as "out of memory" errors. See + default_vsz_limit and service { vsz_limit } settings. + - Imap4flags: fixed segfault bug occurring in multiscript context. + - Added version checking to the ManageSieve settings plugin. This plugin was + forgotten when the LDA plugin was updated with this change in the previous + release. + - LDA Sieve plugin: fixed memory leak at deinitialization. + +v0.2.1 27-09-2010 Stephan Bosch <stephan@rename-it.nl> + + + Incorporated distinction between original and final envelope recipient in + Sieve interpreter, as recently introduced in Dovecot. + + Regex extension: added support for regex keys composed from variables. + - LDA Sieve plugin: added _version symbol to enable Dovecot's plugin version + check. Without this check, people can forget to recompile the plugin, which + can lead to unexpected effects. + - LDA Sieve plugin: turned debug message about an unconfigured home directory + into a proper error and added script path information. + - Fixed unnecessary reporting of dummy extensions in ManageSieve SIEVE + capability; the comparator-i;octet and comparator-i;ascii-numeric + 'extensions' were reported explicitly. + +v0.2.0 10-09-2010 Stephan Bosch <stephan@rename-it.nl> + + * Merged Sieve and ManageSieve packages into a single Pigeonhole package. + There is also no need to patch Dovecot anymore to gain ManageSieve support. + Version numbering of previous Sieve releases is continued as v0.2.0. The + sources originally branched off from Sieve v0.1.5 and ManageSieve v0.11.4, + but the NEWS history of much more recent releases for Dovecot v1.2 is + included since these changes are all included in this release as well. + * The ManageSieve service now binds to TCP port 4190 by default due to the + IANA port assignment for the ManageSieve service. When upgrading from v1.2, + this should be taken into account. The service can be configured manually to + listen on both 2000 and 4190. + * The Dovecot configuration now calls the ManageSieve protocol 'sieve' in + stead of 'managesieve' because it is registered as such with IANA. The + binaries and the services are still called managesieve and + managesieve-login. + * The binary representation of a compiled Sieve script is updated to include + source code locations of all commands and arguments. This is implemented in + a similar manner as such debug information is included in some system + executables and libraries (DWARF-like). Run-time errors can now always refer + to the proper line number in the Sieve source script. + * The Sieve plugin is adapted to work properly with the new LMTP service + introduced with Dovecot v2.0. The same plugin is used for both LDA and LMTP. + * The 'sieve_subaddress_sep' setting for the Sieve subaddress extension is now + known as 'recipient_delimiter'. Although the deprecated sieve_subaddress_sep + setting is still recognized for backwards compatibility, it is recommended + to update the setting to the new name, since the new LMTP service also uses + the recipient_delimiter setting. + * ManageSieve: changed default IMPLEMENTATION capability to from 'Dovecot' to + 'Dovecot Pigeonhole'. + * Renamed the sieved tool to sieve-dump. The original name was somewhat + confusing. + * Updated man pages to match style and structure of new Dovecot man pages. + * Made testsuite commands more uniform and cleaned up many of the testsuite + scripts. Some minor new tests were added in the process. + + Simplified string matching API to use abstract string lists as data sources. + This will also make implementing the index extension easier in the future. + + Significantly improved trace debugging with the sieve-test tool. The full + execution of the script can be examined, including the matched values and + keys of the respective Sieve test commands. The executed statements are + listed with their line number (and code address when requested). The level + of detail is configurable from the command line. + + The SIEVE and NOTIFY capabilities reported by the ManageSieve protocol can + now be configured manually. If left unconfigured, the capabilities are + determined from the default Sieve and ManageSieve configuration. + User-specific capabilities aren't reported until after authentication. + + Significantly improved file error handling. This means that administrators + get a more useful and informative log message when file operations fail. The + most notable example is that when the LDA Sieve plugin is trying to store a + binary for a global script, the resulting failure message also points the + administrator towards pre-compiling the script with sievec. + + Added runtime argument value checking for several commands (redirect, date + vacation). When variables are used, these checks cannot be performed at + compiletime. A proper runtime error now is produced when invalid data is + encountered. + + UTF8 validity of fileinto command argument is now checked either at compile + time or at runtime. Previously, it was not checked until the store action + was executed. + + Validity of IMAP flags for the imap4flags extension is now checked also + at runtime. Previously, it was not checked until the store action was + executed. + + Simplified and restructured error handling. Also made sure that user-caused + errors are no longer written to the Dovecot master/LDA log. + - Multiscript: fixed duplicate implicit keep caused by erroneous execution + state update. + - Prevented assertion failure due to currupt binary string representation. + If the string was missing a final \0 character an assertion was produced in + stead of a binary corruption error. + - Imap4flags: fixed bug in setflag command; when parameter was a stringlist, + only the last item was actually set. + - Variables extension: fixed :length set modifier to recognize utf8 characters + instead of octets. + - Testsuite: prevented innocent warning messages, i.e. those that are part of + the test, from showing up by default. + - ManageSieve/Sieve storage: fixed error handling of PUTSCRIPT commmand; save + commit errors would not make the command fail. + - ManageSieve: enforced protocol syntax better with some of the commands; some + commands allowed spurious extra arguments. + - Fixed Sieve script name checking to properly handle length limit and added + 0x00ff as invalid character. + - Removed spurious old stdio.h (top) includes; these caused compile issues on + specific systems. + - Fixed default Sieve capability (as reported by ManageSieve): extra + extensions spamtest, spamtestplus and virustest were enabled by default. + These should, however, only be enabled when properly configured and there + is no default configuration. + +(Fused Dovecot Sieve and ManageSieve packages into a single Pigeonhole release) + +Dovecot Sieve NEWS history: +--------------------------- + +Dovecot 1.2: + +v0.1.17 19-06-2010 Stephan Bosch <stephan@rename-it.nl> + + - Made sure source code positions for compiler messages are recorded at start + of tokens. + - Fixed a few potential memory leaks in the Sieve compiler and the + spam/virustest extensions. + - Made command line tools return proper exit status upon failure. + +v0.1.16 30-04-2010 Stephan Bosch <stephan@rename-it.nl> + + * Finished implementation of spamtest, spamtestplus and virustest extensions. + These are not enabled by default and need to be activated with the + sieve_extensions setting. Documentation available in + doc/spamtest-virustest.txt + + Vacation extension: the from address of the generated reply is now by + default equal to whatever known recipient alias matched the headers of the + message. If it is one of the aliases specified with :addresses, it is used + instead of the envelope recipient address that was used before. + + Restructured and optimized the lexical scanner. + + Added --with-docs configure option to allow disabling installation of + documentation. + - Accidentally omitted 'extern' in two declarations of global variables in + header files, causing compile failures on certain systems. + - Deprecated imapflags extension: fixed implicit assignment of flags. Turns + out this never really worked, but the effect of this bug was obscured by the + removeflag bug fixed in the previous release. + - Fixed various memset argument mixups in enotify extension. This caused + warnings on certain systems, but luckily no adverse effects at runtime. + +v0.1.15 25-01-2010 Stephan Bosch <stephan@rename-it.nl> + + * Enotify extension: + - Adjusted notify method API for addition of new notification methods. + - Set default importance level to 'normal' (was 'high'). + * Include extension: updated implementation towards most recent specification + (all should be backwards compatible): + - Implemented global variables namespace. + - Global command may now appear anywhere in a script. + - Implemented script name checking using the requirements specified in the + ManageSieve draft. + - One issue remains: ManageSieve currently requires included scripts to be + uploaded first, which is not according to specification. + * Changed envelope path parser to allow to and from envelope addresses that + have no domain part. + + Added preliminary support for Sieve plugins and added support for installing + Sieve development headers. + + Started work on the implementation of the spamtest, spamtestplus and + virustest extensions (unfinished). + + Deprecated notify extension: implemented denotify command. + + Variables extension: added support for variable namespaces. + + Added configurable script size limit. Compiler will refuse to compile files + larger than sieve_max_script_size. + + Testsuite changes: + - Added support for changing and testing an extension's configuration. + - Added a command line parameter for copying errors to stderr. + - Fixed a bug in the i;ascii-numeric comparator. If one of the strings started + with a non-digit character, the comparator would always yield less-than. + - Imap4flags extension: fixed bug in removeflag: removing a single flag failed + due to off-by-one error (bug report by Julian Cowley). + - Improved EACCES error messages for stat() and lstat() syscalls and slightly + improved error messages that may uccur when saving a binary. + - Vacation extension: fixed typo in runtime log message (patch by Julian + Cowley). + - Fixed use of minus '-' in man pages; it is now properly escaped. + - Fixed parser recovery. In particular cases it would trigger spurious errors + after an initial valid error and sometimes additional errors were + inappropriately ignored. + +v0.1.14 19-12-2009 Stephan Bosch <stephan@rename-it.nl> + + * Made the imposed limits on the number of redirects and the number of + actions configurable. The settings are called sieve_max_actions and + sieve_max_redirects. + * Did a major rework of extension handling, making sure that no global state + is maintained. This change was triggered by problems that global state info + would cause for Dovecot v2.0, but it is also important for v1.2 as it + significantly cleans up the library implementation. + + Made LDA Sieve plugin recognize the deliver_log_format setting. + + Message headers produced from user-supplied data are now RFC2047-encoded if + necessary for outgoing messages. This is for example important for the + :subject argument of the vacation action. + + Added support for the $text$ substitution in the deprecated notify + extension. + + The subaddress extension now also accepts recipient_delimiter setting as an + alias for sieve_subaddress_sep setting. This anticipates the + recipient_delimiter setting in v2.0. + - Fixed logging of mailbox names. It logged the converted mUTF7 version in + stead of the original UTF8 version supplied by the user. + - Fixed a minor memory leak in the multiscript support. + - Fixed a bug in the recompilation of Sieve scripts. Made sure that scripts + are only recompiled when the script file - or the symlink pointing to it - + is strictly newer. + +v0.1.13 18-10-2009 Stephan Bosch <stephan@rename-it.nl> + + + Body extension: implemented proper handling of the :raw transform and added + various new tests to the test suite. However, :content "multipart" and + :content "message/rfc822" are still not working. + + Fixed race condition occurring when multiple instances are saving the same + binary (patch by Timo Sirainen). + + Test suite: added support for testing multiscript execution. + - Made compiler more lenient towars missing CRLF at the end of the script in a + hash comment. + - Body extension: don't give SKIP_BODY_BLOCK flag to message parser, we want + the body! (patch by Timo Sirainen). + - Fixed handling of implicit side effects for multiscript execution. + - Fixed bugs in multiscript support; subsequent keep actions were not always + merged correctly and implicit side effects were not always handled + correctly. + - Fixed a segfault bug in the sieve-test tool occurring when compile fails. + - Fixed segfault bug in action procesing. It was triggered while merging side + effects in duplicate actions. + - Fixed bug in the Sieve plugin that caused it to try to stat() a NULL path, + yielding a 'Bad address' error. + +v0.1.12 21-08-2009 Stephan Bosch <stephan@rename-it.nl> + + + Testsuite: added support for testing binaries stored on disk. + + Implemented the new date extension. This allows matching against date values + in header fields and the current date at the time of script evaluation. + +v0.1.11 08-08-2009 Stephan Bosch <stephan@rename-it.nl> + + + Built skeleton implementation for the date extension (RFC 5260). It + compiles, but it does not do anything useful yet. Therefore, it is not part + of the default compilation. + - Fixed ARM portability issues caused by char type not being signed on that + platform. Reading optional operands from a binary would fail for action side + effects. Also, an accidental mixup of an int return type with bool caused + the interpreter to continue on ARM even though an error occured. + - Removed direct stdint.h includes to prevent portability issues. + - Fixed segfault bug in the handling of script open failures. + - Include: improved user error messages and system log messages. + - Fixed copy-paste mixup between sieve_after and sieve_before settings in the + LDA Sieve plugin. If only a sieve_after script was active, nothing would + have been executed. Patch by Mike Abbott. + - Include: fixed a bug in HOME substitution in the sieve_dir path. Surfaced in + ManageSieve. + +v0.1.10 03-08-2009 Stephan Bosch <stephan@rename-it.nl> + + * Changed action execution of fileinto and keep. These changes depend on API + additions in Dovecot, making this release depend on Dovecot v1.2.2 or newer. + * Further developed the sieve-filter command line tool. This required a few + changes to the action execution of the Sieve engine. The tool was + successfully tested on folders with a few 100k spam messages. However, the + commandline options are still incomplete, a man page is missing and it needs + much more testing before I can recommend anyone to use this tool. + + Added support for the mailbox extension. This allows checking whether a + mailbox exists using the mailboxexists command and it adds the :create + argument to the fileinto command to create the mailbox when it is missing. + The :create feature is useless unless the Deliver LDA is run with the -n + option. + + Improved the testsuite with tests for message delivery. Messages stored + using keep and fileinto can be fed back into the Sieve engine for + verification. This includes testing of applied IMAP flags. + + Updated the man pages with the new method of specifying the supported + extensions using + and - (for the -x parameter of the sieve tools) + + Further developed the deprecated notify extension. A dummy for the denotify + command exists, meaning that its use does not cause an error anymore. + - Fixed a bug in the derivation of the binary path from the script path. A + bare filename would yield a path relative to root. + - Fixed a bug in the value matching code. The context data now uses a proper + pool instead of the data stack. Bug reported by Jan Sechser. + - Fixed assertion fail in the include extension caused by missing + initialization upon binary load. This bug surfaces only for stored + binaries. Bug reported by Tom Hendrikx. + - Fixed include error message for failed :global include. It mentioned the + wrong config parameter. + - Fixed broken wiki reference in an error message of the plugin about the + 'sieve' setting. + - Fixed behavior of fileinto when delivering into a namespace prefix. + Previous fix used the wrong storage. + +v0.1.9 22-07-2009 Stephan Bosch <stephan@rename-it.nl> + + * Removed the unfinished sieve-filter tool from the default build. It is now + only built when the --with-unfinished-features switch is supplied during + configure. + + Started building support for the ereject version of the reject action, + which has a preference to use an SMTP/LMTP protocol error instead of a + bounce message. This is to be used to make the Sieve plugin honour Deliver's + -e parameter. This is not yet finished and not built by default. + + Improved 'Permission denied' error messages just like Dovecot does, + precisely specifying what permission is missing to access or create a file. + + Added additional headers to the list of allowed headers for the address + test. The restrictive nature of the address test is not always appropriate. + Still thinking of a better, less restrictive implementation. + + Made the deprecated notify extension compatible with the old CMUSieve + plugin. However, the denotify command and the $text$ substitution are not + yet supported. + + Made the discard action log a message to avoid confusion about disappearing + messages. + - Fixed behavior of fileinto when delivering into a namespace prefix. It now + uses silent delivery into INBOX as fallback. + - Fixed logging of folder namespace prefix upon delivery into a prefixed + namespace. Formerly it only logged the bare folder name. + - Fixed a potential segfault in the argument validation. It didn't surface + because no command could have a :tag followed by an associated parameter as + last argument. + - Fixed segfault bug occurring in envelope test when performed on null (<>) + envelope path. The fix involves a rather large restructuring of the code to + make sure envelope addresses are properly handled everywhere (bug reported + by Nikita Koshikov) + - Envelope: fixed bug in application of address parts; failure to obtain + the part would cause inappropriate match success (bug reported by Ron Lee) + - Fixed extension conflict checks during validation. It could sometimes + produce useless errormessages. This is currently only used by the + deprecated extensions. + - Forgot to remove old explicit storage library dependency (patch by + Arkadiusz Miskiewicz). + - Fixed compiler warnings on certain platforms regarding the use fwrite for + outgoing message construction + +v0.1.8 12-07-2009 Stephan Bosch <stephan@rename-it.nl> + + - Fixed AIX compile problem. For portability, the typeof operator is + not used anymore. + + Added partial support for the deprecated notify extension. However, it + turns out that the implementation provided by cmusieve is even older (2001), + meaning that this is currently not backwards compatible with cmusieve. + +v0.1.7 05-07-2009 Stephan Bosch <stephan@rename-it.nl> + + + Added support for CRLF line breaks in strbuf error handler to fix a + ManageSieve problem. + + Improved consistency of sieve tool documentation and fixed missing + parameters in internal tool help output. + + Enhanced extensions configuration, allowing to specify the enabled + extensions relatively to the default (patch by Steffen Kaiser). + - Forgot to initialize script execution status in Sieve plugin, causing + segfaults on compile errors in specific conditions. + - Fixed logging in Sieve plugin for execution of default main script (went + to STDERR). + +v0.1.6 18-06-2009 Stephan Bosch <stephan@rename-it.nl> + + * Adjusted to changes in Dovecot to make it compile against v1.2.rc5 + * Made default of sieve_dir setting match the ManageSieve implementation. + - Fixed a few problems in de body extension that caused assert failures in + specific situations. + +v0.1.5 18-04-2009 Stephan Bosch <stephan@rename-it.nl> + + * Ported the implementation of the Sieve include extension to the latest + draft. This means that the import and export commands are replaced by a new + command called global. The import and export commands are now DEPRICATED and + are mere aliases for the global command. The new specification also adds the + :once modifier to the include command. The also newly specified global.* + variable namespace is not implemented yet as support for variable namespaces + is currently missing. + * Did a major rework of the multiscript support for better error handling and + made sure that persistent global scripts (sieve_before/sieve_after) are + always executed, even when the user does not have a script of his own and + a global default is missing. + + Provided basic support for the environment extension. Currenly, the name, + version and host items are useful. Others are pending. + + Improved error message that is presented when an unknown Sieve extension is + provided as argument to the require command. It now notifies the user that + Sieve core commands do not need to be specified in require. + - Fixed bug in includes at levels deeper than one. + - Fixed bug in address matching that was caused by the failure to handle group + specifications. In dovecot, these are marked by address items with NULL + elements, which causes a segfault if not considered. The group 'undisclosed- + recipients:;' in particular triggered this bug. Bug reported by Bernhard + Schmidt. + +v0.1.4 21-03-2009 Stephan Bosch <stephan@rename-it.nl> + + * Started work on the sieve-filter tool. With this command line tool it will + be possible to (re-)apply Sieve filters on a mail folder. It is currently + undocumented and far from functional. + + Added a custom debug extension that provides the possibility to print debug + messages from scripts executed by the Sieve tools. + - Fixed issue with opening relative paths as a mail file. Bug reported by Ian + P. Christian. + - Fixed MAC OSX compile problem. Turns out the extern modifier was missing at + multiple places. Bug reported by Edgar Fuss. + - Fixed Solaris compile problem: removed unecessary and unportable linker + flags that caused compile to fail. Bug reported by Andrés Yacopino. + +v0.1.3 12-02-2009 Stephan Bosch <stephan@rename-it.nl> + + * Adapted to changes in Dovecot, making this release dependent on Dovecot + >= 1.2.beta1 + * Made mail address comparison fully case-insensitive. This is particularly + noticeable for the :addresses argument of the vacation command. + + Finished enotify extension. Currently, only the mailto notification method + is implemented. All still needs to be tested thoroughly. + + Implemented multiscript support. It is now possible to execute multiple + Sieve scripts sequentially. Administrator-controlled scripts can be + executed before and after the user's script. Still needs to be tested + thoroughly. + + Implemented support for configuring the available Sieve extensions. + + Made the subaddress extension (partially) configurable using the + sieve_subaddress_sep setting, which allows specifying a (multi-charater) + separator other than '+'. + + Compiler now warns about invalid header field names used for the header and + address tests. + + Vacation extension now properly generates a References header for the + response message. + + Added testing of basic result execution to the test suite. Also added + supportfor testing the outgoing messages produced by the Sieve interpreter. + + Included execution of the actual result in the sieve-test command line tool. + The undocumented sieve-exec tool that existed for this is now removed as + planned. + + Added support for the now obsolete 'imapflags' extension for backwards + compatibility with CMUSieve. This also implements the mark/unmark commands. + - Fixed bugs in the regex extension: 1) if an optional match value did not in + fact match, subsequent match values would get unexpected indexes. 2) fixed + segfault bug occurring when regex is freed. + - Fixed bug in the use of the :from agrument for the vacation command. If this + address included a phrase part, the response would not be a valid RFC822 + message. + - Plugged a theoretical security hole occurring when a directory is opened as a + Sieve binary. + - Cleaned up and fixed various log messages. + - Fixed bug in the outgoing address verification. Addresses ending in ',' were + erroneously accepted. + +v0.1.2 26-11-2008 Stephan Bosch <stephan@rename-it.nl> + + - Fixed important bug in the redirect action (and probably other actions like + reject and vacation that only send messages). This was a bug in the handling + of context information during the execution of actions. It caused the sieve + interpreter to crash with a segfault when redirect was executed. + +v0.1.1 24-11-2008 Stephan Bosch <stephan@rename-it.nl> + + * Re-enabled support for compiling against dovecot headers. Much like + cmusieve, command line tools like sievec and sieved are not compiled in this + case. + * Started implementation of enotify extension. Not anywhere near finished + though. + * Adapted to changes in Dovecot on various occasions, making this release + dependent on Dovecot >= v1.2.alpa4. + + Improved logging of errors at specific occasions and added debug messages to + find script execution problems quicker. + + Removed code duplication between command line tools and the test suite. + Also restructured the sources of the tools. + + Added UTF-8 to UTF-7 folder name conversion for compatibility with IMAP. + + Created man pages for the command line tools. These are automatically + installed upon 'make install' + + Incorporated Valgrind support into the testsuite and fixed a few memory + leaks in the process. + - Fixed compile error surfacing for gcc3.4. Forgot mask argument for the + open() system call when the O_CREAT flag is specified. Bug found by + Sergey Ivanov. + - Fixed bug in the sievec tool. -d output was always written to stdout. + - Fixed important bug in the imap4flags extension. When no :flags argument is + specified, the previous version would always use the final value of the + internal variable to set the flags. This means that modifications to the + internal variable also affected the bare fileinto/keep actions executed + earlier. This does not comply to the RFC. + - Fixed bug in the include extension's import/export commands. Duplicate + import/exports caused problems. + - Fixed bug in the handling of non-existent scripts. Errors were sometimes + ignored. + - Dovecot omitted unfolding multi-line headers. This was added to the cmusieve + plugin after the code was incorporated into the new implementation. This is + now mplicitly fixed by concurrent change in Dovecot. + +v0.1.0 23-10-2008 Stephan Bosch <stephan@rename-it.nl> + + * Initial release + +Dovecot ManageSieve NEWS history: +--------------------------------- + +Dovecot 1.2: + +v0.11.11: + * This release contains adjustments to match changes in the Sieve API. This + means that this release will only compile against Pigeonhole Sieve + v0.1.15. + + Implemented ManageSieve QUOTA enforcement. + + Added MAXREDIRECTS capability after login. + + Implemented new script name rules specified in most recent ManageSieve + draft. + - Fixed assertion failure occurring with challenge-response SASL mechanisms. + - Made configure complain about trying to compile against installed Dovecot + headers alone. + - Fixed compile warning for compilation against CMUSieve. + +v0.11.10: + * This release contains adjustments to match changes in the Sieve API. This + means that this release will only compile against Pigeonhole Sieve + v0.1.14. + - Fixed compilation of ManageSieve against CMUSieve. + +v0.11.9: + * Adjusted to changes in the Dovecot login proxy API. This release + therefore depends on Dovecot v1.2.4. + + Reintroduced ability to abort SASL with "*" response. Latest ManageSieve + specification includes it. + +v0.11.8: + - Fixed TLS support for proxying ManageSieve. The protocol state machine + was incorrect. Also added a check that disables ssl when 'starttls' is + not enabled for the user. This produces a proper warning in the log file. + There is no such thing as a managesieveS protocol which has SSL from the + start. + +v0.11.7: + * Adjusted to changes in the Dovecot login API. This release now depends on + Dovecot v1.2.1 or newer. + * Incorporated various small changes in IMAP into ManageSieve. This includes + properly enabling the generation of core dumps. + - The previous release implicitly resolved the FreeBSD script truncation + error. This release adds a small correction to the code that detects the + truncation. + - Fixed panic occurring when many errors are produced by the Sieve compiler + (bug found by Pascal Volk). + - Fixed memory leak in the PUTSCRIPT command. + +v0.11.6: + * Adjusted to changes in Dovecot regarding client idle timeout vs + authentication timeout. This release now depends on Dovecot v1.2.rc6 or + newer. + - Fixed CRLF line breaks in compile errors (bug reported by Pascal Volk). + - Corrected directory/file creation behavior with respect to mode bits + and gid (bug reported by Pascal Volk). + - Improved handling of script truncation bugs: connection is now closed and + an error is logged. bug itself not fixed yet). + - Prevented temp script name from showing up in error output. + +v0.11.5: + * Incorporated various changes from imap-login into managesieve-login. This + includes changes in the proxy support. + +v0.11.4: + * Adjusted to changes in the Dovecot signal handler API. + +v0.11.3: + * Changed the SASL service name from "managesieve" into "sieve" as required + in the protocol specification. Don't forget to adjust your configuration + if your authentication mechanism depends on this service name. + * Adapted to changes in Dovecot, making this release dependent on Dovecot + >= v1.2.beta1. + * Adapted to changes in the new Sieve implementation, making this release + dependent on Dovecot Sieve >= v0.1.3 if used. The old cmusieve plugin is + still supported. + + Implemented making the SIEVE and NOTIFY capability fully dynamic, meaning + that the sieve_extensions setting that was introduced for the new Sieve + plugin properly affects the ManageSieve daemon as well. + + Added support for the CHECKSCRIPT command. In terms of the supported + commands, the ManageSieve daemon now complies with protocol VERSION 1.0 as + listed in the CAPABILITY response. + - Fixed maximum permissions for uploaded scripts; was 0777. This + was shielded however by the default umask (not documented to be + configurable), so the actual permissions would never have been 0777. + - Fixed a segfault bug in the authentication time-out. Bug report and trace + provided by Wolfgang Friebel. + - Fixed handling of ~/ in use of mail-data for script location. + - Fixed small problems in the login proxy support. + +v0.11.2: + * Adapted to changes in Dovecot, making this release dependent on Dovecot + >= v1.2.alpa4. + +v0.11.1: + - Fixed security issue that gives virtual users the ability to read and + modify each other's scripts if the directory structure of the sieve + storage is known. + * Updated NOOP command to match new protocol specification + + Improved error handling and implemented the new response codes: + ACTIVE, NONEXISTENT, ALREADYEXISTS and WARNINGS + +v0.11.0: + * Upgraded to Dovecot v1.2 + * Added support for new ManageSieve extensions RENAME and NOOP + * Moved sieve settings to plugin {} section of config file. Now the settings + `sieve` and `sieve_dir` in the plugin section are used for the Sieve plugin + and the ManageSieve service, avoiding the posibility of accidental + differences in configuration. + +Dovecot 1.1: + +v0.10.3 + * Removed erroneous inline declarations that caused compiler warnings. GCC 4.3 + turns out to fail entirely as reported by Joel Johnson. + * Fixed auto-dectection of Sieve implementation during ./configure. It now + produces a proper error when the directory is invalid. + +v0.10.2 + * Fixed bug that caused SASL mechanisms that require more than a single client + response to fail. Reported by Steffen Kaiser and occured when he tried using + the (obsolete) LOGIN mechanism. + * Updated installation and configuration documentation to match the + information provided in the wiki + +v0.10.1 + * Fixed bug introduced in v0.10.0: compiled scripts were also written to disk + in the sieve/tmp directory and left there. This accumulates much .sievec + junk in that directory over time. + * Fixed bug in tmp file generation for sieve-storage: errors other than EEXIST + would cause the daemon to sleep() loop indefinitely. + + + Improved log lines to be more recognizable as being generated from + managesieve. + + Added short proxy configuration explanation to the README file + + Added 'Known Issues' section to the README file + - Fixed assert bug in sieve-storage occurring when save is canceled. + +v0.10.0 + * Upgraded to Dovecot 1.1: + - The actual managesieve implementation is now a separate package. + The dovecot tree still needs to be patched though to make dovecot + recognize the new managesieve service. + - Incorporated changes to imap/imap-login into the equivalent + managesieve processes. + - Removed cmusieve implementation from managesieve sources. It is + now linked externally from the dovecot-sieve-1.1 package. + - Restructured README.managesieve file into separate README, NEWS, + TODO, DESIGN and INSTALL files. + * Added support for new libsieve implementation (to be released). This + package can be compiled with either the new or the old Sieve + implementation (autodetected). If the new Sieve becomes stable, this + package will be merged with it to make a single package for Dovecot + Sieve support. + +Dovecot 1.0: + +v9 + ++ Definitively fixed the segfault mentioned in V8. It proved to be + very time-constrained and thus hard to reproduce. The error turned out + to be related to the input handling of the login daemon during + authentication. ++ Checked for changes in the imap daemon that weren't propagated to the + managesieve implementation due to code duplication. ++ Fixed a bug in the autodetection of the sieve storage location. ++ Fixed bug in the sieve storage that failed to refresh the symlink if + the storage was moved. ++ Improved error handing in the sieve-storage implementation in various + places. ++ Fixed the situation in which the active script link is located in the + sieve storage. ++ Added managesieve configuration to dovecot-example.conf and made the example + in this file more concise. + +v8 + ++ Fixed a few incompatibilities with 1.0.7 version. For instance, the "Logged + in" message is now sent by the -login process and not by the managesieve + daemon anymore. This caused a segfault every once in a while. ++ Probably fixed the settings problem reported by Steffen Kaiser regarding + login_dir. 'dovecot -n' now reports correct results, but testing will show + whether the whole problem is solved. ++ The managesieve daemon now accepts the sieve_storage and sieve configuration + settings, so it is now possible to explicitly configure the location of the + sieve storage and the active script respectively. The daemon still falls back + to using the mail_location (MAIL) settings if nothing else is specified. ++ The cyrus timsieved does not use the + character in string literals and many + clients have adopted to this behaviour. The latest managesieve (08) advises to + accept a missing + from clients. The server should not send any + characters + as well. This behavior is now implemented on the server. ++ Cleaned up sieve-storage.c: split up the sieve_storage_create function in + various sub-functions for obtaining the various paths and directories. ++ Forced manual intervention if rescueing a non-symlink file at the active script + path fails somehow. Previously, this presented the admin with a log message + that it had just eaten the script, which is not very nice. ++ Restructured the README.managesieve file and added some more explanation with + regard to the configuration of the daemon. + +v7 + +- Robin Breathe indicated that the regex capability was missing in the server's + SIEVE listing. It turns out I forgot to make arrangements for setting + ENABLE_REGEX in the cmu libsieve sources, so the regex extension was not + compiled in. I copied the configure.in section regarding ENABLE_REGEX from + dovecot-sieve-1.0.2 and that fixed the problem. + +v6 + +- Corked the client output stream while producing the capability greeting and on + other some other occasions as well. Some naive client implementations expect to + receive this as a single tcp frame and it is a good practice to do so anyway. + Using this change the Thunderbird sieve extension (v0.1.1) seemed to work. However, + scripts larger than a tcp frame still caused failures. All these issues are fixed + in the latest version of the sieve add-on (currently v0.1.4). +- Cleaned up the new proxy source. My editor made the indentation a complete mess + in terms of TABs vs spaces. +- Added TRYLATER response codes to BYE and NO messages where appropriate. +- Recopied the libsieve library into this patch to incorporate any changes that were + made (only sieve-cmu.c still needs to be compared to the old cmu-sieve.c). This + also solves the __attribute__((unused)) GCC dependencies. These were fixed long + ago by Timo.... the code duplication beast strikes again. +- Removed spurious return value from void function in + src/lib-sieve/sieve-implementation.c as reported by Robin Breathe. GCC fails to + report these issues. The function involved is currently not used and serves only + as an example on how dovecot could support multiple sieve backends... + +v5 + +- Applied patch by Uldis Pakuls to fix master_dump_settings bug +- Added some compilation/installation info to this README +- Moved README to source tree root as README.managesieve +- Fixed minor error handling bug in sieve_storage.c with respect to a missing + root directory. +- Now sieve capabilities are reported as they are specified by the implementing + library and not in forced upper case. The sieve RFC now explicitly states + that sieve capability identifiers are case-sensitive. This broke compatibility + with SquirrelMail/Avelsieve. +- Disabled ANONYMOUS login entirely until proper support is implemented. V4 + claimed to do so as well, but in fact it only stopped announcing it. +- Implemented managesieve-proxy. It is not so much a clean copy of imap-proxy, + since the managesieve greeting is much more complex and requires parsing. + Configuration is identical to imap-proxy. This seems to be a little under- + documented however (http://wiki.dovecot.org/PasswordDatabase/ExtraFields). + +v4 + +- Added managesieve_implementation_string setting to the managesieve + configuration. This can be used to customize the default "IMPLEMENTATION" + capability response. +- Denied ANONYMOUS login until proper support is implemented +- Fixed problem with authenticate command regarding continued responses. In + V3 only initial response would work. Problem was caused by rc2 -> rc28 + upgrade. One of the clear reasons why code duplication is a very bad idea. +- Fixed readlink bug as indicated by Timo: return value of readlink can also + be -1. +- Fixed bug in the regular file rescue code, as introduced in the previous + version. Used stat instead of lstat. This caused the symlink to be rescued + subsequently in the next activation, thus still overwriting the initially + rescued script. + +v3 + +- Updated source to compile with dovecot 1.0.rc27 +- Daemon now uses the same location for .dovecot.sieve as dovecot-lda + This is typically ~/.dovecot.sieve +- If .dovecot.sieve is a regular file, it is now moved into the script storage as + dovecot.orig.sieve, preventing deletion of (important) active scripts + upon upgrade. +- Changed error handling to yield a BYE message when the managesieve + daemon exits unexpectedly (upon login) before any commands are entered. + Horde-ingo would wait indefinitely for a response. + +v2 + +- Fixed the bug (missing CRLF) in the authenticate command +- Modified the sieve storage library making the interface much less crude. +- The scripts put on the server using the putscript command are now + checked before they are accepted. +- The reported SIEVE capability is now directly read from the sieve + implementation (in this case cmu), listing much more than "FILEINTO + VACATION". +- Imported instance of libsieve source into this patch for implementation + of script checking and capability listing. THIS NEEDS TO BE CHANGED! +- Fixed some minor bugs in the putscript command diff --git a/pigeonhole/README b/pigeonhole/README new file mode 100644 index 0000000..ad2ab02 --- /dev/null +++ b/pigeonhole/README @@ -0,0 +1,332 @@ +Pigeonhole for Dovecot v2.4 + +Introduction +============ + +This package is part of the Pigeonhole project (http://pigeonhole.dovecot.org). +It adds support for the Sieve language (RFC 5228) and the ManageSieve protocol +(RFC 5804) to the Dovecot Secure IMAP Server. In the literal sense, a pigeonhole +is a a hole or recess inside a dovecot for pigeons to nest in. It is, however, +also the name for one of a series of small, open compartments in a cabinet used +for filing or sorting mail. As a verb, it describes the act of putting an item +into one of those pigeonholes. The name `Pigeonhole' therefore well describes an +important part of the functionality that this project adds to Dovecot: sorting +and filing e-mail messages. + +The Sieve language is used to specify how e-mail needs to be processed. By +writing Sieve scripts, users can customize how messages are delivered, e.g. +whether they are forwarded or stored in special folders. Unwanted messages can +be discarded or rejected, and, when the user is not available, the Sieve +interpreter can send an automated reply. Above all, the Sieve language is meant +to be simple, extensible and system independent. And, unlike most other mail +filtering script languages, it does not allow users to execute arbitrary +programs. This is particularly useful to prevent virtual users from having full +access to the mail store. The intention of the language is to make it impossible +for users to do anything more complex (and dangerous) than write simple mail +filters. + +Using the ManageSieve protocol, users can upload their Sieve scripts remotely, +without needing direct filesystem access through FTP or SCP. Additionally, a +ManageSieve server always makes sure that uploaded scripts are valid, preventing +compile failures at mail delivery. + +This package provides Sieve support as a plugin to Dovecot's Local Delivery +Agent (LDA) and Dovecot's LMTP service. The ManageSieve protocol is provided is +an additional service, next to Dovecot's own POP3 and IMAP services. + +Features +======== + + * The Pigeonhole Sieve implementation aims to be admin- and user-friendly. + Much like Dovecot itself, common error messages are made as easily + understandable as possible. Any crash, no matter how it happened, is + considered a bug that will be fixed. The compiler does not bail on the first + error, but it looks for more script errors to make debugging more efficient. + + * The Pigeonhole Sieve implementation is, much like the Sieve language itself, + highly extensible with new Sieve capabilities. This includes support for + third-party plugins. It should eventually provide the necessary + infrastructure for at least all currently known relevant (proposed) Sieve + extensions. The goal is to keep the extension interface provided by the + Sieve implementation as generic as possible, i.e. without explicit support + for specific extensions. New similar extensions can then use the same + interface methods without changes to the Sieve engine code. If an extension + is not loaded using the require command, the compiler truly does not know of + its existence. + + * The Pigeonhole Sieve plugin is backwards compatible with the old CMUSieve + plugin, which provided Sieve support for older versions of Dovecot. All + Sieve extensions supported by the old plugin are also supported by the + Pigeonhole Sieve plugin, including those that are now considered to be + deprecated. + + * The Pigeonhole Sieve implementation supports executing multiple Sieve + scripts sequentially. Using this feature it is possible to execute + administrator-controlled Sieve scripts before and after the user's personal + Sieve script, guaranteeing that responses and message deliveries are never + duplicated. This implementation is based on a draft specification + (http://tools.ietf.org/html/draft-degener-sieve-multiscript-00), which + defines the Sieve behavior when multiple scripts are executed sequentially + on the same message. + + * The Pigeonhole Sieve implementation includes a test suite to automatically + assess whether the compiled Sieve engine works correctly. The test suite is + an extension to the Sieve language and is therefore easily extended with new + tests. Currently, the test suite is mostly limited to testing script + processing. The performed actions are not tested fully yet. + + * The Pigeonhole Sieve implementation supports the new and very useful + variables extension, which allows maintaining state information throughout + a Sieve script across subsequent rules. + + * The Pigeonhole Sieve plugin is distributed with a sieve-test tool that + simplifies testing Sieve scripts and provides additional debugging + facilities. + +Sieve Implementation Status +=========================== + +The core of the language (as specified in RFC 5228) is fully supported. In +addition to that, this Sieve implementation features various extensions. The +following list outlines the implementation status of each supported extension: + + The language extensions defined in the base specification are fully supported: + + encoded-character (RFC 5228; page 10) + fileinto (RFC 5228; page 23) + envelope (RFC 5228; page 27) + + The following Sieve language extensions are also supported: + + copy (RFC 3894): fully supported. + body (RFC 5173): fully supported. + environment (RFC 5183): fully supported (v0.4.0+). + variables (RFC 5229): fully supported. + vacation (RFC 5230): fully supported. + + vacation-seconds (RFC 6131): fully supported (v0.2.3+). + relational (RFC 5231): fully supported. + imap4flags (RFC 5232): fully supported. + subaddress (RFC 5233): fully supported, but with limited configurability. + spamtest and virustest (RFC 5235): fully supported (v0.1.16+). + date (RFC 5260; Section 4): fully supported (v0.1.12+). + index (RFC 5260; Section 6): fully supported (v0.4.7+). + editheader (RFC 5293): fully supported (v0.3.0+). + reject (RFC 5429; Section 2.2): fully supported. + enotify (RFC 5435): fully supported (v0.1.3+). + mailto method (RFC 5436): fully supported (v0.1.3+). + xmpp method (RFC 5437): is under development and will become available + as a plugin. + ihave (RFC 5463): fully supported (v0.2.4+). + mailbox (RFC 5490; Section 3): fully supported (v0.1.10+), but ACL + permissions are not verified for mailboxexists. + mboxmetadata and servermetadata (RFC 5490): fully supported (v0.4.7+) + foreverypart (RFC 5703; Section 3): fully supported (v0.4.10+). + mime (RFC 5703; Section 4): fully supported (v0.4.10+). + extracttext (RFC 5703; Section 7): fully supported (v0.4.12+). + include (RFC 6609): fully supported (v0.4.0+). + imapsieve (RFC 6785): fully supported (v0.4.14+). + duplicate (RFC 7352): fully supported (v0.4.3+). + regex (draft v08; not latest version): almost fully supported, but + UTF-8 is not supported. + + The following deprecated extensions are supported for backwards + compatibility: + + imapflags (obsolete draft): fully backwards compatible (v0.1.3+) + notify (obsolete draft): fully backwards compatible (v0.1.15+) + + The availability of these deprecated extensions is disabled by default. + + The following Dovecot-specific Sieve extensions are available: + + vnd.dovecot.debug (v0.3.0+): + Allows logging debug messages. + vnd.dovecot.execute (v0.4.0+; sieve_extprograms plugin): + Implements executing a pre-defined set of external programs with the + option to process string data through the external program. + vnd.dovecot.filter (v0.4.0+; sieve_extprograms plugin): + Implements filtering messages through a pre-defined set of external + programs. + vnd.dovecot.pipe (v0.4.0+; sieve_extprograms plugin): + Implements piping messages to a pre-defined set of external programs. + vnd.dovecot.report (v0.4.14): + Implements sending MARF reports (RFC 5965). + + The following extensions are under development: + + ereject (RFC 5429; page 4): implemented, but currently equal to reject. + + Many more extensions to the language exist. Not all of these extensions are + useful for Dovecot in particular, but many of them are. Currently, the + author has taken notice of the following extensions: + + replace (RFC 5703; Section 5): planned. + enclose (RFC 5703; Section 6): planned. + envelope-dsn, envelope-deliverby, redirect-dsn and + redirect-deliverby (RFC 6009): planned; depends on lib-smtp changes in + Dovecot. + extlists (RFC 6134): planned. + convert (RFC 6558): under consideration. + + These extensions will be added as soon as the necessary infrastructure is + available. + +Check the TODO file for an up-to-date list of open issues and current +development. + +Compiling and Configuring +========================= + +Refer to INSTALL file. + +Sieve Tools +=========== + +To test the sieve engine outside deliver, it is useful to try the commands that +exist in the src/sieve-tools/ directory of this package. After installation, +these are available at your $prefix/bin directory. The following commands are +installed: + +sievec - Compiles sieve scripts into a binary representation for later + execution. Refer to the next section on manually compiling Sieve + scripts. + +sieve-test - This is a universal Sieve test tool for testing the effect of a + Sieve script on a particular message. It allows compiling, + running and testing Sieve scripts. It can either be used to + display the actions that would be performed on the provided test + message or it can be used to test the actual delivery of the + message and show the messages that would normally be sent through + SMTP. + +sieve-dump - Dumps the content of a Sieve binary file for (development) + debugging purposes. + +sieve-filter - Allow running Sieve filters on messages already stored in a + mailbox. + +When installed, man pages are also available for these commands. In this package +the man pages are present in doc/man and can be viewed before install using +e.g.: + +man -l doc/man/sieve-test.1 + +Various example scripts are bundled in the directory 'examples'. These scripts +were downloaded from various locations. View the top comment in the scripts for +url and author information. + +Compiling Sieve Scripts +======================= + +When the LDA Sieve plugin executes a script for the first time (or after it has +been changed), it is compiled into into a binary form. The Pigeonhole Sieve +implementation uses the .svbin extension to store compiled Sieve scripts (e.g. +.dovecot.svbin). To store the binary, the plugin needs write access in the +directory in which the script is located. + +A problem occurs when a global script is encountered by the plugin. For security +reasons, global script directories are not supposed to be writable by the user. +Therefore, the plugin cannot store the binary when the script is first compiled. +Note that this doesn't mean that the old compiled version of the script is used +when the binary cannot be written: it compiles and uses the current script +version. The only real problem is that the plugin will not be able to update +the binary on disk, meaning that the global script needs to be recompiled each +time it needs to be executed, i.e. for every incoming message, which is +inefficient. + +To mitigate this problem, the administrator must manually pre-compile global +scripts using the sievec command line tool. For example: + +sievec /var/lib/dovecot/sieve/global/ + +This is often necessary for scripts listed in the sieve_default, sieve_before +and sieve_after settings. For global scripts that are only included in other +scripts using the include extension, this step is not necessary, since included +scripts are incorporated into the binary produced for the main script located in +a user directory. + +Compile and Runtime Logging +=========================== + +Log messages produced at runtime by the Sieve plugin are written to two +locations: + + * Messages are primarily logged to the user log. By default this log file is + located in the same directory as the user's main active personal script (as + specified by the sieve setting). This log file bears the name of that script + file appended with ".log", e.g. ".dovecot.sieve.log". The location of the + user log file can also be explicitly configured using the sieve_user_log + setting (e.g. for when Sieve scripts are not stored on the local file + system). + + If there are errors or warnings in the script, the messages are appended to + that log file until it eventually grows too large. When that happens, the + old log file is rotated to a ".log.0" file and an empty log file is started. + Informational messages are not written to this log file and the log file is + not created until messages are actually logged, i.e. when an error or + warning is produced. + + * Messages that could be of interest to the system administrator are also + written to the Dovecot LDA logging facility (usually syslog). This includes + informational messages that indicate what actions are executed on incoming + messages. Compile errors encountered in the user's private script are not + logged here. + +The ManageSieve service reports compile errors and warnings only back to the +user. System and configuration-related messages are written to the Dovecot +logging facility. + +Known issues +============ + +Sieve +----- + +Most open issues are outlined in the TODO file. The more generic ones are (re-) +listed here: + +* Compile errors are sometimes a bit obscure and long. This needs work. + Suggestions for improvement are welcome. + +* The documentation needs work. + +ManageSieve +----------- + +* Although this ManageSieve server should comply with the draft specification of + the ManageSieve protocol, quite a few clients don't. This is particularly true + for the TLS support. However, now that Cyrus' Timsieved has changed its + behavior towards protocol compliance, all those clients will follow + eventually. + + Clients known to have TLS issues: + - Thunderbird Sieve add-on: fixed as per version 0.1.5 + - AvelSieve: patch on the wiki: http://wiki.dovecot.org/ManageSieve + - KMail + kio_sieve: TLS broken for old versions. This issue is fixed at + least in kmail 1.9.9 / kde 3.5.9. + + Unfortunately, there is no reliable way to provide a workaround for this + problem. We will have to wait for the authors of these clients to make the + proper adjustments. + +* Other client issues: + + - SmartSieve, WebSieve: + These clients are specifically written for Cyrus timsieved and fail on + multiple stages of the protocol when connected to Pigeonhole ManageSieve. + +Authors +======= + +Refer to AUTHORS file. + +Contact Info +============ + +Stephan Bosch <stephan at rename-it dot nl> +IRC: Freenode, #dovecot, S[r]us +Web: http://pigeonhole.dovecot.org + +Please use the Dovecot mailing list <dovecot at dovecot.org> for questions about +this package. You can post to the list without subscribing, the mail then waits +in a moderator queue for a while. See http://dovecot.org/mailinglists.html diff --git a/pigeonhole/TODO b/pigeonhole/TODO new file mode 100644 index 0000000..39420b5 --- /dev/null +++ b/pigeonhole/TODO @@ -0,0 +1,97 @@ +Current activities: + +* Rework string matching: + - Give Sieve its own runtime string type, rather than (ab)using string_t. + - Add support for stream matching for handling large values, e.g. from the + body extension. + - Improve efficiency of :matches and :contains match types. +* Build proper comparator support: + - Add normalize() method to comparators to normalize the string before + matching (for efficiency). + - Allow for the existence of dynamic comparators (i.e. specified by + variables). + - Implement comparator-i;unicode-casemap. + +Parallel plugin-based efforts (on hold at the moment): + +* Implement enotify xmpp method as a plugin. + +Next (mostly in order of descending priority/precedence): + +* Implement message modification and extraction API in order to: + - Properly implement the interaction between editheader and foreverypart/mime. + - Implement replace, enclose extensions. +* Properly implement Sieve internationalization support (utf-8 handling), + currently it is not complete: + - Make this implementation fully conform section 2.7.2 of RFC5228 (Comparisons + Across Character Sets). + - Verify validity of utf8 where necessary. +* Further develop regex extension and update it to the latest draft: + - Implement the :quoteregex set modifier + - Investigate the use of the TRE regexp library to gain UTF-8 capability + (posix regexes actually do support utf8, but only when locale is set + accordingly) +* Finish LDAP Sieve script storage for read-only access. + - Consolidate LDAP connections when more than a single Sieve script must be + loaded from different storages linked to the same LDAP server. + - Adjust Sieve script API to support asynchronous script retrieval to + retrieve scripts in parallel when possible. +* Improve error handling. + - Implement dropping errors in the user's mailbox as a mail message. +* Finish body extension: + - Build test cases for decoding MIME encodings to UTF-8 +* Cleanup the test suite + - Restructure test scripts + - Add more comment on purpose of tests +* Finish the ereject extension +* Vacation extension improvements: + - Implement configurable sender exclusion list. + - Implement mechanism for implicitly including an account's aliases in the + vacation command's :addresses list. +* Fix remaining RFC deviations: + - Fix issues listed in doc/rfc/RFC-questions.txt based on answers + - Verify outgoing mail addresses at runtime when necessary + (e.g. after variables substitution) + - Improve handling of invalid addresses in headers (requires Dovecot changes) +* Improve sieve_extprograms plugin: + - Redesign (forcible) local script termination. It should use SIGCHLD and + a ioloop-based timeout. + - Add facility to trigger a temporary failure condition when a program + fails rather than an implicit keep. + - Add a method to implicitly pass environment variables such as SENDER and + RECIPIENT through the script socket service. +* Make testsuite much more exhaustive: + - Add support for testing the content of result actions + - Test as many error/warning/info conditions as possible. + - Review the specification documents and check whether the given requirements + are tested at least once. +* Fix ManageSieve proxy to recognize response codes from the backend and forward + them to the user if appropriate/safe. Probably means implementing a proper + ManageSieve client library. +* Test ManageSieve behavior thoroughly: + - Test pipelined behavior + - Test proxy authentication +* Code cleanup: + - Make address handling more uniform. + - Review all FIXMEs + +* Build a server with test mail accounts that processes lots and lots of mail + (e.g. spam, mailing lists etc.) + +Low priority items: + +* Implement extlists extension as a plugin +* Enotify extension: detect use of variable values extracted from the message + that are used in the method argument. RFC reports this as a security issue. +* Provide a solution for mail_get_headers_utf8 reparsing the whole message each + time it is called (header and address test; Timo might provide solution from + within Dovecot) +* Warn during compile if using non-existent folders. + +* Variables extension: implement compile time evaluation of constant values + - Detect assignment of too large constant values to variables at compile + time. +* Add development documentation, i.e. comment on library functions and document + the binary and byte-code format. +* Implement sip-message notify mechanism. + diff --git a/pigeonhole/aclocal.m4 b/pigeonhole/aclocal.m4 new file mode 100644 index 0000000..c29cec5 --- /dev/null +++ b/pigeonhole/aclocal.m4 @@ -0,0 +1,1174 @@ +# generated automatically by aclocal 1.16.3 -*- Autoconf -*- + +# Copyright (C) 1996-2020 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +# Copyright (C) 2002-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.16' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.16.3], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.16.3])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + AS_CASE([$CONFIG_FILES], + [*\'*], [eval set x "$CONFIG_FILES"], + [*], [set x $CONFIG_FILES]) + shift + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf + do + # Strip MF so we end up with the name of the file. + am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`AS_DIRNAME(["$am_mf"])` + am_filepart=`AS_BASENAME(["$am_mf"])` + AM_RUN_LOG([cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles]) || am_rc=$? + done + if test $am_rc -ne 0; then + AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE="gmake" (or whatever is + necessary). You can also try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking).]) + fi + AS_UNSET([am_dirpart]) + AS_UNSET([am_filepart]) + AS_UNSET([am_mf]) + AS_UNSET([am_rc]) + rm -f conftest-deps.mk +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking is enabled. +# This creates each '.Po' and '.Plo' makefile fragment that we'll need in +# order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.65])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> +# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl +]) +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542> + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: <https://www.gnu.org/software/coreutils/>. + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless 'enable' is passed literally. +# For symmetry, 'disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. +AC_DEFUN([AM_MAINTAINER_MODE], +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], + [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], + am_maintainer_other[ make rules and dependencies not useful + (and sometimes confusing) to the casual installer])], + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST([MAINT])dnl +] +) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check whether make has an 'include' directive that can support all +# the idioms we need for our automatic dependency tracking code. +AC_DEFUN([AM_MAKE_INCLUDE], +[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) +cat > confinc.mk << 'END' +am__doit: + @echo this is the am__doit target >confinc.out +.PHONY: am__doit +END +am__include="#" +am__quote= +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) + AS_CASE([$?:`cat confinc.out 2>/dev/null`], + ['0:this is the am__doit target'], + [AS_CASE([$s], + [BSD], [am__include='.include' am__quote='"'], + [am__include='include' am__quote=''])]) + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +AC_MSG_RESULT([${_am_result}]) +AC_SUBST([am__include])]) +AC_SUBST([am__quote])]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + MISSING="\${SHELL} '$am_aux_dir/missing'" +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Copyright (C) 1999-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# Copyright (C) 2001-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar <conftest.tar]) + AM_RUN_LOG([cat conftest.dir/file]) + grep GrepMe conftest.dir/file >/dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([m4/dovecot.m4]) +m4_include([m4/libtool.m4]) +m4_include([m4/ltoptions.m4]) +m4_include([m4/ltsugar.m4]) +m4_include([m4/ltversion.m4]) +m4_include([m4/lt~obsolete.m4]) diff --git a/pigeonhole/compile b/pigeonhole/compile new file mode 100755 index 0000000..23fcba0 --- /dev/null +++ b/pigeonhole/compile @@ -0,0 +1,348 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2018-03-07.03; # UTC + +# Copyright (C) 1999-2020 Free Software Foundation, Inc. +# Written by Tom Tromey <tromey@cygnus.com>. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to <bug-automake@gnu.org> or send patches to +# <automake-patches@gnu.org>. + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN* | MSYS*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/* | msys/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to <bug-automake@gnu.org>. +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ + icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/pigeonhole/config.guess b/pigeonhole/config.guess new file mode 100755 index 0000000..f50dcdb --- /dev/null +++ b/pigeonhole/config.guess @@ -0,0 +1,1480 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2018 Free Software Foundation, Inc. + +timestamp='2018-02-24' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <https://www.gnu.org/licenses/>. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# +# Please send patches to <config-patches@gnu.org>. + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2018 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > "$dummy.c" ; + for c in cc gcc c89 c99 ; do + if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "$UNAME_SYSTEM" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval "$set_cc_for_build" + cat <<-EOF > "$dummy.c" + #include <features.h> + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + "/sbin/$sysctl" 2>/dev/null || \ + "/usr/sbin/$sysctl" 2>/dev/null || \ + echo unknown)` + case "$UNAME_MACHINE_ARCH" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine="${arch}${endian}"-unknown + ;; + *) machine="$UNAME_MACHINE_ARCH"-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently (or will in the future) and ABI. + case "$UNAME_MACHINE_ARCH" in + earm*) + os=netbsdelf + ;; + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval "$set_cc_for_build" + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # Determine ABI tags. + case "$UNAME_MACHINE_ARCH" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "$UNAME_VERSION" in + Debian*) + release='-gnu' + ;; + *) + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "$machine-${os}${release}${abi}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit ;; + *:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" + exit ;; + *:ekkoBSD:*:*) + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" + exit ;; + *:SolidBSD:*:*) + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" + exit ;; + *:MirBSD:*:*) + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" + exit ;; + *:Sortix:*:*) + echo "$UNAME_MACHINE"-unknown-sortix + exit ;; + *:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox + exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE=alpha ;; + "EV4.5 (21064)") + UNAME_MACHINE=alpha ;; + "LCA4 (21066/21068)") + UNAME_MACHINE=alpha ;; + "EV5 (21164)") + UNAME_MACHINE=alphaev5 ;; + "EV5.6 (21164A)") + UNAME_MACHINE=alphaev56 ;; + "EV5.6 (21164PC)") + UNAME_MACHINE=alphapca56 ;; + "EV5.7 (21164PC)") + UNAME_MACHINE=alphapca57 ;; + "EV6 (21264)") + UNAME_MACHINE=alphaev6 ;; + "EV6.7 (21264A)") + UNAME_MACHINE=alphaev67 ;; + "EV6.8CB (21264C)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8AL (21264B)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8CX (21264D)") + UNAME_MACHINE=alphaev68 ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE=alphaev69 ;; + "EV7 (21364)") + UNAME_MACHINE=alphaev7 ;; + "EV7.9 (21364A)") + UNAME_MACHINE=alphaev79 ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo "$UNAME_MACHINE"-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo "$UNAME_MACHINE"-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix"$UNAME_RELEASE" + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux"$UNAME_RELEASE" + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval "$set_cc_for_build" + SUN_ARCH=i386 + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH=x86_64 + fi + fi + echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos"$UNAME_RELEASE" + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos"$UNAME_RELEASE" + ;; + sun4) + echo sparc-sun-sunos"$UNAME_RELEASE" + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos"$UNAME_RELEASE" + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint"$UNAME_RELEASE" + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint"$UNAME_RELEASE" + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint"$UNAME_RELEASE" + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten"$UNAME_RELEASE" + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten"$UNAME_RELEASE" + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix"$UNAME_RELEASE" + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix"$UNAME_RELEASE" + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix"$UNAME_RELEASE" + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" +#ifdef __cplusplus +#include <stdio.h> /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos"$UNAME_RELEASE" + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] + then + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$TARGET_BINARY_INTERFACE"x = x ] + then + echo m88k-dg-dgux"$UNAME_RELEASE" + else + echo m88k-dg-dguxbcs"$UNAME_RELEASE" + fi + else + echo i586-dg-dgux"$UNAME_RELEASE" + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + fi + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + fi + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + case "$UNAME_MACHINE" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "$sc_cpu_version" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "$sc_kernel_bits" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "$HP_ARCH" = "" ]; then + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ "$HP_ARCH" = hppa2.0w ] + then + eval "$set_cc_for_build" + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH=hppa2.0w + else + HP_ARCH=hppa64 + fi + fi + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux"$HPUX_REV" + exit ;; + 3050*:HI-UX:*:*) + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo "$UNAME_MACHINE"-unknown-osf1mk + else + echo "$UNAME_MACHINE"-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi"$UNAME_RELEASE" + exit ;; + *:BSD/OS:*:*) + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case "$UNAME_PROCESSOR" in + amd64) + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; + esac + echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" + exit ;; + i*:CYGWIN*:*) + echo "$UNAME_MACHINE"-pc-cygwin + exit ;; + *:MINGW64*:*) + echo "$UNAME_MACHINE"-pc-mingw64 + exit ;; + *:MINGW*:*) + echo "$UNAME_MACHINE"-pc-mingw32 + exit ;; + *:MSYS*:*) + echo "$UNAME_MACHINE"-pc-msys + exit ;; + i*:PW*:*) + echo "$UNAME_MACHINE"-pc-pw32 + exit ;; + *:Interix*:*) + case "$UNAME_MACHINE" in + x86) + echo i586-pc-interix"$UNAME_RELEASE" + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix"$UNAME_RELEASE" + exit ;; + IA64) + echo ia64-unknown-interix"$UNAME_RELEASE" + exit ;; + esac ;; + i*:UWIN*:*) + echo "$UNAME_MACHINE"-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + *:GNU:*:*) + # the GNU system + echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" + exit ;; + i*86:Minix:*:*) + echo "$UNAME_MACHINE"-pc-minix + exit ;; + aarch64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arm*:Linux:*:*) + eval "$set_cc_for_build" + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi + else + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + cris:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + crisv32:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + e2k:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + frv:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + hexagon:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + i*86:Linux:*:*) + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + exit ;; + ia64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + k1om:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m32r*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m68*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" + test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } + ;; + mips64el:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-"$LIBC" + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-"$LIBC" + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-"$LIBC" + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-"$LIBC" + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-"$LIBC" + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-"$LIBC" + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-"$LIBC" + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" + exit ;; + sh64*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + sh*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + tile*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + vax:Linux:*:*) + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" + exit ;; + x86_64:Linux:*:*) + if objdump -f /bin/sh | grep -q elf32-x86-64; then + echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32 + else + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + fi + exit ;; + xtensa*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo "$UNAME_MACHINE"-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo "$UNAME_MACHINE"-unknown-stop + exit ;; + i*86:atheos:*:*) + echo "$UNAME_MACHINE"-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo "$UNAME_MACHINE"-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos"$UNAME_RELEASE" + exit ;; + i*86:*DOS:*:*) + echo "$UNAME_MACHINE"-pc-msdosdjgpp + exit ;; + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" + else + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + echo "$UNAME_MACHINE"-pc-isc"$UNAME_REL" + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" + else + echo "$UNAME_MACHINE"-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configure will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos"$UNAME_RELEASE" + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos"$UNAME_RELEASE" + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos"$UNAME_RELEASE" + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos"$UNAME_RELEASE" + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv"$UNAME_RELEASE" + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo "$UNAME_MACHINE"-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo "$UNAME_MACHINE"-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux"$UNAME_RELEASE" + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv"$UNAME_RELEASE" + else + echo mips-unknown-sysv"$UNAME_RELEASE" + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux"$UNAME_RELEASE" + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux"$UNAME_RELEASE" + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux"$UNAME_RELEASE" + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux"$UNAME_RELEASE" + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux"$UNAME_RELEASE" + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux"$UNAME_RELEASE" + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux"$UNAME_RELEASE" + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody"$UNAME_RELEASE" + exit ;; + *:Rhapsody:*:*) + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval "$set_cc_for_build" + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = x86; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk"$UNAME_RELEASE" + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = 386; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo "$UNAME_MACHINE"-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux"$UNAME_RELEASE" + exit ;; + *:DragonFly:*:*) + echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "$UNAME_MACHINE" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" + exit ;; + i*86:rdos:*:*) + echo "$UNAME_MACHINE"-pc-rdos + exit ;; + i*86:AROS:*:*) + echo "$UNAME_MACHINE"-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo "$UNAME_MACHINE"-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs + exit ;; +esac + +echo "$0: unable to guess system type" >&2 + +case "$UNAME_MACHINE:$UNAME_SYSTEM" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <<EOF + +NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize +the system type. Please install a C compiler and try again. +EOF + ;; +esac + +cat >&2 <<EOF + +This script (version $timestamp), has failed to recognize the +operating system you are using. If your script is old, overwrite *all* +copies of config.guess and config.sub with the latest versions from: + + https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +and + https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + +If $0 has already been updated, send the following data and any +information you think might be pertinent to config-patches@gnu.org to +provide the necessary information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-functions 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/pigeonhole/config.rpath b/pigeonhole/config.rpath new file mode 100755 index 0000000..24be79c --- /dev/null +++ b/pigeonhole/config.rpath @@ -0,0 +1,684 @@ +#! /bin/sh +# Output a system dependent set of variables, describing how to set the +# run time search path of shared libraries in an executable. +# +# Copyright 1996-2020 Free Software Foundation, Inc. +# Taken from GNU libtool, 2001 +# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# The first argument passed to this file is the canonical host specification, +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld +# should be set by the caller. +# +# The set of defined variables is at the end of this script. + +# Known limitations: +# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer +# than 256 bytes, otherwise the compiler driver will dump core. The only +# known workaround is to choose shorter directory names for the build +# directory and/or the installation directory. + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +shrext=.so + +host="$1" +host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + +# Code taken from libtool.m4's _LT_CC_BASENAME. + +for cc_temp in $CC""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` + +# Code taken from libtool.m4's _LT_COMPILER_PIC. + +wl= +if test "$GCC" = yes; then + wl='-Wl,' +else + case "$host_os" in + aix*) + wl='-Wl,' + ;; + mingw* | cygwin* | pw32* | os2* | cegcc*) + ;; + hpux9* | hpux10* | hpux11*) + wl='-Wl,' + ;; + irix5* | irix6* | nonstopux*) + wl='-Wl,' + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + ecc*) + wl='-Wl,' + ;; + icc* | ifort*) + wl='-Wl,' + ;; + lf95*) + wl='-Wl,' + ;; + nagfor*) + wl='-Wl,-Wl,,' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + wl='-Wl,' + ;; + ccc*) + wl='-Wl,' + ;; + xl* | bgxl* | bgf* | mpixl*) + wl='-Wl,' + ;; + como) + wl='-lopt=' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ F* | *Sun*Fortran*) + wl= + ;; + *Sun\ C*) + wl='-Wl,' + ;; + esac + ;; + esac + ;; + newsos6) + ;; + *nto* | *qnx*) + ;; + osf3* | osf4* | osf5*) + wl='-Wl,' + ;; + rdos*) + ;; + solaris*) + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + wl='-Qoption ld ' + ;; + *) + wl='-Wl,' + ;; + esac + ;; + sunos4*) + wl='-Qoption ld ' + ;; + sysv4 | sysv4.2uw2* | sysv4.3*) + wl='-Wl,' + ;; + sysv4*MP*) + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + wl='-Wl,' + ;; + unicos*) + wl='-Wl,' + ;; + uts4*) + ;; + esac +fi + +# Code taken from libtool.m4's _LT_LINKER_SHLIBS. + +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no + +case "$host_os" in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes; then + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + # Unlike libtool, we use -rpath here, not --rpath, since the documented + # option of GNU ld is called -rpath, not --rpath. + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + case "$host_os" in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + fi + ;; + amigaos*) + case "$host_cpu" in + powerpc) + ;; + m68k) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + cygwin* | mingw* | pw32* | cegcc*) + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + haiku*) + ;; + interix[3-9]*) + hardcode_direct=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + netbsd*) + ;; + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + else + ld_shlibs=no + fi + ;; + esac + ;; + sunos4*) + hardcode_direct=yes + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + esac + if test "$ld_shlibs" = no; then + hardcode_libdir_flag_spec= + fi +else + case "$host_os" in + aix3*) + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + else + aix_use_runtimelinking=no + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + fi + hardcode_direct=yes + hardcode_libdir_separator=':' + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + fi + # Begin _LT_AC_SYS_LIBPATH_AIX. + echo 'int main () { return 0; }' > conftest.c + ${CC} ${LDFLAGS} conftest.c -o conftest + aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` + if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` + fi + if test -z "$aix_libpath"; then + aix_libpath="/usr/lib:/lib" + fi + rm -f conftest.c conftest + # End _LT_AC_SYS_LIBPATH_AIX. + if test "$aix_use_runtimelinking" = yes; then + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + else + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + fi + fi + ;; + amigaos*) + case "$host_cpu" in + powerpc) + ;; + m68k) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + bsdi[45]*) + ;; + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + libext=lib + ;; + darwin* | rhapsody*) + hardcode_direct=no + if { case $cc_basename in ifort*) true;; *) test "$GCC" = yes;; esac; }; then + : + else + ld_shlibs=no + fi + ;; + dgux*) + hardcode_libdir_flag_spec='-L$libdir' + ;; + freebsd2.[01]*) + hardcode_direct=yes + hardcode_minus_L=yes + ;; + freebsd* | dragonfly*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + hpux9*) + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + hpux10*) + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + hpux11*) + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + ;; + *) + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + irix5* | irix6* | nonstopux*) + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + netbsd*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + newsos6) + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + *nto* | *qnx*) + ;; + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + else + case "$host_os" in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + osf3*) + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + osf4* | osf5*) + if test "$GCC" = yes; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + # Both cc and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + hardcode_libdir_separator=: + ;; + solaris*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + sunos4*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + ;; + sysv4) + case $host_vendor in + sni) + hardcode_direct=yes # is this really true??? + ;; + siemens) + hardcode_direct=no + ;; + motorola) + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + ;; + sysv4.3*) + ;; + sysv4*MP*) + if test -d /usr/nec; then + ld_shlibs=yes + fi + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + ;; + sysv5* | sco3.2v5* | sco5v6*) + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator=':' + ;; + uts4*) + hardcode_libdir_flag_spec='-L$libdir' + ;; + *) + ld_shlibs=no + ;; + esac +fi + +# Check dynamic linker characteristics +# Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER. +# Unlike libtool.m4, here we don't care about _all_ names of the library, but +# only about the one the linker finds when passed -lNAME. This is the last +# element of library_names_spec in libtool.m4, or possibly two of them if the +# linker has special search rules. +library_names_spec= # the last element of library_names_spec in libtool.m4 +libname_spec='lib$name' +case "$host_os" in + aix3*) + library_names_spec='$libname.a' + ;; + aix[4-9]*) + library_names_spec='$libname$shrext' + ;; + amigaos*) + case "$host_cpu" in + powerpc*) + library_names_spec='$libname$shrext' ;; + m68k) + library_names_spec='$libname.a' ;; + esac + ;; + beos*) + library_names_spec='$libname$shrext' + ;; + bsdi[45]*) + library_names_spec='$libname$shrext' + ;; + cygwin* | mingw* | pw32* | cegcc*) + shrext=.dll + library_names_spec='$libname.dll.a $libname.lib' + ;; + darwin* | rhapsody*) + shrext=.dylib + library_names_spec='$libname$shrext' + ;; + dgux*) + library_names_spec='$libname$shrext' + ;; + freebsd[23].*) + library_names_spec='$libname$shrext$versuffix' + ;; + freebsd* | dragonfly*) + library_names_spec='$libname$shrext' + ;; + gnu*) + library_names_spec='$libname$shrext' + ;; + haiku*) + library_names_spec='$libname$shrext' + ;; + hpux9* | hpux10* | hpux11*) + case $host_cpu in + ia64*) + shrext=.so + ;; + hppa*64*) + shrext=.sl + ;; + *) + shrext=.sl + ;; + esac + library_names_spec='$libname$shrext' + ;; + interix[3-9]*) + library_names_spec='$libname$shrext' + ;; + irix5* | irix6* | nonstopux*) + library_names_spec='$libname$shrext' + case "$host_os" in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; + *) libsuff= shlibsuff= ;; + esac + ;; + esac + ;; + linux*oldld* | linux*aout* | linux*coff*) + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + library_names_spec='$libname$shrext' + ;; + knetbsd*-gnu) + library_names_spec='$libname$shrext' + ;; + netbsd*) + library_names_spec='$libname$shrext' + ;; + newsos6) + library_names_spec='$libname$shrext' + ;; + *nto* | *qnx*) + library_names_spec='$libname$shrext' + ;; + openbsd*) + library_names_spec='$libname$shrext$versuffix' + ;; + os2*) + libname_spec='$name' + shrext=.dll + library_names_spec='$libname.a' + ;; + osf3* | osf4* | osf5*) + library_names_spec='$libname$shrext' + ;; + rdos*) + ;; + solaris*) + library_names_spec='$libname$shrext' + ;; + sunos4*) + library_names_spec='$libname$shrext$versuffix' + ;; + sysv4 | sysv4.3*) + library_names_spec='$libname$shrext' + ;; + sysv4*MP*) + library_names_spec='$libname$shrext' + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + library_names_spec='$libname$shrext' + ;; + tpf*) + library_names_spec='$libname$shrext' + ;; + uts4*) + library_names_spec='$libname$shrext' + ;; +esac + +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' +escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` +shlibext=`echo "$shrext" | sed -e 's,^\.,,'` +escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` +escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` +escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` + +LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF + +# How to pass a linker flag through the compiler. +wl="$escaped_wl" + +# Static library suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally "so"). +shlibext="$shlibext" + +# Format of library name prefix. +libname_spec="$escaped_libname_spec" + +# Library names that the linker finds when passed -lNAME. +library_names_spec="$escaped_library_names_spec" + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec" + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator="$hardcode_libdir_separator" + +# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the +# resulting binary. +hardcode_direct="$hardcode_direct" + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L="$hardcode_minus_L" + +EOF diff --git a/pigeonhole/config.sub b/pigeonhole/config.sub new file mode 100755 index 0000000..1d8e98b --- /dev/null +++ b/pigeonhole/config.sub @@ -0,0 +1,1801 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2018 Free Software Foundation, Inc. + +timestamp='2018-02-22' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <https://www.gnu.org/licenses/>. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to <config-patches@gnu.org>. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS + +Canonicalize a configuration name. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2018 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo "$1" + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo "$1" | sed 's/-[^-]*$//'` + if [ "$basic_machine" != "$1" ] + then os=`echo "$1" | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | ba \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | wasm32 \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | ba-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | e2k-* | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ + | pyramid-* \ + | riscv32-* | riscv64-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | wasm32-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-pc + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + asmjs) + basic_machine=asmjs-unknown + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2*) + basic_machine=m68k-bull + os=-sysv3 + ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=$os"spe" + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=-linux + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + nsv-tandem) + basic_machine=nsv-tandem + ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + x64) + basic_machine=x86_64-pc + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases that might get confused + # with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # es1800 is here to avoid being matched by es* (a different OS) + -es1800*) + os=-ose + ;; + # Now accept the basic system types. + # The portable systems comes first. + # Each alternative MUST end in a * to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ + | -midnightbsd*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -xray | -os68k* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo "$os" | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4*) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=-eabi + ;; + *) + os=-elf + ;; + esac + ;; + -nacl*) + ;; + -ios) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + pru-*) + os=-elf + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` + ;; +esac + +echo "$basic_machine$os" +exit + +# Local variables: +# eval: (add-hook 'write-file-functions 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/pigeonhole/configure b/pigeonhole/configure new file mode 100755 index 0000000..7c1f0ff --- /dev/null +++ b/pigeonhole/configure @@ -0,0 +1,16069 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for Pigeonhole 0.5.21. +# +# Report bugs to <dovecot@dovecot.org>. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: dovecot@dovecot.org about your system, including any +$0: error possibly output before this message. Then install +$0: a modern shell, or manually run the script under such a +$0: shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 </dev/null +exec 6>&1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='Pigeonhole' +PACKAGE_TARNAME='dovecot-2.3-pigeonhole' +PACKAGE_VERSION='0.5.21' +PACKAGE_STRING='Pigeonhole 0.5.21' +PACKAGE_BUGREPORT='dovecot@dovecot.org' +PACKAGE_URL='' + +ac_unique_file="src" +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +LDAP_PLUGIN_FALSE +LDAP_PLUGIN_TRUE +LDAP_LIBS +BUILD_MANAGESIEVE_FALSE +BUILD_MANAGESIEVE_TRUE +BUILD_DOCS_FALSE +BUILD_DOCS_TRUE +BUILD_UNFINISHED_FALSE +BUILD_UNFINISHED_TRUE +sieve_docdir +BINARY_LDFLAGS +BINARY_CFLAGS +moduledir +RUN_TEST +VALGRIND +DOVECOT_PLUGIN_DEPS_FALSE +DOVECOT_PLUGIN_DEPS_TRUE +DOVECOT_INSTALLED_FALSE +DOVECOT_INSTALLED_TRUE +LIBDOVECOT_LUA_DEPS +LIBDOVECOT_LUA +DOVECOT_LUA_CFLAGS +DOVECOT_LUA_LIBS +LIBDOVECOT_LUA_INCLUDE +LIBDOVECOT_LIBFTS_INCLUDE +LIBDOVECOT_ACL_INCLUDE +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE +LIBDOVECOT_NOTIFY_INCLUDE +LIBDOVECOT_FTS_INCLUDE +LIBDOVECOT_IMAPC_INCLUDE +LIBDOVECOT_DSYNC_INCLUDE +LIBDOVECOT_LMTP_INCLUDE +LIBDOVECOT_SUBMISSION_INCLUDE +LIBDOVECOT_POP3_INCLUDE +LIBDOVECOT_IMAP_INCLUDE +LIBDOVECOT_CONFIG_INCLUDE +LIBDOVECOT_IMAP_LOGIN_INCLUDE +LIBDOVECOT_SQL_INCLUDE +LIBDOVECOT_LOGIN_INCLUDE +LIBDOVECOT_STORAGE_INCLUDE +LIBDOVECOT_SERVICE_INCLUDE +LIBDOVECOT_DOVEADM_INCLUDE +LIBDOVECOT_AUTH_INCLUDE +LIBDOVECOT_LDA_INCLUDE +LIBDOVECOT_INCLUDE +LIBDOVECOT_LIBFTS_DEPS +LIBDOVECOT_DSYNC_DEPS +LIBDOVECOT_STORAGE_DEPS +LIBDOVECOT_LDA_DEPS +LIBDOVECOT_COMPRESS_DEPS +LIBDOVECOT_SSL_DEPS +LIBDOVECOT_SQL_DEPS +LIBDOVECOT_LOGIN_DEPS +LIBDOVECOT_DEPS +LIBDOVECOT_LIBFTS +LIBDOVECOT_DSYNC +LIBDOVECOT_STORAGE +LIBDOVECOT_LDA +LIBDOVECOT_COMPRESS +LIBDOVECOT_SSL +LIBDOVECOT_SQL +LIBDOVECOT_LOGIN +LIBDOVECOT +DOVECOT_BINARY_LDFLAGS +DOVECOT_BINARY_CFLAGS +DOVECOT_COMPRESS_LIBS +DOVECOT_SQL_LIBS +DOVECOT_SSL_LIBS +DOVECOT_LIBS +DOVECOT_CFLAGS +DOVECOT_INSTALLED +dovecot_statedir +dovecot_docdir +dovecot_pkglibdir +dovecot_pkglibexecdir +dovecot_pkgincludedir +dovecot_installed_moduledir +dovecot_moduledir +dovecotdir +DISTCHECK_CONFIGURE_FLAGS +RELRO_LDFLAGS +PIE_LDFLAGS +PIE_CFLAGS +LT_SYS_LIBRARY_PATH +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +RANLIB +ac_ct_AR +AR +DLLTOOL +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +EGREP +GREP +SED +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +LIBTOOL +CPP +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +MAINT +MAINTAINER_MODE_FALSE +MAINTAINER_MODE_TRUE +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +runstatedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL +am__quote' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_silent_rules +enable_maintainer_mode +enable_dependency_tracking +enable_shared +enable_static +with_pic +enable_fast_install +with_aix_soname +with_gnu_ld +with_sysroot +enable_libtool_lock +with_dovecot +with_dovecot_install_dirs +enable_hardening +with_retpoline +enable_ubsan +with_moduledir +with_unfinished_features +with_docs +with_managesieve +with_ldap +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +LT_SYS_LIBRARY_PATH +VALGRIND' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir runstatedir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures Pigeonhole 0.5.21 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root + [DATAROOTDIR/doc/dovecot-2.3-pigeonhole] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of Pigeonhole 0.5.21:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --enable-maintainer-mode + enable make rules and dependencies not useful (and + sometimes confusing) to the casual installer + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --enable-hardening=yes Enable various hardenings (default: yes) + --enable-ubsan Enable undefined behaviour sanitizes (default=no) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + both] + --with-aix-soname=aix|svr4|both + shared library versioning (aka "SONAME") variant to + provide on AIX, [default=aix]. + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot[=DIR] Search for dependent libraries within DIR (or the + compiler's sysroot if not specified). + --with-dovecot=DIR Dovecot base directory + --with-dovecot-install-dirs + Use install directories configured for Dovecot + (default) + --with-retpoline=<choice> + Retpoline mitigation choice (default: keep) + --with-moduledir=DIR Base directory for dynamically loadable modules + --with-unfinished-features + Build unfinished new features/extensions + [default=no] + --with-docs Install documentation (default) + --with-managesieve Build ManageSieve service [default=yes] + --with-ldap=yes|plugin Build with LDAP support + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + LIBS libraries to pass to the linker, e.g. -l<library> + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if + you have headers in a nonstandard directory <include dir> + CPP C preprocessor + LT_SYS_LIBRARY_PATH + User-defined run-time library search path. + VALGRIND Path to valgrind + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to <dovecot@dovecot.org>. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +Pigeonhole configure 0.5.21 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case <limits.h> declares $2. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ---------------------------------- ## +## Report this to dovecot@dovecot.org ## +## ---------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by Pigeonhole $as_me 0.5.21, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +cat >>confdefs.h <<_ACEOF +#define PIGEONHOLE_ABI_VERSION "0.5.ABIv21($PACKAGE_VERSION)" +_ACEOF + + +ac_aux_dir= +for ac_dir in . "$srcdir"/.; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in . \"$srcdir\"/." "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + + + +# Autoheader is not needed and does more harm than good for this package. However, it is +# tightly integrated in autoconf/automake and therefore it is difficult not to use it. As +# a workaround we give autoheader a dummy config header to chew on and we handle the +# real config header ourselves. +ac_config_headers="$ac_config_headers dummy-config.h pigeonhole-config.h" + + + +cat >>confdefs.h <<_ACEOF +#define PIGEONHOLE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PIGEONHOLE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +am__api_version='1.16' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + +if test x"${MISSING+set}" != xset; then + MISSING="\${SHELL} '$am_aux_dir/missing'" +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='dovecot-2.3-pigeonhole' + VERSION='0.5.21' + + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> +# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar plaintar pax cpio none' + +# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether UID '$am_uid' is supported by ustar format" >&5 +$as_echo_n "checking whether UID '$am_uid' is supported by ustar format... " >&6; } + if test $am_uid -le $am_max_uid; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + _am_tools=none + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GID '$am_gid' is supported by ustar format" >&5 +$as_echo_n "checking whether GID '$am_gid' is supported by ustar format... " >&6; } + if test $am_gid -le $am_max_gid; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + _am_tools=none + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a ustar tar archive" >&5 +$as_echo_n "checking how to create a ustar tar archive... " >&6; } + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_ustar-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + { echo "$as_me:$LINENO: $_am_tar --version" >&5 + ($_am_tar --version) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && break + done + am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=ustar -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x ustar -w "$$tardir"' + am__tar_='pax -L -x ustar -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H ustar -L' + am__tar_='find "$tardir" -print | cpio -o -H ustar -L' + am__untar='cpio -i -H ustar -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_ustar}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5 + (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + rm -rf conftest.dir + if test -s conftest.tar; then + { echo "$as_me:$LINENO: $am__untar <conftest.tar" >&5 + ($am__untar <conftest.tar) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + { echo "$as_me:$LINENO: cat conftest.dir/file" >&5 + (cat conftest.dir/file) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + grep GrepMe conftest.dir/file >/dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + if ${am_cv_prog_tar_ustar+:} false; then : + $as_echo_n "(cached) " >&6 +else + am_cv_prog_tar_ustar=$_am_tool +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_ustar" >&5 +$as_echo "$am_cv_prog_tar_ustar" >&6; } + + + + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542> + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: <https://www.gnu.org/software/coreutils/>. + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 +$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } + # Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then : + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 +$as_echo "$USE_MAINTAINER_MODE" >&6; } + if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + + MAINT=$MAINTAINER_MODE_TRUE + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdio.h> +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 +$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; } +cat > confinc.mk << 'END' +am__doit: + @echo this is the am__doit target >confinc.out +.PHONY: am__doit +END +am__include="#" +am__quote= +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 + (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + case $?:`cat confinc.out 2>/dev/null` in #( + '0:this is the am__doit target') : + case $s in #( + BSD) : + am__include='.include' am__quote='"' ;; #( + *) : + am__include='include' am__quote='' ;; +esac ;; #( + *) : + ;; +esac + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 +$as_echo "${_am_result}" >&6; } + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.6' +macro_revision='2.4.6' + + + + + + + + + + + + + +ltmain=$ac_aux_dir/ltmain.sh + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case $ECHO in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in + *GNU* | *'with BFD'*) + test no != "$with_gnu_ld" && break + ;; + *) + test yes != "$with_gnu_ld" && break + ;; + esac + fi + done + IFS=$lt_save_ifs +else + lt_cv_path_LD=$LD # Let the user override the test with a path. +fi +fi + +LD=$lt_cv_path_LD +if test -n "$LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) + lt_cv_prog_gnu_ld=yes + ;; +*) + lt_cv_prog_gnu_ld=no + ;; +esac +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n "$lt_cv_sys_max_cmd_len"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test yes != "$GCC"; then + reload_cmds=false + fi + ;; + darwin*) + if test yes = "$GCC"; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cr} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&5 + if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&5 && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 +$as_echo "$with_sysroot" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 +$as_echo_n "checking for a working dd... " >&6; } +if ${ac_cv_path_lt_DD+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +if test -z "$lt_DD"; then + ac_path_lt_DD_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in dd; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_lt_DD" || continue +if "$ac_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi + $ac_path_lt_DD_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_lt_DD"; then + : + fi +else + ac_cv_path_lt_DD=$lt_DD +fi + +rm -f conftest.i conftest2.i conftest.out +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 +$as_echo "$ac_cv_path_lt_DD" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 +$as_echo_n "checking how to truncate binary pipes... " >&6; } +if ${lt_cv_truncate_bin+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 +$as_echo "$lt_cv_truncate_bin" >&6; } + + + + + + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cr libconftest.a conftest.o" >&5 + $AR cr libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[912]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[012][,.]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*|11.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ctype.h> +#include <stdlib.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + +# Set options + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + # Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_static=yes +fi + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + pic_mode=default +fi + + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[5-9]*,yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 +$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } + +# Check whether --with-aix-soname was given. +if test "${with_aix_soname+set}" = set; then : + withval=$with_aix_soname; case $withval in + aix|svr4|both) + ;; + *) + as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname +else + if ${lt_cv_with_aix_soname+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_with_aix_soname=aix +fi + + with_aix_soname=$lt_cv_with_aix_soname +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 +$as_echo "$with_aix_soname" >&6; } + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +func_cc_basename $compiler +cc_basename=$func_cc_basename_result + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/${ac_tool_prefix}file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC=$CC +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test yes = "$GCC"; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + lt_prog_compiler_pic='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # flang / f18. f95 an alias for gfortran or flang on Debian + flang* | f18* | f95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_pic_works"; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_static_works"; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu | gnu*) + link_all_deplibs=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + export_dynamic_flag_spec='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='$wl--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + export_dynamic_flag_spec='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test no = "$ld_shlibs"; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct=no + hardcode_direct_absolute=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + export_dynamic_flag_spec='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' $wl-bernotok' + allow_undefined_flag=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test yes = "$GCC"; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test yes = "$lt_cv_prog_compiler__b"; then + archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test yes = "$lt_cv_irix_exported_symbol"; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + link_all_deplibs=no + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + ld_shlibs=yes + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + else + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + osf3*) + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='$wl-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='$wl-z,text' + allow_undefined_flag='$wl-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='$wl-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test no = "$ld_shlibs" && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([A-Za-z]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + + + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib<name>.so + # instead of lib<name>.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test yes = "$hardcode_automatic"; then + + # We can hardcode non-existent directories. + if test no != "$hardcode_direct" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && + test no != "$hardcode_minus_L"; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test relink = "$hardcode_action" || + test yes = "$inherit_rpath"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen=shl_load +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen=dlopen +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report what library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC=$lt_save_CC + + + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + + +# Couple with Dovecot +# + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -Werror -Wunknown-warning-option" >&5 +$as_echo_n "checking whether C compiler handles -Werror -Wunknown-warning-option... " >&6; } +if ${gl_cv_warn_c__Werror__Wunknown_warning_option+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -Werror -Wunknown-warning-option" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__Werror__Wunknown_warning_option=yes +else + gl_cv_warn_c__Werror__Wunknown_warning_option=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__Werror__Wunknown_warning_option" >&5 +$as_echo "$gl_cv_warn_c__Werror__Wunknown_warning_option" >&6; } +if test "x$gl_cv_warn_c__Werror__Wunknown_warning_option" = xyes; then : + gl_unknown_warnings_are_errors='-Wunknown-warning-option -Werror' +else + gl_unknown_warnings_are_errors= +fi + + + +# Check whether --with-dovecot was given. +if test "${with_dovecot+set}" = set; then : + withval=$with_dovecot; dovecotdir="$withval" +else + + dc_prefix=$prefix + test "x$dc_prefix" = xNONE && dc_prefix=$ac_default_prefix + dovecotdir="$dc_prefix/lib/dovecot" + + +fi + + + +# Check whether --with-dovecot-install-dirs was given. +if test "${with_dovecot_install_dirs+set}" = set; then : + withval=$with_dovecot_install_dirs; if test x$withval = xno; then : + + use_install_dirs=no + +else + + use_install_dirs=yes + +fi +else + use_install_dirs=yes +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for \"$dovecotdir/dovecot-config\"" >&5 +$as_echo_n "checking for \"$dovecotdir/dovecot-config\"... " >&6; } + if test -f "$dovecotdir/dovecot-config"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dovecotdir/dovecot-config" >&5 +$as_echo "$dovecotdir/dovecot-config" >&6; } + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: " >&5 +$as_echo "$as_me: " >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: Use --with-dovecot=DIR to provide the path to the dovecot-config file." >&5 +$as_echo "$as_me: Use --with-dovecot=DIR to provide the path to the dovecot-config file." >&6;} + as_fn_error $? "dovecot-config not found" "$LINENO" 5 + +fi + + old=`pwd` + cd $dovecotdir + abs_dovecotdir=`pwd` + cd $old + DISTCHECK_CONFIGURE_FLAGS="--with-dovecot=$abs_dovecotdir --without-dovecot-install-dirs" + + ORIG_CFLAGS="$CFLAGS" + ORIG_LDFLAGS="$LDFLAGS" + ORIG_BINARY_CFLAGS="$BINARY_CFLAGS" + ORIG_BINARY_LDFLAGS="$BINARY_LDFLAGS" + + eval `grep -i '^dovecot_[a-z_]*=' "$dovecotdir"/dovecot-config` + eval `grep '^LIBDOVECOT[A-Z0-9_]*=' "$dovecotdir"/dovecot-config` + + CFLAGS="$ORIG_CFLAGS" + LDFLAGS="$ORIG_LDFLAGS" + BINARY_CFLAGS="$ORIG_BINARY_CFLAGS" + BINARY_LDFLAGS="$ORIG_BINARY_LDFLAGS" + + dovecot_installed_moduledir="$dovecot_moduledir" + + if test "$use_install_dirs" = "no"; then : + + dovecot_pkgincludedir='$(pkgincludedir)' + dovecot_pkglibdir='$(pkglibdir)' + dovecot_pkglibexecdir='$(libexecdir)/dovecot' + dovecot_docdir='$(docdir)' + dovecot_moduledir='$(moduledir)' + dovecot_statedir='$(statedir)' + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC is clang 3.3+" >&5 +$as_echo_n "checking whether $CC is clang 3.3+... " >&6; } + if $CC -dM -E -x c /dev/null | grep __clang__ > /dev/null 2>&1; then : + + have_clang=yes + +else + + have_clang=no + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_clang" >&5 +$as_echo "$have_clang" >&6; } + + + if test "x$ac_cv_c_compiler_gnu" = "xyes"; then : + + CFLAGS="$CFLAGS -Wall -W -Wmissing-prototypes -Wmissing-declarations -Wpointer-arith -Wchar-subscripts -Wformat=2 -Wbad-function-cast" + + if test "$have_clang" = "yes"; then : + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 3) + # error new clang + #endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + + CFLAGS="$CFLAGS -Wno-duplicate-decl-specifier" + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +else + + CFLAGS="$CFLAGS -fno-builtin-strftime" + +fi + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #if __GNUC__ < 4 + # error old gcc + #endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + CFLAGS="$CFLAGS -Wstrict-aliasing=2" + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + old_cflags=$CFLAGS + CFLAGS="-std=gnu99" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + CFLAGS="$CFLAGS $old_cflags" + +else + + CFLAGS="$old_cflags" + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + +fi + + + # Check whether --enable-hardening was given. +if test "${enable_hardening+set}" = set; then : + enableval=$enable_hardening; enable_hardening=$enableval +else + enable_hardening=yes +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking Whether to enable hardening" >&5 +$as_echo_n "checking Whether to enable hardening... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_hardening" >&5 +$as_echo "$enable_hardening" >&6; } + + + + PIE_CFLAGS= + PIE_LDFLAGS= + + if test "$enable_hardening" = yes; then : + + OLD_CFLAGS=$CFLAGS + case "$host" in + *-*-mingw* | *-*-msvc* | *-*-cygwin* ) + ;; *) + CFLAGS="-fPIE -DPIE" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -pie" >&5 +$as_echo_n "checking whether C compiler handles -pie... " >&6; } +if ${gl_cv_warn_c__pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -pie" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__pie=yes +else + gl_cv_warn_c__pie=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__pie" >&5 +$as_echo "$gl_cv_warn_c__pie" >&6; } +if test "x$gl_cv_warn_c__pie" = xyes; then : + + PIE_CFLAGS="-fPIE -DPIE" + PIE_LDFLAGS="-pie" + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -Wl,-pie" >&5 +$as_echo_n "checking whether C compiler handles -Wl,-pie... " >&6; } +if ${gl_cv_warn_c__Wl__pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -Wl,-pie" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__Wl__pie=yes +else + gl_cv_warn_c__Wl__pie=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__Wl__pie" >&5 +$as_echo "$gl_cv_warn_c__Wl__pie" >&6; } +if test "x$gl_cv_warn_c__Wl__pie" = xyes; then : + + PIE_CFLAGS="-fPIE -DPIE" + PIE_LDFLAGS="-Wl,-pie" + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5 +$as_echo "not supported" >&6; } +fi + + +fi + + esac + CFLAGS=$OLD_CFLAGS + +fi + + + + + + if test "$enable_hardening" = yes; then : + + case "$host" in + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -fstack-protector-strong" >&5 +$as_echo_n "checking whether C compiler handles -fstack-protector-strong... " >&6; } +if ${gl_cv_warn_c__fstack_protector_strong+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -fstack-protector-strong" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__fstack_protector_strong=yes +else + gl_cv_warn_c__fstack_protector_strong=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__fstack_protector_strong" >&5 +$as_echo "$gl_cv_warn_c__fstack_protector_strong" >&6; } +if test "x$gl_cv_warn_c__fstack_protector_strong" = xyes; then : + + CFLAGS="$CFLAGS -fstack-protector-strong" + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -fstack-protector" >&5 +$as_echo_n "checking whether C compiler handles -fstack-protector... " >&6; } +if ${gl_cv_warn_c__fstack_protector+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -fstack-protector" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__fstack_protector=yes +else + gl_cv_warn_c__fstack_protector=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__fstack_protector" >&5 +$as_echo "$gl_cv_warn_c__fstack_protector" >&6; } +if test "x$gl_cv_warn_c__fstack_protector" = xyes; then : + + CFLAGS="$CFLAGS -fstack-protector" + +fi + + +fi + + esac + +fi + + + + if test "$enable_hardening" = yes; then : + + case "$host" in + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2" >&5 +$as_echo_n "checking whether C compiler handles -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2... " >&6; } +if ${gl_cv_warn_c__O2__U_FORTIFY_SOURCE__D_FORTIFY_SOURCE_2+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__O2__U_FORTIFY_SOURCE__D_FORTIFY_SOURCE_2=yes +else + gl_cv_warn_c__O2__U_FORTIFY_SOURCE__D_FORTIFY_SOURCE_2=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__O2__U_FORTIFY_SOURCE__D_FORTIFY_SOURCE_2" >&5 +$as_echo "$gl_cv_warn_c__O2__U_FORTIFY_SOURCE__D_FORTIFY_SOURCE_2" >&6; } +if test "x$gl_cv_warn_c__O2__U_FORTIFY_SOURCE__D_FORTIFY_SOURCE_2" = xyes; then : + + CFLAGS="$CFLAGS -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2" + +fi + + esac + +fi + + + +# Check whether --with-retpoline was given. +if test "${with_retpoline+set}" = set; then : + withval=$with_retpoline; with_retpoline=$withval +else + with_retpoline=keep +fi + + + + if test "$enable_hardening" = yes; then : + + case "$host" in + *) + as_gl_Warn=`$as_echo "gl_cv_warn_c_-mfunction-return=$with_retpoline" | $as_tr_sh` +gl_positive="-mfunction-return=$with_retpoline" +case $gl_positive in + -Wno-*) gl_positive=-W`expr "X$gl_positive" : 'X-Wno-\(.*\)'` ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -mfunction-return=$with_retpoline" >&5 +$as_echo_n "checking whether C compiler handles -mfunction-return=$with_retpoline... " >&6; } +if eval \${$as_gl_Warn+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors $gl_positive" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_gl_Warn=yes" +else + eval "$as_gl_Warn=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +eval ac_res=\$$as_gl_Warn + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_gl_Warn"\" = x"yes"; then : + CFLAGS="$CFLAGS -mfunction-return=$with_retpoline" +fi + + as_gl_Warn=`$as_echo "gl_cv_warn_c_-mindirect-branch=$with_retpoline" | $as_tr_sh` +gl_positive="-mindirect-branch=$with_retpoline" +case $gl_positive in + -Wno-*) gl_positive=-W`expr "X$gl_positive" : 'X-Wno-\(.*\)'` ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -mindirect-branch=$with_retpoline" >&5 +$as_echo_n "checking whether C compiler handles -mindirect-branch=$with_retpoline... " >&6; } +if eval \${$as_gl_Warn+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors $gl_positive" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_gl_Warn=yes" +else + eval "$as_gl_Warn=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +eval ac_res=\$$as_gl_Warn + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_gl_Warn"\" = x"yes"; then : + + CFLAGS="$CFLAGS -mindirect-branch=$with_retpoline" + +fi + + esac + +fi + + + RELRO_LDFLAGS= + if test "$enable_hardening" = yes; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for how to force completely read-only GOT table" >&5 +$as_echo_n "checking for how to force completely read-only GOT table... " >&6; } + ld_help=`$CC -Wl,-help 2>&1` + case $ld_help in + *"-z relro"*) RELRO_LDFLAGS="-Wl,-z -Wl,relro" ;; + esac + case $ld_help in + *"-z now"*) RELRO_LDFLAGS="$RELRO_LDFLAGS -Wl,-z -Wl,now" ;; + esac + if test "x$RELRO_LDFLAGS" != "x"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RELRO_LDFLAGS" >&5 +$as_echo "$RELRO_LDFLAGS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unknown" >&5 +$as_echo "unknown" >&6; } + +fi + +fi + + + + # Check whether --enable-ubsan was given. +if test "${enable_ubsan+set}" = set; then : + enableval=$enable_ubsan; want_ubsan=yes +else + want_ubsan=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we want undefined behaviour sanitizer" >&5 +$as_echo_n "checking whether we want undefined behaviour sanitizer... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $want_ubsan" >&5 +$as_echo "$want_ubsan" >&6; } + if test x$want_ubsan = xyes; then : + + san_flags="" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -fsanitize=undefined" >&5 +$as_echo_n "checking whether C compiler handles -fsanitize=undefined... " >&6; } +if ${gl_cv_warn_c__fsanitize_undefined+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -fsanitize=undefined" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__fsanitize_undefined=yes +else + gl_cv_warn_c__fsanitize_undefined=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__fsanitize_undefined" >&5 +$as_echo "$gl_cv_warn_c__fsanitize_undefined" >&6; } +if test "x$gl_cv_warn_c__fsanitize_undefined" = xyes; then : + + san_flags="$san_flags -fsanitize=undefined" + +$as_echo "#define HAVE_FSANITIZE_UNDEFINED 1" >>confdefs.h + + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -fno-sanitize=nonnull-attribute" >&5 +$as_echo_n "checking whether C compiler handles -fno-sanitize=nonnull-attribute... " >&6; } +if ${gl_cv_warn_c__fno_sanitize_nonnull_attribute+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -fno-sanitize=nonnull-attribute" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__fno_sanitize_nonnull_attribute=yes +else + gl_cv_warn_c__fno_sanitize_nonnull_attribute=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__fno_sanitize_nonnull_attribute" >&5 +$as_echo "$gl_cv_warn_c__fno_sanitize_nonnull_attribute" >&6; } +if test "x$gl_cv_warn_c__fno_sanitize_nonnull_attribute" = xyes; then : + + san_flags="$san_flags -fno-sanitize=nonnull-attribute" + +$as_echo "#define HAVE_FNO_SANITIZE_NONNULL_ATTRIBUTE 1" >>confdefs.h + + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -fsanitize=implicit-integer-truncation" >&5 +$as_echo_n "checking whether C compiler handles -fsanitize=implicit-integer-truncation... " >&6; } +if ${gl_cv_warn_c__fsanitize_implicit_integer_truncation+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -fsanitize=implicit-integer-truncation" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__fsanitize_implicit_integer_truncation=yes +else + gl_cv_warn_c__fsanitize_implicit_integer_truncation=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__fsanitize_implicit_integer_truncation" >&5 +$as_echo "$gl_cv_warn_c__fsanitize_implicit_integer_truncation" >&6; } +if test "x$gl_cv_warn_c__fsanitize_implicit_integer_truncation" = xyes; then : + + san_flags="$san_flags -fsanitize=implicit-integer-truncation" + +$as_echo "#define HAVE_FSANITIZE_IMPLICIT_INTEGER_TRUNCATION 1" >>confdefs.h + + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -fsanitize=local-bounds" >&5 +$as_echo_n "checking whether C compiler handles -fsanitize=local-bounds... " >&6; } +if ${gl_cv_warn_c__fsanitize_local_bounds+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -fsanitize=local-bounds" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__fsanitize_local_bounds=yes +else + gl_cv_warn_c__fsanitize_local_bounds=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__fsanitize_local_bounds" >&5 +$as_echo "$gl_cv_warn_c__fsanitize_local_bounds" >&6; } +if test "x$gl_cv_warn_c__fsanitize_local_bounds" = xyes; then : + + san_flags="$san_flags -fsanitize=local-bounds" + +$as_echo "#define HAVE_FSANITIZE_LOCAL_BOUNDS 1" >>confdefs.h + + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -fsanitize=integer" >&5 +$as_echo_n "checking whether C compiler handles -fsanitize=integer... " >&6; } +if ${gl_cv_warn_c__fsanitize_integer+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -fsanitize=integer" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__fsanitize_integer=yes +else + gl_cv_warn_c__fsanitize_integer=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__fsanitize_integer" >&5 +$as_echo "$gl_cv_warn_c__fsanitize_integer" >&6; } +if test "x$gl_cv_warn_c__fsanitize_integer" = xyes; then : + + san_flags="$san_flags -fsanitize=integer" + +$as_echo "#define HAVE_FSANITIZE_INTEGER 1" >>confdefs.h + + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -fsanitize=nullability" >&5 +$as_echo_n "checking whether C compiler handles -fsanitize=nullability... " >&6; } +if ${gl_cv_warn_c__fsanitize_nullability+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -fsanitize=nullability" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__fsanitize_nullability=yes +else + gl_cv_warn_c__fsanitize_nullability=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__fsanitize_nullability" >&5 +$as_echo "$gl_cv_warn_c__fsanitize_nullability" >&6; } +if test "x$gl_cv_warn_c__fsanitize_nullability" = xyes; then : + + san_flags="$san_flags -fsanitize=nullability" + +$as_echo "#define HAVE_FSANITIZE_NULLABILITY 1" >>confdefs.h + + +fi + + if test "$san_flags" != "" ; then : + + EXTRA_CFLAGS="$EXTRA_CFLAGS $san_flags -U_FORTIFY_SOURCE -g -ggdb3 -O0 -fno-omit-frame-pointer" + +$as_echo "#define HAVE_UNDEFINED_SANITIZER 1" >>confdefs.h + + +else + + as_fn_error $? "No undefined sanitizer support in your compiler" "$LINENO" 5 + +fi + san_flags="" + +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if test "$DOVECOT_INSTALLED" = "yes"; then + DOVECOT_INSTALLED_TRUE= + DOVECOT_INSTALLED_FALSE='#' +else + DOVECOT_INSTALLED_TRUE='#' + DOVECOT_INSTALLED_FALSE= +fi + + + + _plugin_deps=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OS supports plugin dependencies" >&5 +$as_echo_n "checking whether OS supports plugin dependencies... " >&6; } + case "$host_os" in + darwin*) + _plugin_deps=no + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_plugin_deps" >&5 +$as_echo "$_plugin_deps" >&6; } + if test "x$_plugin_deps" = "xyes"; then + DOVECOT_PLUGIN_DEPS_TRUE= + DOVECOT_PLUGIN_DEPS_FALSE='#' +else + DOVECOT_PLUGIN_DEPS_TRUE='#' + DOVECOT_PLUGIN_DEPS_FALSE= +fi + + unset _plugin_deps + + + + # Extract the first word of "valgrind", so it can be a program name with args. +set dummy valgrind; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_VALGRIND+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $VALGRIND in + [\\/]* | ?:[\\/]*) + ac_cv_path_VALGRIND="$VALGRIND" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_VALGRIND="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_VALGRIND" && ac_cv_path_VALGRIND="reject" + ;; +esac +fi +VALGRIND=$ac_cv_path_VALGRIND +if test -n "$VALGRIND"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $VALGRIND" >&5 +$as_echo "$VALGRIND" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "$VALGRIND" != reject; then : + + cat > run-test.sh <<_DC_EOF +#!/bin/sh +top_srcdir=\$1 +shift + +if test "\$NOUNDEF" != ""; then + noundef="--undef-value-errors=no" +else + noundef="" +fi + +if test "\$NOCHILDREN" != ""; then + trace_children="--trace-children=no" +else + trace_children="--trace-children=yes" +fi + +skip_path="\$top_srcdir/run-test-valgrind.exclude" +if test -r "\$skip_path" && grep -w -q "\$(basename \$1)" "\$skip_path"; then + NOVALGRIND=true +fi + +if test "\$NOVALGRIND" != ""; then + \$* + ret=\$? +else + test_out="test.out~\$\$" + trap "rm -f \$test_out" 0 1 2 3 15 + supp_path="\$top_srcdir/run-test-valgrind.supp" + if test -r "\$supp_path"; then + $VALGRIND -q \$trace_children --error-exitcode=213 --leak-check=full --gen-suppressions=all --suppressions="\$supp_path" --log-file=\$test_out \$noundef \$* + else + $VALGRIND -q \$trace_children --error-exitcode=213 --leak-check=full --gen-suppressions=all --log-file=\$test_out \$noundef \$* + fi + ret=\$? + if test -s \$test_out; then + cat \$test_out + ret=1 + fi +fi +if test \$ret != 0; then + echo "Failed to run: \$*" >&2 +fi +exit \$ret +_DC_EOF + RUN_TEST='$(LIBTOOL) execute $(SHELL) $(top_builddir)/run-test.sh $(top_srcdir)' + +else + + RUN_TEST='' + +fi + + + + + +# Check whether --with-moduledir was given. +if test "${with_moduledir+set}" = set; then : + withval=$with_moduledir; moduledir="$withval" +else + moduledir="$dovecot_moduledir" + +fi + + + +LIBDOVECOT_INCLUDE="$LIBDOVECOT_INCLUDE $LIBDOVECOT_STORAGE_INCLUDE" +CFLAGS="$CFLAGS -I\$(top_srcdir)" +LIBS="$DOVECOT_LIBS" +BINARY_LDFLAGS="$PIE_LDFLAGS $RELRO_LDFLAGS" +BINARY_CFLAGS="$PIE_CFLAGS" + + + + +# Define Sieve documentation install dir +# + +sieve_docdir='${dovecot_docdir}/sieve' + + +# Extensions under development +# + + +# Check whether --with-unfinished-features was given. +if test "${with_unfinished_features+set}" = set; then : + withval=$with_unfinished_features; if test x$withval = xno || test x$withval = xauto; then + want_unfinished_features=$withval + else + want_unfinished_features=yes + fi +else + want_unfinished_features=no +fi + + if test "$want_unfinished_features" = "yes"; then + BUILD_UNFINISHED_TRUE= + BUILD_UNFINISHED_FALSE='#' +else + BUILD_UNFINISHED_TRUE='#' + BUILD_UNFINISHED_FALSE= +fi + + +if test "$want_unfinished_features" = "yes"; then + +$as_echo "#define HAVE_SIEVE_UNFINISHED /**/" >>confdefs.h + +fi + +# +# + + + + +# Check whether --with-docs was given. +if test "${with_docs+set}" = set; then : + withval=$with_docs; if test x$withval = xno; then + want_docs=no + else + want_docs=yes + fi +else + want_docs=yes +fi + + if test "$want_docs" = "yes"; then + BUILD_DOCS_TRUE= + BUILD_DOCS_FALSE='#' +else + BUILD_DOCS_TRUE='#' + BUILD_DOCS_FALSE= +fi + + + +# Check whether --with-managesieve was given. +if test "${with_managesieve+set}" = set; then : + withval=$with_managesieve; if test x$withval = xno || test x$withval = xauto; then + want_managesieve=$withval + else + want_managesieve=yes + fi +else + want_managesieve=yes +fi + + if test "$want_managesieve" = "yes"; then + BUILD_MANAGESIEVE_TRUE= + BUILD_MANAGESIEVE_FALSE='#' +else + BUILD_MANAGESIEVE_TRUE='#' + BUILD_MANAGESIEVE_FALSE= +fi + + + +# Check whether --with-ldap was given. +if test "${with_ldap+set}" = set; then : + withval=$with_ldap; + want=want_`echo ldap|sed s/-/_/g` + if test $withval = yes || test $withval = no || test $withval = auto; then + eval $want=$withval + elif test $withval = plugin; then + if test "plugin" = plugin; then + eval $want=plugin + else + as_fn_error $? "--with-ldap=plugin not supported" "$LINENO" 5 + fi + elif `echo $withval|grep '^/' >/dev/null`; then + as_fn_error $? "--with-ldap=path not supported. You may want to use instead: +CPPFLAGS=-I$withval/include LDFLAGS=-L$withval/lib ./configure --with-ldap" "$LINENO" 5 + else + as_fn_error $? "--with-ldap: Unknown value: $withval" "$LINENO" 5 + fi + +else + want_ldap=no +fi + + +# FIXME: Imported this from Dovecot auth for now. We're working on a proper +# lib-ldap, but, until then, some code is duplicated. +have_ldap=no +if test $want_ldap != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldap_init in -lldap" >&5 +$as_echo_n "checking for ldap_init in -lldap... " >&6; } +if ${ac_cv_lib_ldap_ldap_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lldap $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ldap_init (); +int +main () +{ +return ldap_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ldap_ldap_init=yes +else + ac_cv_lib_ldap_ldap_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldap_ldap_init" >&5 +$as_echo "$ac_cv_lib_ldap_ldap_init" >&6; } +if test "x$ac_cv_lib_ldap_ldap_init" = xyes; then : + + ac_fn_c_check_header_mongrel "$LINENO" "ldap.h" "ac_cv_header_ldap_h" "$ac_includes_default" +if test "x$ac_cv_header_ldap_h" = xyes; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldap_initialize in -lldap" >&5 +$as_echo_n "checking for ldap_initialize in -lldap... " >&6; } +if ${ac_cv_lib_ldap_ldap_initialize+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lldap $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ldap_initialize (); +int +main () +{ +return ldap_initialize (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ldap_ldap_initialize=yes +else + ac_cv_lib_ldap_ldap_initialize=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldap_ldap_initialize" >&5 +$as_echo "$ac_cv_lib_ldap_ldap_initialize" >&6; } +if test "x$ac_cv_lib_ldap_ldap_initialize" = xyes; then : + + +$as_echo "#define LDAP_HAVE_INITIALIZE /**/" >>confdefs.h + + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldap_start_tls_s in -lldap" >&5 +$as_echo_n "checking for ldap_start_tls_s in -lldap... " >&6; } +if ${ac_cv_lib_ldap_ldap_start_tls_s+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lldap $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ldap_start_tls_s (); +int +main () +{ +return ldap_start_tls_s (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ldap_ldap_start_tls_s=yes +else + ac_cv_lib_ldap_ldap_start_tls_s=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldap_ldap_start_tls_s" >&5 +$as_echo "$ac_cv_lib_ldap_ldap_start_tls_s" >&6; } +if test "x$ac_cv_lib_ldap_ldap_start_tls_s" = xyes; then : + + +$as_echo "#define LDAP_HAVE_START_TLS_S /**/" >>confdefs.h + + +fi + + LDAP_LIBS="-lldap" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ber_free in -lldap" >&5 +$as_echo_n "checking for ber_free in -lldap... " >&6; } +if ${ac_cv_lib_ldap_ber_free+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lldap $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ber_free (); +int +main () +{ +return ber_free (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ldap_ber_free=yes +else + ac_cv_lib_ldap_ber_free=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldap_ber_free" >&5 +$as_echo "$ac_cv_lib_ldap_ber_free" >&6; } +if test "x$ac_cv_lib_ldap_ber_free" = xyes; then : + + # do nothing, default is to add -lldap to LIBS + : + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ber_free in -llber" >&5 +$as_echo_n "checking for ber_free in -llber... " >&6; } +if ${ac_cv_lib_lber_ber_free+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llber $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ber_free (); +int +main () +{ +return ber_free (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lber_ber_free=yes +else + ac_cv_lib_lber_ber_free=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lber_ber_free" >&5 +$as_echo "$ac_cv_lib_lber_ber_free" >&6; } +if test "x$ac_cv_lib_lber_ber_free" = xyes; then : + + LDAP_LIBS="$LDAP_LIBS -llber" + +fi + + +fi + + + if test $want_ldap != plugin; then + +$as_echo "#define SIEVE_BUILTIN_LDAP /**/" >>confdefs.h + + fi + + +$as_echo "#define STORAGE_LDAP /**/" >>confdefs.h + + for ac_header in sasl.h sasl/sasl.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + have_ldap=yes + +else + + if test $want_ldap != auto; then + as_fn_error $? "Can't build with LDAP support: ldap.h not found" "$LINENO" 5 + fi + +fi + + + +else + + if test $want_ldap != auto; then + as_fn_error $? "Can't build with LDAP support: libldap not found" "$LINENO" 5 + fi + +fi + +fi + +if test $have_ldap = no; then + not_scriptloc="$not_scriptloc ldap" +else + scriptloc="$scriptloc ldap" + if test $want_ldap = plugin; then + have_ldap_plugin=yes + scriptloc="$scriptloc (plugin)" + fi +fi + if test "$have_ldap_plugin" = "yes"; then + LDAP_PLUGIN_TRUE= + LDAP_PLUGIN_FALSE='#' +else + LDAP_PLUGIN_TRUE='#' + LDAP_PLUGIN_FALSE= +fi + + +CFLAGS="$CFLAGS $EXTRA_CFLAGS" +LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS" + +ac_config_files="$ac_config_files Makefile doc/Makefile doc/man/Makefile doc/example-config/Makefile doc/example-config/conf.d/Makefile doc/rfc/Makefile doc/extensions/Makefile doc/locations/Makefile doc/plugins/Makefile src/Makefile src/lib-sieve/Makefile src/lib-sieve/util/Makefile src/lib-sieve/storage/Makefile src/lib-sieve/storage/data/Makefile src/lib-sieve/storage/file/Makefile src/lib-sieve/storage/dict/Makefile src/lib-sieve/storage/ldap/Makefile src/lib-sieve/plugins/Makefile src/lib-sieve/plugins/vacation/Makefile src/lib-sieve/plugins/subaddress/Makefile src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile src/lib-sieve/plugins/relational/Makefile src/lib-sieve/plugins/regex/Makefile src/lib-sieve/plugins/imap4flags/Makefile src/lib-sieve/plugins/copy/Makefile src/lib-sieve/plugins/include/Makefile src/lib-sieve/plugins/body/Makefile src/lib-sieve/plugins/variables/Makefile src/lib-sieve/plugins/enotify/Makefile src/lib-sieve/plugins/enotify/mailto/Makefile src/lib-sieve/plugins/notify/Makefile src/lib-sieve/plugins/environment/Makefile src/lib-sieve/plugins/mailbox/Makefile src/lib-sieve/plugins/date/Makefile src/lib-sieve/plugins/spamvirustest/Makefile src/lib-sieve/plugins/ihave/Makefile src/lib-sieve/plugins/editheader/Makefile src/lib-sieve/plugins/metadata/Makefile src/lib-sieve/plugins/duplicate/Makefile src/lib-sieve/plugins/index/Makefile src/lib-sieve/plugins/mime/Makefile src/lib-sieve/plugins/special-use/Makefile src/lib-sieve/plugins/vnd.dovecot/Makefile src/lib-sieve/plugins/vnd.dovecot/debug/Makefile src/lib-sieve/plugins/vnd.dovecot/environment/Makefile src/lib-sieve/plugins/vnd.dovecot/report/Makefile src/lib-sieve-tool/Makefile src/lib-managesieve/Makefile src/plugins/Makefile src/plugins/doveadm-sieve/Makefile src/plugins/lda-sieve/Makefile src/plugins/sieve-extprograms/Makefile src/plugins/imapsieve/Makefile src/plugins/imap-filter-sieve/Makefile src/plugins/settings/Makefile src/sieve-tools/Makefile src/managesieve/Makefile src/managesieve-login/Makefile src/testsuite/Makefile stamp.h" + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then + as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DOVECOT_INSTALLED_TRUE}" && test -z "${DOVECOT_INSTALLED_FALSE}"; then + as_fn_error $? "conditional \"DOVECOT_INSTALLED\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DOVECOT_PLUGIN_DEPS_TRUE}" && test -z "${DOVECOT_PLUGIN_DEPS_FALSE}"; then + as_fn_error $? "conditional \"DOVECOT_PLUGIN_DEPS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_UNFINISHED_TRUE}" && test -z "${BUILD_UNFINISHED_FALSE}"; then + as_fn_error $? "conditional \"BUILD_UNFINISHED\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_DOCS_TRUE}" && test -z "${BUILD_DOCS_FALSE}"; then + as_fn_error $? "conditional \"BUILD_DOCS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_MANAGESIEVE_TRUE}" && test -z "${BUILD_MANAGESIEVE_FALSE}"; then + as_fn_error $? "conditional \"BUILD_MANAGESIEVE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${LDAP_PLUGIN_TRUE}" && test -z "${LDAP_PLUGIN_FALSE}"; then + as_fn_error $? "conditional \"LDAP_PLUGIN\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by Pigeonhole $as_me 0.5.21, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to <dovecot@dovecot.org>." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +Pigeonhole config.status 0.5.21 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' +configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_import \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +lt_cv_nm_interface \ +nm_file_list_spec \ +lt_cv_truncate_bin \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +configure_time_dlsearch_path \ +configure_time_lt_sys_library_path; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' + +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile' + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "dummy-config.h") CONFIG_HEADERS="$CONFIG_HEADERS dummy-config.h" ;; + "pigeonhole-config.h") CONFIG_HEADERS="$CONFIG_HEADERS pigeonhole-config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "doc/man/Makefile") CONFIG_FILES="$CONFIG_FILES doc/man/Makefile" ;; + "doc/example-config/Makefile") CONFIG_FILES="$CONFIG_FILES doc/example-config/Makefile" ;; + "doc/example-config/conf.d/Makefile") CONFIG_FILES="$CONFIG_FILES doc/example-config/conf.d/Makefile" ;; + "doc/rfc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/rfc/Makefile" ;; + "doc/extensions/Makefile") CONFIG_FILES="$CONFIG_FILES doc/extensions/Makefile" ;; + "doc/locations/Makefile") CONFIG_FILES="$CONFIG_FILES doc/locations/Makefile" ;; + "doc/plugins/Makefile") CONFIG_FILES="$CONFIG_FILES doc/plugins/Makefile" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "src/lib-sieve/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/Makefile" ;; + "src/lib-sieve/util/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/util/Makefile" ;; + "src/lib-sieve/storage/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/storage/Makefile" ;; + "src/lib-sieve/storage/data/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/storage/data/Makefile" ;; + "src/lib-sieve/storage/file/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/storage/file/Makefile" ;; + "src/lib-sieve/storage/dict/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/storage/dict/Makefile" ;; + "src/lib-sieve/storage/ldap/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/storage/ldap/Makefile" ;; + "src/lib-sieve/plugins/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/Makefile" ;; + "src/lib-sieve/plugins/vacation/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/vacation/Makefile" ;; + "src/lib-sieve/plugins/subaddress/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/subaddress/Makefile" ;; + "src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile" ;; + "src/lib-sieve/plugins/relational/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/relational/Makefile" ;; + "src/lib-sieve/plugins/regex/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/regex/Makefile" ;; + "src/lib-sieve/plugins/imap4flags/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/imap4flags/Makefile" ;; + "src/lib-sieve/plugins/copy/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/copy/Makefile" ;; + "src/lib-sieve/plugins/include/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/include/Makefile" ;; + "src/lib-sieve/plugins/body/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/body/Makefile" ;; + "src/lib-sieve/plugins/variables/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/variables/Makefile" ;; + "src/lib-sieve/plugins/enotify/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/enotify/Makefile" ;; + "src/lib-sieve/plugins/enotify/mailto/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/enotify/mailto/Makefile" ;; + "src/lib-sieve/plugins/notify/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/notify/Makefile" ;; + "src/lib-sieve/plugins/environment/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/environment/Makefile" ;; + "src/lib-sieve/plugins/mailbox/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/mailbox/Makefile" ;; + "src/lib-sieve/plugins/date/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/date/Makefile" ;; + "src/lib-sieve/plugins/spamvirustest/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/spamvirustest/Makefile" ;; + "src/lib-sieve/plugins/ihave/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/ihave/Makefile" ;; + "src/lib-sieve/plugins/editheader/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/editheader/Makefile" ;; + "src/lib-sieve/plugins/metadata/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/metadata/Makefile" ;; + "src/lib-sieve/plugins/duplicate/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/duplicate/Makefile" ;; + "src/lib-sieve/plugins/index/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/index/Makefile" ;; + "src/lib-sieve/plugins/mime/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/mime/Makefile" ;; + "src/lib-sieve/plugins/special-use/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/special-use/Makefile" ;; + "src/lib-sieve/plugins/vnd.dovecot/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/vnd.dovecot/Makefile" ;; + "src/lib-sieve/plugins/vnd.dovecot/debug/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/vnd.dovecot/debug/Makefile" ;; + "src/lib-sieve/plugins/vnd.dovecot/environment/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/vnd.dovecot/environment/Makefile" ;; + "src/lib-sieve/plugins/vnd.dovecot/report/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve/plugins/vnd.dovecot/report/Makefile" ;; + "src/lib-sieve-tool/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-sieve-tool/Makefile" ;; + "src/lib-managesieve/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib-managesieve/Makefile" ;; + "src/plugins/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/Makefile" ;; + "src/plugins/doveadm-sieve/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/doveadm-sieve/Makefile" ;; + "src/plugins/lda-sieve/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/lda-sieve/Makefile" ;; + "src/plugins/sieve-extprograms/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/sieve-extprograms/Makefile" ;; + "src/plugins/imapsieve/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/imapsieve/Makefile" ;; + "src/plugins/imap-filter-sieve/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/imap-filter-sieve/Makefile" ;; + "src/plugins/settings/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/settings/Makefile" ;; + "src/sieve-tools/Makefile") CONFIG_FILES="$CONFIG_FILES src/sieve-tools/Makefile" ;; + "src/managesieve/Makefile") CONFIG_FILES="$CONFIG_FILES src/managesieve/Makefile" ;; + "src/managesieve-login/Makefile") CONFIG_FILES="$CONFIG_FILES src/managesieve-login/Makefile" ;; + "src/testsuite/Makefile") CONFIG_FILES="$CONFIG_FILES src/testsuite/Makefile" ;; + "stamp.h") CONFIG_FILES="$CONFIG_FILES stamp.h" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' <conf$$subs.awk | sed ' +/^[^""]/{ + N + s/\n// +} +' >>$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' <confdefs.h | sed ' +s/'"$ac_delim"'/"\\\ +"/g' >>$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + case $CONFIG_FILES in #( + *\'*) : + eval set x "$CONFIG_FILES" ;; #( + *) : + set x $CONFIG_FILES ;; #( + *) : + ;; +esac + shift + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf + do + # Strip MF so we end up with the name of the file. + am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`$as_dirname -- "$am_mf" || +$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$am_mf" : 'X\(//\)[^/]' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$am_mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + am_filepart=`$as_basename -- "$am_mf" || +$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$am_mf" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { echo "$as_me:$LINENO: cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles" >&5 + (cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } || am_rc=$? + done + if test $am_rc -ne 0; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE=\"gmake\" (or whatever is + necessary). You can also try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking). +See \`config.log' for more details" "$LINENO" 5; } + fi + { am_dirpart=; unset am_dirpart;} + { am_filepart=; unset am_filepart;} + { am_mf=; unset am_mf;} + { am_rc=; unset am_rc;} + rm -f conftest-deps.mk +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +# The names of the tagged configurations supported by this script. +available_tags='' + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec=$shared_archive_member_spec + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name lister interface. +nm_interface=$lt_lt_cv_nm_interface + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and where our libraries should be installed. +lt_sysroot=$lt_sysroot + +# Command to truncate a binary pipe. +lt_truncate_bin=$lt_lt_cv_truncate_bin + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain=$ac_aux_dir/ltmain.sh + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + +not_scriptloc=`echo "$not_scriptloc"|sed 's/ / -/g'` + +echo +echo "Install prefix . : $prefix" +echo "script drivers . : file dict$scriptloc" +if test "$not_scriptloc" != ""; then + echo " :$not_scriptloc" +fi + diff --git a/pigeonhole/configure.ac b/pigeonhole/configure.ac new file mode 100644 index 0000000..6239f62 --- /dev/null +++ b/pigeonhole/configure.ac @@ -0,0 +1,245 @@ +AC_PREREQ([2.59]) + +# Be sure to update ABI version also if anything changes that might require +# recompiling plugins. Most importantly that means if any structs are changed. +AC_INIT([Pigeonhole], [0.5.21], [dovecot@dovecot.org], [dovecot-2.3-pigeonhole]) +AC_DEFINE_UNQUOTED([PIGEONHOLE_ABI_VERSION], "0.5.ABIv21($PACKAGE_VERSION)", [Pigeonhole ABI version]) + +AC_CONFIG_AUX_DIR([.]) +AC_CONFIG_SRCDIR([src]) +AC_CONFIG_MACRO_DIR([m4]) + +# Autoheader is not needed and does more harm than good for this package. However, it is +# tightly integrated in autoconf/automake and therefore it is difficult not to use it. As +# a workaround we give autoheader a dummy config header to chew on and we handle the +# real config header ourselves. +AC_CONFIG_HEADERS([dummy-config.h pigeonhole-config.h]) + +AC_DEFINE_UNQUOTED(PIGEONHOLE_NAME, "$PACKAGE_NAME", + [Define to the full name of Pigeonhole for Dovecot.]) +AC_DEFINE_UNQUOTED(PIGEONHOLE_VERSION, "$PACKAGE_VERSION", + [Define to the version of Pigeonhole for Dovecot.]) + +AM_INIT_AUTOMAKE([no-define foreign tar-ustar]) + +AM_MAINTAINER_MODE + +AC_PROG_CC +AC_PROG_CPP +AC_PROG_LIBTOOL + +# Couple with Dovecot +# + +DC_DOVECOT +DC_DOVECOT_MODULEDIR +LIBDOVECOT_INCLUDE="$LIBDOVECOT_INCLUDE $LIBDOVECOT_STORAGE_INCLUDE" +CFLAGS="$CFLAGS -I\$(top_srcdir)" +LIBS="$DOVECOT_LIBS" +BINARY_LDFLAGS="$PIE_LDFLAGS $RELRO_LDFLAGS" +BINARY_CFLAGS="$PIE_CFLAGS" +AC_SUBST(BINARY_CFLAGS) +AC_SUBST(BINARY_LDFLAGS) +AC_SUBST(LIBDOVECOT_INCLUDE) + +# Define Sieve documentation install dir +# + +sieve_docdir='${dovecot_docdir}/sieve' +AC_SUBST(sieve_docdir) + +# Extensions under development +# + +AC_ARG_WITH(unfinished-features, +[AC_HELP_STRING([--with-unfinished-features], + [Build unfinished new features/extensions [default=no]])], + if test x$withval = xno || test x$withval = xauto; then + want_unfinished_features=$withval + else + want_unfinished_features=yes + fi, + want_unfinished_features=no) +AM_CONDITIONAL(BUILD_UNFINISHED, test "$want_unfinished_features" = "yes") + +if test "$want_unfinished_features" = "yes"; then + AC_DEFINE(HAVE_SIEVE_UNFINISHED,, + [Define to build unfinished features/extensions.]) +fi + +# +# + +dnl TEST_WITH(name, value, [plugin]) +AC_DEFUN([TEST_WITH], [ + want=want_`echo $1|sed s/-/_/g` + if test $2 = yes || test $2 = no || test $2 = auto; then + eval $want=$2 + elif test $2 = plugin; then + if test "$3" = plugin; then + eval $want=plugin + else + AC_ERROR([--with-$1=plugin not supported]) + fi + elif `echo $2|grep '^/' >/dev/null`; then + AC_ERROR([--with-$1=path not supported. You may want to use instead: +CPPFLAGS=-I$2/include LDFLAGS=-L$2/lib ./configure --with-$1]) + else + AC_ERROR([--with-$1: Unknown value: $2]) + fi +]) + +AC_ARG_WITH(docs, +[ --with-docs Install documentation (default)], + if test x$withval = xno; then + want_docs=no + else + want_docs=yes + fi, + want_docs=yes) +AM_CONDITIONAL(BUILD_DOCS, test "$want_docs" = "yes") + +AC_ARG_WITH(managesieve, +[AC_HELP_STRING([--with-managesieve], + [Build ManageSieve service [default=yes]])], + if test x$withval = xno || test x$withval = xauto; then + want_managesieve=$withval + else + want_managesieve=yes + fi, + want_managesieve=yes) +AM_CONDITIONAL(BUILD_MANAGESIEVE, test "$want_managesieve" = "yes") + +AC_ARG_WITH(ldap, +AS_HELP_STRING([--with-ldap=yes|plugin], [Build with LDAP support]), + TEST_WITH(ldap, $withval, plugin), + want_ldap=no) + +# FIXME: Imported this from Dovecot auth for now. We're working on a proper +# lib-ldap, but, until then, some code is duplicated. +have_ldap=no +if test $want_ldap != no; then + AC_CHECK_LIB(ldap, ldap_init, [ + AC_CHECK_HEADER(ldap.h, [ + AC_CHECK_LIB(ldap, ldap_initialize, [ + AC_DEFINE(LDAP_HAVE_INITIALIZE,, [Define if you have ldap_initialize]) + ]) + AC_CHECK_LIB(ldap, ldap_start_tls_s, [ + AC_DEFINE(LDAP_HAVE_START_TLS_S,, [Define if you have ldap_start_tls_s]) + ]) + LDAP_LIBS="-lldap" + AC_CHECK_LIB(ldap, ber_free, [ + # do nothing, default is to add -lldap to LIBS + : + ], [ + AC_CHECK_LIB(lber, ber_free, [ + LDAP_LIBS="$LDAP_LIBS -llber" + ]) + ]) + AC_SUBST(LDAP_LIBS) + if test $want_ldap != plugin; then + AC_DEFINE(SIEVE_BUILTIN_LDAP,, [LDAP support is built in]) + fi + + AC_DEFINE(STORAGE_LDAP,, [Build with LDAP support]) + AC_CHECK_HEADERS(sasl.h sasl/sasl.h) + have_ldap=yes + ], [ + if test $want_ldap != auto; then + AC_ERROR([Can't build with LDAP support: ldap.h not found]) + fi + ]) + ], [ + if test $want_ldap != auto; then + AC_ERROR([Can't build with LDAP support: libldap not found]) + fi + ]) +fi + +if test $have_ldap = no; then + not_scriptloc="$not_scriptloc ldap" +else + scriptloc="$scriptloc ldap" + if test $want_ldap = plugin; then + have_ldap_plugin=yes + scriptloc="$scriptloc (plugin)" + fi +fi +AM_CONDITIONAL(LDAP_PLUGIN, test "$have_ldap_plugin" = "yes") + +CFLAGS="$CFLAGS $EXTRA_CFLAGS" +LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS" + +AC_CONFIG_FILES([ +Makefile +doc/Makefile +doc/man/Makefile +doc/example-config/Makefile +doc/example-config/conf.d/Makefile +doc/rfc/Makefile +doc/extensions/Makefile +doc/locations/Makefile +doc/plugins/Makefile +src/Makefile +src/lib-sieve/Makefile +src/lib-sieve/util/Makefile +src/lib-sieve/storage/Makefile +src/lib-sieve/storage/data/Makefile +src/lib-sieve/storage/file/Makefile +src/lib-sieve/storage/dict/Makefile +src/lib-sieve/storage/ldap/Makefile +src/lib-sieve/plugins/Makefile +src/lib-sieve/plugins/vacation/Makefile +src/lib-sieve/plugins/subaddress/Makefile +src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile +src/lib-sieve/plugins/relational/Makefile +src/lib-sieve/plugins/regex/Makefile +src/lib-sieve/plugins/imap4flags/Makefile +src/lib-sieve/plugins/copy/Makefile +src/lib-sieve/plugins/include/Makefile +src/lib-sieve/plugins/body/Makefile +src/lib-sieve/plugins/variables/Makefile +src/lib-sieve/plugins/enotify/Makefile +src/lib-sieve/plugins/enotify/mailto/Makefile +src/lib-sieve/plugins/notify/Makefile +src/lib-sieve/plugins/environment/Makefile +src/lib-sieve/plugins/mailbox/Makefile +src/lib-sieve/plugins/date/Makefile +src/lib-sieve/plugins/spamvirustest/Makefile +src/lib-sieve/plugins/ihave/Makefile +src/lib-sieve/plugins/editheader/Makefile +src/lib-sieve/plugins/metadata/Makefile +src/lib-sieve/plugins/duplicate/Makefile +src/lib-sieve/plugins/index/Makefile +src/lib-sieve/plugins/mime/Makefile +src/lib-sieve/plugins/special-use/Makefile +src/lib-sieve/plugins/vnd.dovecot/Makefile +src/lib-sieve/plugins/vnd.dovecot/debug/Makefile +src/lib-sieve/plugins/vnd.dovecot/environment/Makefile +src/lib-sieve/plugins/vnd.dovecot/report/Makefile +src/lib-sieve-tool/Makefile +src/lib-managesieve/Makefile +src/plugins/Makefile +src/plugins/doveadm-sieve/Makefile +src/plugins/lda-sieve/Makefile +src/plugins/sieve-extprograms/Makefile +src/plugins/imapsieve/Makefile +src/plugins/imap-filter-sieve/Makefile +src/plugins/settings/Makefile +src/sieve-tools/Makefile +src/managesieve/Makefile +src/managesieve-login/Makefile +src/testsuite/Makefile +stamp.h]) + +AC_OUTPUT + +not_scriptloc=`echo "$not_scriptloc"|sed 's/ / -/g'` + +echo +echo "Install prefix . : $prefix" +echo "script drivers . : file dict$scriptloc" +if test "$not_scriptloc" != ""; then + echo " :$not_scriptloc" +fi + diff --git a/pigeonhole/depcomp b/pigeonhole/depcomp new file mode 100755 index 0000000..6b39162 --- /dev/null +++ b/pigeonhole/depcomp @@ -0,0 +1,791 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2018-03-07.03; # UTC + +# Copyright (C) 1999-2020 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>. + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to <bug-automake@gnu.org>. +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# Get the directory component of the given path, and save it in the +# global variables '$dir'. Note that this directory component will +# be either empty or ending with a '/' character. This is deliberate. +set_dir_from () +{ + case $1 in + */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; + *) dir=;; + esac +} + +# Get the suffix-stripped basename of the given path, and save it the +# global variable '$base'. +set_base_from () +{ + base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` +} + +# If no dependency file was actually created by the compiler invocation, +# we still have to create a dummy depfile, to avoid errors with the +# Makefile "include basename.Plo" scheme. +make_dummy_depfile () +{ + echo "#dummy" > "$depfile" +} + +# Factor out some common post-processing of the generated depfile. +# Requires the auxiliary global variable '$tmpdepfile' to be set. +aix_post_process_depfile () +{ + # If the compiler actually managed to produce a dependency file, + # post-process it. + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependency.h'. + # Do two passes, one to just change these to + # $object: dependency.h + # and one to simply output + # dependency.h: + # which is needed to avoid the deleted-header problem. + { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" + sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" + } > "$depfile" + rm -f "$tmpdepfile" + else + make_dummy_depfile + fi +} + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' +# Character ranges might be problematic outside the C locale. +# These definitions help. +upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ +lower=abcdefghijklmnopqrstuvwxyz +digits=0123456789 +alpha=${upper}${lower} + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Avoid interferences from the environment. +gccflag= dashmflag= + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The second -e expression handles DOS-style file names with drive + # letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ + | tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + aix_post_process_depfile + ;; + +tcc) + # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 + # FIXME: That version still under development at the moment of writing. + # Make that this statement remains true also for stable, released + # versions. + # It will wrap lines (doesn't matter whether long or short) with a + # trailing '\', as in: + # + # foo.o : \ + # foo.c \ + # foo.h \ + # + # It will put a trailing '\' even on the last line, and will use leading + # spaces rather than leading tabs (at least since its commit 0394caf7 + # "Emit spaces for -MD"). + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. + # We have to change lines of the first kind to '$object: \'. + sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" + # And for each line of the second kind, we have to emit a 'dep.h:' + # dummy dependency, to avoid the deleted-header problem. + sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + set_dir_from "$object" + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + set_base_from "$source" + tmpdepfile=$base.d + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir=$base.d-lock + trap " + echo '$0: caught signal, cleaning up...' >&2 + rmdir '$lockdir' + exit 1 + " 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0; do + # mkdir is a portable test-and-set. + if mkdir "$lockdir" 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rmdir "$lockdir" + break + else + # If the lock is being held by a different process, wait + # until the winning process is done or we timeout. + while test -d "$lockdir" && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + set_dir_from "$object" + set_base_from "$object" + + if test "$libtool" = yes; then + # Libtool generates 2 separate objects for the 2 libraries. These + # two compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir$base.o.d # libtool 1.5 + tmpdepfile2=$dir.libs/$base.o.d # Likewise. + tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + # Same post-processing that is required for AIX mode. + aix_post_process_depfile + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + echo >> "$depfile" # make sure the fragment doesn't end with a backslash + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this sed invocation + # correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process the last invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed '1,2d' "$tmpdepfile" \ + | tr ' ' "$nl" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E \ + | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + | sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/pigeonhole/doc/Makefile.am b/pigeonhole/doc/Makefile.am new file mode 100644 index 0000000..5131ece --- /dev/null +++ b/pigeonhole/doc/Makefile.am @@ -0,0 +1,18 @@ +SUBDIRS = \ + man \ + example-config \ + rfc \ + extensions \ + locations \ + plugins + +docfiles = + +if BUILD_DOCS +sieve_doc_DATA = $(docfiles) +endif + +EXTRA_DIST = \ + devel \ + $(docfiles) + diff --git a/pigeonhole/doc/Makefile.in b/pigeonhole/doc/Makefile.in new file mode 100644 index 0000000..4ac14f7 --- /dev/null +++ b/pigeonhole/doc/Makefile.in @@ -0,0 +1,760 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = doc +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(sieve_docdir)" +DATA = $(sieve_doc_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = \ + man \ + example-config \ + rfc \ + extensions \ + locations \ + plugins + +docfiles = +@BUILD_DOCS_TRUE@sieve_doc_DATA = $(docfiles) +EXTRA_DIST = \ + devel \ + $(docfiles) + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-sieve_docDATA: $(sieve_doc_DATA) + @$(NORMAL_INSTALL) + @list='$(sieve_doc_DATA)'; test -n "$(sieve_docdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sieve_docdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sieve_docdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(sieve_docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(sieve_docdir)" || exit $$?; \ + done + +uninstall-sieve_docDATA: + @$(NORMAL_UNINSTALL) + @list='$(sieve_doc_DATA)'; test -n "$(sieve_docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(sieve_docdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(sieve_docdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-sieve_docDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-sieve_docDATA + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-sieve_docDATA install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-sieve_docDATA + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/doc/devel/DESIGN b/pigeonhole/doc/devel/DESIGN new file mode 100644 index 0000000..8e78112 --- /dev/null +++ b/pigeonhole/doc/devel/DESIGN @@ -0,0 +1,45 @@ +The compiler consists of the following stages: + +PARSER: sieve-parser.c, sieve-lexer.c + Parses the scriptfile and produces an abstract syntax tree for it + (sieve-ast.c). + +VALIDATOR: sieve-validator.c + Performs contextual analysis on the ast produced by the parser. This checks + for the validity of commands, tests and arguments. Also, the ast is decorated + with any context data acquired during the process. This context is used by the + last compiler stage. + +GENERATOR: sieve-generator.c + This last compiler stage uses a visitor pattern to wander through the ast and + produces sieve byte code (sieve-binary.c). + +The resulting (in-memory) binary can be fed to the interpreter for execution: + +INTERPRETER: sieve-interpreter.c + The interpreter executes the byte code and produces a sieve_result object. + This result is no more than just a collection of actions to be performed. + During execution, action commands add actions to the result. Duplates and + conflicts between actions are handled in this execution phase. + +RESULT: sieve-result.c sieve-actions.c + When the result is to be executed, it needs no further checking, as the + validity of the result was verified during interpretation already. The + result's actions are executed in a transaction-like atomic manner. If one of + the actions fails, the whole transaction is rolled back meaning that either + everything succeeds or everything fails. This is only possible to some extent: + transmitted responses can of course not be rolled back. However, these are + executed in the commit phase, meaning that they will only be performed if all + other actions were successful. + +Debugging: + +BINARY-DUMPER: sieve-code-dumper.c sieve-binary-dumper.c + A loaded binary can be dumped to a stream in human-readable form using the + binary-dumper. The binary-dumper displays information on all the blocks that + the binary consists off. Program code blocks are dumped using the code-dumper. + It's implementation is similar to the interpreter, with the exception that it + performs no actions and just sequentially wanders through the byte code + printing instructions along the way. The term human-readable is a bit optimistic + though; currently, the presented data looks like an assembly language. + diff --git a/pigeonhole/doc/example-config/Makefile.am b/pigeonhole/doc/example-config/Makefile.am new file mode 100644 index 0000000..f30c9fb --- /dev/null +++ b/pigeonhole/doc/example-config/Makefile.am @@ -0,0 +1,10 @@ +SUBDIRS = conf.d + +pkgsysconfdir = $(sysconfdir)/dovecot + +exampledir = $(dovecot_docdir)/example-config +example_DATA = \ + sieve-ldap.conf + +EXTRA_DIST = \ + $(example_DATA) diff --git a/pigeonhole/doc/example-config/Makefile.in b/pigeonhole/doc/example-config/Makefile.in new file mode 100644 index 0000000..af6460c --- /dev/null +++ b/pigeonhole/doc/example-config/Makefile.in @@ -0,0 +1,755 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = doc/example-config +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(exampledir)" +DATA = $(example_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = conf.d +pkgsysconfdir = $(sysconfdir)/dovecot +exampledir = $(dovecot_docdir)/example-config +example_DATA = \ + sieve-ldap.conf + +EXTRA_DIST = \ + $(example_DATA) + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/example-config/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/example-config/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-exampleDATA: $(example_DATA) + @$(NORMAL_INSTALL) + @list='$(example_DATA)'; test -n "$(exampledir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(exampledir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(exampledir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(exampledir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(exampledir)" || exit $$?; \ + done + +uninstall-exampleDATA: + @$(NORMAL_UNINSTALL) + @list='$(example_DATA)'; test -n "$(exampledir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(exampledir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(exampledir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-exampleDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-exampleDATA + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exampleDATA install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-exampleDATA + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/doc/example-config/conf.d/20-managesieve.conf b/pigeonhole/doc/example-config/conf.d/20-managesieve.conf new file mode 100644 index 0000000..3f71b58 --- /dev/null +++ b/pigeonhole/doc/example-config/conf.d/20-managesieve.conf @@ -0,0 +1,84 @@ +## +## ManageSieve specific settings +## + +# Uncomment to enable managesieve protocol: +#protocols = $protocols sieve + +# Service definitions + +#service managesieve-login { + #inet_listener sieve { + # port = 4190 + #} + + #inet_listener sieve_deprecated { + # port = 2000 + #} + + # Number of connections to handle before starting a new process. Typically + # the only useful values are 0 (unlimited) or 1. 1 is more secure, but 0 + # is faster. <doc/wiki/LoginProcess.txt> + #service_count = 1 + + # Number of processes to always keep waiting for more connections. + #process_min_avail = 0 + + # If you set service_count=0, you probably need to grow this. + #vsz_limit = 64M +#} + +#service managesieve { + # Max. number of ManageSieve processes (connections) + #process_limit = 1024 +#} + +# Service configuration + +protocol sieve { + # Maximum ManageSieve command line length in bytes. ManageSieve usually does + # not involve overly long command lines, so this setting will not normally + # need adjustment + #managesieve_max_line_length = 65536 + + # Maximum number of ManageSieve connections allowed for a user from each IP + # address. + # NOTE: The username is compared case-sensitively. + #mail_max_userip_connections = 10 + + # Space separated list of plugins to load (none known to be useful so far). + # Do NOT try to load IMAP plugins here. + #mail_plugins = + + # MANAGESIEVE logout format string: + # %i - total number of bytes read from client + # %o - total number of bytes sent to client + # %{put_bytes} - Number of bytes saved using PUTSCRIPT command + # %{put_count} - Number of scripts saved using PUTSCRIPT command + # %{get_bytes} - Number of bytes read using GETCRIPT command + # %{get_count} - Number of scripts read using GETSCRIPT command + # %{get_bytes} - Number of bytes processed using CHECKSCRIPT command + # %{get_count} - Number of scripts checked using CHECKSCRIPT command + # %{deleted_count} - Number of scripts deleted using DELETESCRIPT command + # %{renamed_count} - Number of scripts renamed using RENAMESCRIPT command + #managesieve_logout_format = bytes=%i/%o + + # To fool ManageSieve clients that are focused on CMU's timesieved you can + # specify the IMPLEMENTATION capability that Dovecot reports to clients. + # For example: 'Cyrus timsieved v2.2.13' + #managesieve_implementation_string = Dovecot Pigeonhole + + # Explicitly specify the SIEVE and NOTIFY capability reported by the server + # before login. If left unassigned these will be reported dynamically + # according to what the Sieve interpreter supports by default (after login + # this may differ depending on the user). + #managesieve_sieve_capability = + #managesieve_notify_capability = + + # The maximum number of compile errors that are returned to the client upon + # script upload or script verification. + #managesieve_max_compile_errors = 5 + + # Refer to 90-sieve.conf for script quota configuration and configuration of + # Sieve execution limits. +} diff --git a/pigeonhole/doc/example-config/conf.d/90-sieve-extprograms.conf b/pigeonhole/doc/example-config/conf.d/90-sieve-extprograms.conf new file mode 100644 index 0000000..17dcb77 --- /dev/null +++ b/pigeonhole/doc/example-config/conf.d/90-sieve-extprograms.conf @@ -0,0 +1,44 @@ +# Sieve Extprograms plugin configuration + +# Don't forget to add the sieve_extprograms plugin to the sieve_plugins setting. +# Also enable the extensions you need (one or more of vnd.dovecot.pipe, +# vnd.dovecot.filter and vnd.dovecot.execute) by adding these to the +# sieve_extensions or sieve_global_extensions settings. Restricting these +# extensions to a global context using sieve_global_extensions is recommended. + +plugin { + + # The directory where the program sockets are located for the + # vnd.dovecot.pipe, vnd.dovecot.filter and vnd.dovecot.execute extension + # respectively. The name of each unix socket contained in that directory + # directly maps to a program-name referenced from the Sieve script. + #sieve_pipe_socket_dir = sieve-pipe + #sieve_filter_socket_dir = sieve-filter + #sieve_execute_socket_dir = sieve-execute + + # The directory where the scripts are located for direct execution by the + # vnd.dovecot.pipe, vnd.dovecot.filter and vnd.dovecot.execute extension + # respectively. The name of each script contained in that directory + # directly maps to a program-name referenced from the Sieve script. + #sieve_pipe_bin_dir = /usr/lib/dovecot/sieve-pipe + #sieve_filter_bin_dir = /usr/lib/dovecot/sieve-filter + #sieve_execute_bin_dir = /usr/lib/dovecot/sieve-execute +} + +# An example program service called 'do-something' to pipe messages to +#service do-something { + # Define the executed script as parameter to the sieve service + #executable = script /usr/lib/dovecot/sieve-pipe/do-something.sh + + # Use some unprivileged user for executing the program + #user = dovenull + + # The unix socket located in the sieve_pipe_socket_dir (as defined in the + # plugin {} section above) + #unix_listener sieve-pipe/do-something { + # LDA/LMTP must have access + # user = vmail + # mode = 0600 + #} +#} + diff --git a/pigeonhole/doc/example-config/conf.d/90-sieve.conf b/pigeonhole/doc/example-config/conf.d/90-sieve.conf new file mode 100644 index 0000000..238bcf4 --- /dev/null +++ b/pigeonhole/doc/example-config/conf.d/90-sieve.conf @@ -0,0 +1,205 @@ +## +## Settings for the Sieve interpreter +## + +# Do not forget to enable the Sieve plugin in 15-lda.conf and 20-lmtp.conf +# by adding it to the respective mail_plugins= settings. + +# The Sieve interpreter can retrieve Sieve scripts from several types of +# locations. The default `file' location type is a local filesystem path +# pointing to a Sieve script file or a directory containing multiple Sieve +# script files. More complex setups can use other location types such as +# `ldap' or `dict' to fetch Sieve scripts from remote databases. +# +# All settings that specify the location of one ore more Sieve scripts accept +# the following syntax: +# +# location = [<type>:]path[;<option>[=<value>][;...]] +# +# If the type prefix is omitted, the script location type is 'file' and the +# location is interpreted as a local filesystem path pointing to a Sieve script +# file or directory. Refer to Pigeonhole wiki or INSTALL file for more +# information. + +plugin { + # The location of the user's main Sieve script or script storage. The LDA + # Sieve plugin uses this to find the active script for Sieve filtering at + # delivery. The "include" extension uses this location for retrieving + # :personal" scripts. This is also where the ManageSieve service will store + # the user's scripts, if supported. + # + # Currently only the 'file:' location type supports ManageSieve operation. + # Other location types like 'dict:' and 'ldap:' can currently only + # be used as a read-only script source (). + # + # For the 'file:' type: use the ';active=' parameter to specify where the + # active script symlink is located. + # For other types: use the ';name=' parameter to specify the name of the + # default/active script. + sieve = file:~/sieve;active=~/.dovecot.sieve + + # The default Sieve script when the user has none. This is the location of a + # global sieve script file, which gets executed ONLY if user's personal Sieve + # script doesn't exist. Be sure to pre-compile this script manually using the + # sievec command line tool if the binary is not stored in a global location. + # --> See sieve_before for executing scripts before the user's personal + # script. + #sieve_default = /var/lib/dovecot/sieve/default.sieve + + # The name by which the default Sieve script (as configured by the + # sieve_default setting) is visible to the user through ManageSieve. + #sieve_default_name = + + # Location for ":global" include scripts as used by the "include" extension. + #sieve_global = + + # The location of a Sieve script that is run for any message that is about to + # be discarded; i.e., it is not delivered anywhere by the normal Sieve + # execution. This only happens when the "implicit keep" is canceled, by e.g. + # the "discard" action, and no actions that deliver the message are executed. + # This "discard script" can prevent discarding the message, by executing + # alternative actions. If the discard script does nothing, the message is + # still discarded as it would be when no discard script is configured. + #sieve_discard = + + # Location Sieve of scripts that need to be executed before the user's + # personal script. If a 'file' location path points to a directory, all the + # Sieve scripts contained therein (with the proper `.sieve' extension) are + # executed. The order of execution within that directory is determined by the + # file names, using a normal 8bit per-character comparison. + # + # Multiple script locations can be specified by appending an increasing number + # to the setting name. The Sieve scripts found from these locations are added + # to the script execution sequence in the specified order. Reading the + # numbered sieve_before settings stops at the first missing setting, so no + # numbers may be skipped. + #sieve_before = /var/lib/dovecot/sieve.d/ + #sieve_before2 = ldap:/etc/sieve-ldap.conf;name=ldap-domain + #sieve_before3 = (etc...) + + # Identical to sieve_before, only the specified scripts are executed after the + # user's script (only when keep is still in effect!). Multiple script + # locations can be specified by appending an increasing number. + #sieve_after = + #sieve_after2 = + #sieve_after2 = (etc...) + + # Which Sieve language extensions are available to users. By default, all + # supported extensions are available, except for deprecated extensions or + # those that are still under development. Some system administrators may want + # to disable certain Sieve extensions or enable those that are not available + # by default. This setting can use '+' and '-' to specify differences relative + # to the default. For example `sieve_extensions = +imapflags' will enable the + # deprecated imapflags extension in addition to all extensions were already + # enabled by default. + #sieve_extensions = +notify +imapflags + + # Which Sieve language extensions are ONLY available in global scripts. This + # can be used to restrict the use of certain Sieve extensions to administrator + # control, for instance when these extensions can cause security concerns. + # This setting has higher precedence than the `sieve_extensions' setting + # (above), meaning that the extensions enabled with this setting are never + # available to the user's personal script no matter what is specified for the + # `sieve_extensions' setting. The syntax of this setting is similar to the + # `sieve_extensions' setting, with the difference that extensions are + # enabled or disabled for exclusive use in global scripts. Currently, no + # extensions are marked as such by default. + #sieve_global_extensions = + + # The Pigeonhole Sieve interpreter can have plugins of its own. Using this + # setting, the used plugins can be specified. Check the Dovecot wiki + # (wiki2.dovecot.org) or the pigeonhole website + # (http://pigeonhole.dovecot.org) for available plugins. + # The sieve_extprograms plugin is included in this release. + #sieve_plugins = + + # The maximum size of a Sieve script. The compiler will refuse to compile any + # script larger than this limit. If set to 0, no limit on the script size is + # enforced. + #sieve_max_script_size = 1M + + # The maximum number of actions that can be performed during a single script + # execution. If set to 0, no limit on the total number of actions is enforced. + #sieve_max_actions = 32 + + # The maximum number of redirect actions that can be performed during a single + # script execution. If set to 0, no redirect actions are allowed. + #sieve_max_redirects = 4 + + # The maximum number of personal Sieve scripts a single user can have. If set + # to 0, no limit on the number of scripts is enforced. + # (Currently only relevant for ManageSieve) + #sieve_quota_max_scripts = 0 + + # The maximum amount of disk storage a single user's scripts may occupy. If + # set to 0, no limit on the used amount of disk storage is enforced. + # (Currently only relevant for ManageSieve) + #sieve_quota_max_storage = 0 + + # The primary e-mail address for the user. This is used as a default when no + # other appropriate address is available for sending messages. If this setting + # is not configured, either the postmaster or null "<>" address is used as a + # sender, depending on the action involved. This setting is important when + # there is no message envelope to extract addresses from, such as when the + # script is executed in IMAP. + #sieve_user_email = + + # The path to the file where the user log is written. If not configured, a + # default location is used. If the main user's personal Sieve (as configured + # with sieve=) is a file, the logfile is set to <filename>.log by default. If + # it is not a file, the default user log file is ~/.dovecot.sieve.log. + #sieve_user_log = + + # Specifies what envelope sender address is used for redirected messages. + # The following values are supported for this setting: + # + # "sender" - The sender address is used (default). + # "recipient" - The final recipient address is used. + # "orig_recipient" - The original recipient is used. + # "user_email" - The user's primary address is used. This is + # configured with the "sieve_user_email" setting. If + # that setting is unconfigured, "user_mail" is equal to + # "recipient". + # "postmaster" - The postmaster_address configured for the LDA. + # "<user@domain>" - Redirected messages are always sent from user@domain. + # The angle brackets are mandatory. The null "<>" address + # is also supported. + # + # This setting is ignored when the envelope sender is "<>". In that case the + # sender of the redirected message is also always "<>". + #sieve_redirect_envelope_from = sender + + ## TRACE DEBUGGING + # Trace debugging provides detailed insight in the operations performed by + # the Sieve script. These settings apply to both the LDA Sieve plugin and the + # IMAPSIEVE plugin. + # + # WARNING: On a busy server, this functionality can quickly fill up the trace + # directory with a lot of trace files. Enable this only temporarily and as + # selective as possible. + + # The directory where trace files are written. Trace debugging is disabled if + # this setting is not configured or if the directory does not exist. If the + # path is relative or it starts with "~/" it is interpreted relative to the + # current user's home directory. + #sieve_trace_dir = + + # The verbosity level of the trace messages. Trace debugging is disabled if + # this setting is not configured. Possible values are: + # + # "actions" - Only print executed action commands, like keep, + # fileinto, reject and redirect. + # "commands" - Print any executed command, excluding test commands. + # "tests" - Print all executed commands and performed tests. + # "matching" - Print all executed commands, performed tests and the + # values matched in those tests. + #sieve_trace_level = + + # Enables highly verbose debugging messages that are usually only useful for + # developers. + #sieve_trace_debug = no + + # Enables showing byte code addresses in the trace output, rather than only + # the source line numbers. + #sieve_trace_addresses = no +} diff --git a/pigeonhole/doc/example-config/conf.d/Makefile.am b/pigeonhole/doc/example-config/conf.d/Makefile.am new file mode 100644 index 0000000..8cea566 --- /dev/null +++ b/pigeonhole/doc/example-config/conf.d/Makefile.am @@ -0,0 +1,10 @@ +pkgsysconfdir = $(sysconfdir)/dovecot + +exampledir = $(dovecot_docdir)/example-config/conf.d +example_DATA = \ + 20-managesieve.conf \ + 90-sieve.conf \ + 90-sieve-extprograms.conf + +EXTRA_DIST = \ + $(example_DATA) diff --git a/pigeonhole/doc/example-config/conf.d/Makefile.in b/pigeonhole/doc/example-config/conf.d/Makefile.in new file mode 100644 index 0000000..a32ed00 --- /dev/null +++ b/pigeonhole/doc/example-config/conf.d/Makefile.in @@ -0,0 +1,576 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = doc/example-config/conf.d +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(exampledir)" +DATA = $(example_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkgsysconfdir = $(sysconfdir)/dovecot +exampledir = $(dovecot_docdir)/example-config/conf.d +example_DATA = \ + 20-managesieve.conf \ + 90-sieve.conf \ + 90-sieve-extprograms.conf + +EXTRA_DIST = \ + $(example_DATA) + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/example-config/conf.d/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/example-config/conf.d/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-exampleDATA: $(example_DATA) + @$(NORMAL_INSTALL) + @list='$(example_DATA)'; test -n "$(exampledir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(exampledir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(exampledir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(exampledir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(exampledir)" || exit $$?; \ + done + +uninstall-exampleDATA: + @$(NORMAL_UNINSTALL) + @list='$(example_DATA)'; test -n "$(exampledir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(exampledir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(exampledir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-exampleDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-exampleDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exampleDATA install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-exampleDATA + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/doc/example-config/sieve-ldap.conf b/pigeonhole/doc/example-config/sieve-ldap.conf new file mode 100644 index 0000000..0325ee5 --- /dev/null +++ b/pigeonhole/doc/example-config/sieve-ldap.conf @@ -0,0 +1,74 @@ +# This file needs to be accessible by the Sieve interpreter running in LDA/LMTP. +# This requires acces by the mail user. Don't use privileged LDAP credentials +# here as these may likely leak. Only search and read access is required. + +# Space separated list of LDAP hosts to use. host:port is allowed too. +hosts = localhost + +# LDAP URIs to use. You can use this instead of hosts list. Note that this +# setting isn't supported by all LDAP libraries. +#uris = + +# Distinguished Name - the username used to login to the LDAP server. +# Leave it commented out to bind anonymously. +#dn = + +# Password for LDAP server, if dn is specified. +#dnpass = + +# Use SASL binding instead of the simple binding. Note that this changes +# ldap_version automatically to be 3 if it's lower. +#sasl_bind = no +# SASL mechanism name to use. +#sasl_mech = +# SASL realm to use. +#sasl_realm = +# SASL authorization ID, ie. the dnpass is for this "master user", but the +# dn is still the logged in user. Normally you want to keep this empty. +#sasl_authz_id = + +# Use TLS to connect to the LDAP server. +#tls = no +# TLS options, currently supported only with OpenLDAP: +#tls_ca_cert_file = +#tls_ca_cert_dir = +#tls_cipher_suite = +# TLS cert/key is used only if LDAP server requires a client certificate. +#tls_cert_file = +#tls_key_file = +# Valid values: never, hard, demand, allow, try +#tls_require_cert = + +# Use the given ldaprc path. +#ldaprc_path = + +# LDAP library debug level as specified by LDAP_DEBUG_* in ldap_log.h. +# -1 = everything. You may need to recompile OpenLDAP with debugging enabled +# to get enough output. +#debug_level = 0 + +# LDAP protocol version to use. Likely 2 or 3. +#ldap_version = 3 + +# LDAP base. %variables can be used here. +# For example: dc=mail, dc=example, dc=org +base = + +# Dereference: never, searching, finding, always +#deref = never + +# Search scope: base, onelevel, subtree +#scope = subtree + +# Filter for user lookup. Some variables can be used: +# %u - username +# %n - user part in user@domain, same as %u if there's no domain +# %d - domain part in user@domain, empty if there's no domain +# %{name} - name of the Sieve script +#sieve_ldap_filter = (&(objectClass=posixAccount)(uid=%u)) + +# Attribute containing the Sieve script +#sieve_ldap_script_attr = mailSieveRuleSource + +# Attribute used for modification tracking +#sieve_ldap_mod_attr = modifyTimestamp diff --git a/pigeonhole/doc/extensions/Makefile.am b/pigeonhole/doc/extensions/Makefile.am new file mode 100644 index 0000000..54d6b86 --- /dev/null +++ b/pigeonhole/doc/extensions/Makefile.am @@ -0,0 +1,17 @@ +docfiles = \ + duplicate.txt \ + editheader.txt \ + include.txt \ + spamtest-virustest.txt \ + vacation.txt \ + vnd.dovecot.environment.txt \ + vnd.dovecot.report.txt + +if BUILD_DOCS +extensions_docdir = $(sieve_docdir)/extensions +extensions_doc_DATA = $(docfiles) +endif + +EXTRA_DIST = \ + $(docfiles) + diff --git a/pigeonhole/doc/extensions/Makefile.in b/pigeonhole/doc/extensions/Makefile.in new file mode 100644 index 0000000..b2c0c88 --- /dev/null +++ b/pigeonhole/doc/extensions/Makefile.in @@ -0,0 +1,580 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = doc/extensions +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(extensions_docdir)" +DATA = $(extensions_doc_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +docfiles = \ + duplicate.txt \ + editheader.txt \ + include.txt \ + spamtest-virustest.txt \ + vacation.txt \ + vnd.dovecot.environment.txt \ + vnd.dovecot.report.txt + +@BUILD_DOCS_TRUE@extensions_docdir = $(sieve_docdir)/extensions +@BUILD_DOCS_TRUE@extensions_doc_DATA = $(docfiles) +EXTRA_DIST = \ + $(docfiles) + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/extensions/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/extensions/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-extensions_docDATA: $(extensions_doc_DATA) + @$(NORMAL_INSTALL) + @list='$(extensions_doc_DATA)'; test -n "$(extensions_docdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(extensions_docdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(extensions_docdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(extensions_docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(extensions_docdir)" || exit $$?; \ + done + +uninstall-extensions_docDATA: + @$(NORMAL_UNINSTALL) + @list='$(extensions_doc_DATA)'; test -n "$(extensions_docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(extensions_docdir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(extensions_docdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-extensions_docDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-extensions_docDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am \ + install-extensions_docDATA install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-extensions_docDATA + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/doc/extensions/duplicate.txt b/pigeonhole/doc/extensions/duplicate.txt new file mode 100644 index 0000000..962e69e --- /dev/null +++ b/pigeonhole/doc/extensions/duplicate.txt @@ -0,0 +1,48 @@ +Duplicate Extension + +Relevant specifications +======================= + + doc/rfc/duplicate.rfc7352.txt + +Description +=========== + +The "duplicate" extension adds a new test command called "duplicate" to the +Sieve language. This test adds the ability to detect duplications. The main +application for this new test is handling duplicate deliveries commonly caused +by mailing list subscriptions or redirected mail addresses. The detection is +normally performed by matching the message ID to an internal list of message +IDs from previously delivered messages. For more complex applications, the +"duplicate" test can also use the content of a specific header field or other +parts of the message. + +Refer to doc/rfc/duplicate.rfc7352.txt for a specification of the Sieve language +extension. Previously, this extension was Dovecot-specific and available under +the name "vnd.dovecot.duplicate". That implementation differs significantly from +what is now published as an RFC, but for backwards compatibility the original +extension is still supported. + +Configuration +============= + +The "duplicate" extension is available by default. The "duplicate" extension has +its own specific settings. The following settings are available (default +values are indicated): + +sieve_duplicate_default_period = 14d +sieve_duplicate_max_period = 7d + These options respectively specify the default and the maximum value for the + period after which tracked values are purged from the duplicate tracking + database. The period is specified in s(econds), unless followed by a d(ay), + h(our) or m(inute) specifier character. + +Example +======= + +plugin { + sieve = ~/.dovecot.sieve + + sieve_duplicate_default_period = 1h + sieve_duplicate_max_period = 1d +} diff --git a/pigeonhole/doc/extensions/editheader.txt b/pigeonhole/doc/extensions/editheader.txt new file mode 100644 index 0000000..4c75831 --- /dev/null +++ b/pigeonhole/doc/extensions/editheader.txt @@ -0,0 +1,64 @@ +Editheader Extension + +Relevant specifications +======================= + + RFC5293 - doc/rfc/editheader.rfc5293.txt + +Description +=========== + +The editheader extension [RFC5293] enables Sieve scripts to delete and add +message header fields, thereby allowing interaction with other components that +consume or produce header fields. + +Configuration +============= + +The editheader extension is not available by default and needs to be enabled +explicitly by adding it to the sieve_extensions setting. + +The following settings can be configured for the editheader extension (default +values are indicated): + +sieve_editheader_max_header_size = 2048 + The maximum size in bytes of a header field value passed to the addheader + command. The minimum value for this setting is 1024 bytes. The value is in + bytes, unless followed by a k(ilo). + +sieve_editheader_forbid_add = + A space-separated list of headers that cannot be added to the message header. + Addition of the `Subject:' header cannot be prohibited, as required by the RFC + specification. Therefore, adding this header to this setting has no effect. + +sieve_editheader_forbid_delete = + A space-separated list of headers that cannot be deleted from the message + header. Deleting the `Received:' and `Auto-Submitted:' fields is always + forbidden, while removing the `Subject:' header cannot be prohibited, + as required by the RFC specification. Therefore, adding one of these headers + to this setting has no effect. + +sieve_editheader_protected = + A space-separated list of headers that cannot be added to or deleted from + the message header. This setting is provided for backwards compatibility. It + is a combination of the sieve_editheader_forbid_add and + sieve_editheader_forbid_delete settings. The same limitations apply. + +Invalid values for the settings above will make the Sieve interpreter log +a warning and revert to the default values. + +Example +======= + +plugin { + # Use editheader + sieve_extensions = +editheader + + # Header fiels must not exceed one 1k + sieve_editheader_max_header_size = 1k + + # Protected special headers + sieve_editheader_forbid_add = X-Verified + sieve_editheader_forbid_delete = X-Verified X-Seen +} + diff --git a/pigeonhole/doc/extensions/include.txt b/pigeonhole/doc/extensions/include.txt new file mode 100644 index 0000000..44cfacc --- /dev/null +++ b/pigeonhole/doc/extensions/include.txt @@ -0,0 +1,32 @@ +Include Extension + +Relevant Specifications +======================= + + draft-ietf-sieve-include-05 - doc/rfc/draft-ietf-sieve-include-05.txt + +Description +=========== + +The Sieve include extension permits users to include one Sieve script into +another. This can make managing large scripts or multiple sets of scripts much +easier, and allows a site and its users to build up libraries of scripts. Users +are able to include their own personal scripts or site-wide scripts. + +Included scripts can include more scripts of their own, yielding a tree of +included scripts with the main script (typically the user's personal script) at +its root. + +Configuration +============= + +The include extension is available by default. The include extension has its own +specific settings. The following settings can be configured for the include +extension (default values are indicated): + +sieve_include_max_includes = 255 + The maximum number of scripts that may be included. This is the total number + of scripts involved in the include tree. + +sieve_include_max_nesting_depth = 10 + The maximum nesting depth for the include tree. diff --git a/pigeonhole/doc/extensions/spamtest-virustest.txt b/pigeonhole/doc/extensions/spamtest-virustest.txt new file mode 100644 index 0000000..2ac8ad4 --- /dev/null +++ b/pigeonhole/doc/extensions/spamtest-virustest.txt @@ -0,0 +1,140 @@ +Spamtest and Virustest Extensions + +Relevant Specifications +======================= + + RFC5235 - doc/rfc/spamvirustest.rfc5235.txt + +Description +=========== + +Using the spamtest and virustest extensions (RFC 5235), the Sieve language +provides a uniform and standardized command interface for evaluating spam and +virus tests performed on the message. Users no longer need to know what headers +need to be checked and how the scanner's verdict is represented in the header +field value. They only need to know how to use the spamtest (spamtestplus) and +virustest extensions. This also gives GUI-based Sieve editors the means to +provide a portable and easy to install interface for spam and virus filter +configuration. The burden of specifying which headers need to be checked and how +the scanner output is represented falls onto the Sieve administrator. + +Configuration +============= + +The spamtest, spamtestplus and virustest extensions are not enabled by default +and thus need to be enabled explicitly using the sieve_extensions setting. + +The following settings need to be configured for using the spamtest and +spamtestplus extensions. The virustest extension has identical configuration +settings, but with a `sieve_virustest_' prefix instead of a `sieve_spamtest_' +prefix: + +sieve_spamtest_status_type = "score" / "strlen" / "text" + This specifies the type of status result that the spam/virus scanner produces. + This can either be a numeric score ("score"), a string of identical characters + ("strlen"), e.g. '*******', or a textual description, e.g. `Spam' + or `Not Spam'. + +sieve_spamtest_status_header = <header-field> [ ":" <regexp> ] + This specifies the header field that contains the result information of the + spam scanner and it may express the syntax of the content of the header. If no + matching header is found in the message, the spamtest command will match + against "0". + + This is a structured setting. The first part specifies the header field name. + Optionally, an extended POSIX regular expression follows the header field + name, separated by a colon. Any whitespace directly following the colon is not + part of the regular expression. If the regular expression is omitted, any + header content is accepted and the full header value is used. When a regular + expression is used, it must specify one match value (inside brackets) that + yields the desired spam scanner result. If the header does not match the + regular expression or if no value match is found, the spamtest will match + against "0". + +sieve_spamtest_max_value = + This statically specifies the maximum value a numeric spam score can have. + +sieve_spamtest_max_header = <header-field> [ ":" <regexp> ] + Some spam scanners include the maximum score value in one of their status + headers. Using this setting, this maximum can be extracted from the message + itself instead of specifying the maximum manually using the setting + `sieve_spamtest_max_value' explained above. The syntax is identical to the + `sieve_spamtext_status_header' setting. + +sieve_spamtest_text_valueX = + When the `sieve_spamtest_status_type' setting is set to "text", these settings + specify that the spamtest command will match against "X" when the specified + string is equal to the text (extracted) from the status header. For spamtest, + values of X between 0 and 10 are recognized, while virustest only uses values + between 0 and 5. + +Examples +======== + +This section shows several configuration examples. Each example shows a specimen +of valid virus/spam test headers that the given configuration will work on. + +Example 1 +--------- + +Spam header: `X-Spam-Score: No, score=-3.2' + +plugin { + sieve_extensions = +spamtest +spamtestplus + + sieve_spamtest_status_type = score + sieve_spamtest_status_header = \ + X-Spam-Score: [[:alnum:]]+, score=(-?[[:digit:]]+\.[[:digit:]]) + sieve_spamtest_max_value = 5.0 +} + +Example 2 +--------- + +Spam header: `X-Spam-Status: Yes' + +plugin { + sieve_extensions = +spamtest +spamtestplus + + sieve_spamtest_status_type = text + sieve_spamtest_status_header = X-Spam-Status + sieve_spamtest_text_value1 = No + sieve_spamtest_text_value10 = Yes +} + +Example 3 +--------- + +Spam header: `X-Spam-Score: sssssss' + +plugin { + sieve_extensions = +spamtest +spamtestplus + + sieve_spamtest_status_header = X-Spam-Score + sieve_spamtest_status_type = strlen + sieve_spamtest_max_value = 5 +} + +Example 4 +--------- + +Spam header: `X-Spam-Score: status=3.2 required=5.0' +Virus header: `X-Virus-Scan: Found to be clean.' + +plugin { + sieve_extensions = +spamtest +spamtestplus +virustest + + sieve_spamtest_status_type = score + sieve_spamtest_status_header = \ + X-Spam-Score: score=(-?[[:digit:]]+\.[[:digit:]]).* + sieve_spamtest_max_header = \ + X-Spam-Score: score=-?[[:digit:]]+\.[[:digit:]] required=([[:digit:]]+\.[[:digit:]]) + + sieve_virustest_status_type = text + sieve_virustest_status_header = X-Virus-Scan: Found to be (.+)\. + sieve_virustest_text_value1 = clean + sieve_virustest_text_value5 = infected +} + + + diff --git a/pigeonhole/doc/extensions/vacation.txt b/pigeonhole/doc/extensions/vacation.txt new file mode 100644 index 0000000..3e405a9 --- /dev/null +++ b/pigeonhole/doc/extensions/vacation.txt @@ -0,0 +1,122 @@ +Vacation Extension + +Relevant specifications +======================= + + RFC5230 - doc/rfc/vacation.rfc5230.txt + RFC6131 - doc/rfc/vacation-seconds.rfc6131.txt + +Description +=========== + +The Sieve vacation extension [RFC5230] defines a mechanism to generate automatic +replies to incoming email messages. It takes various precautions to make sure +replies are only sent when appropriate. Script authors specify how often replies +are sent to a particular contact. In the original vacation extension, this +interval is specified in days with a minimum of one day. When more granularity +is necessary and particularly when replies must be sent more frequently than one +day, the vacation-seconds extension [RFC6131] can be used. This allows +specifying the minimum reply interval in seconds with a minimum of zero (reply +is then always sent), depending on administrator configuration. + +Configuration +============= + +The vacation extension is available by default. In contrast, the +vacation-seconds extension - which implies the vacation extension when used - is +not available by default and needs to be enabled explicitly by adding it to the +sieve_extensions setting. The configuration also needs to be adjusted +accordingly to allow a non-reply period of less than a day. + +The vacation and vacation-seconds extensions have their own specific settings. +The settings that specify a period are specified in s(econds), unless followed +by a d(ay), h(our) or m(inute) specifier character. + +The following settings can be configured for the vacation extension (default +values are indicated): + +sieve_vacation_min_period = 1d + This specifies the minimum period that can be specified for the :days and + :seconds tags of the vacation command. A minimum of 0 indicates that users are + allowed to make the Sieve interpreter send a vacation response message for + every incoming message that meets the other reply criteria (refer to RFC5230). + A value of zero is however not recommended. + +sieve_vacation_max_period = 0 + This specifies the maximum period that can be specified for the :days tag of + the vacation command. The configured value must be larger than the + sieve_vacation_min_period setting. A value of 0 has a special meaning: it + indicates that there is no upper limit. + +sieve_vacation_default_period = 7d + This specifies the default period that is used when no :days or :seconds tag + is specified. The configured value must lie between the + sieve_vacation_min_period and sieve_vacation_max_period. + +sieve_vacation_max_subject_codepoints = 256 + The maximum number of Unicode codepoints used in the Subject header generated + for the outgoing vacation message. When composite characters are involved, + the number of actual charactes in the Subject text can be less than this + number, otherwise it is equal. When the subject text exceeds the limit, it is + truncated and the removed part is replaced with an ellipsis character ('...'). + +sieve_vacation_use_original_recipient = no + This specifies whether the original envelope recipient should be used in the + check for implicit delivery. The vacation command checks headers of the + incoming message, such as To: and Cc: for the address of the recipient, to + verify that the message is explicitly addressed at the recipient. If the + recipient address is not found, the vacation action will not trigger a + response to prevent sending a reply when it is not appropriate. Normally only + the final recipient address is used in this check. This setting allows + including the original recipient specified in the SMTP session if available. + This is useful to handle mail accounts with aliases. Use this option with + caution: if you are using aliases that point to more than a single account, + senders can get multiple vacation responses for a single message. + +sieve_vacation_dont_check_recipient = no + This disables the checks for implicit delivery entirely. This means that the + vacation command does not verify that the message is explicitly addressed at + the recipient. Use this option with caution. Specifying 'yes' will violate the + Sieve standards and can cause vacation replies to be sent for messages not + directly addressed at the recipient. + +sieve_vacation_send_from_recipient = no + This setting determines whether vacation messages are sent with the SMTP MAIL + FROM envelope address set to the recipient address of the Sieve script owner. + Normally this is set to <>, which is the default as recommended in the + specification. This is meant to prevent mail loops. However, there are + situations for which a valid sender address is required and this setting can + be used to accommodate for those. + +sieve_vacation_to_header_ignore_envelope = no + With this setting disabled (the default), the "To:" header in the composed + vacation reply is determined by finding the envelope sender address in the + first "Sender:", "Resent-From:", or "From:" headers (in that order). The + matching address is used in the "To:" header of the reply, which then includes + the "phrase" part of the address; i.e., usually the name of the person + associated with that address. If no match is found, the bare envelope sender + address is used instead. In contrast, with this setting enabled, the envelope + is completely ignored for this purpose and the first address found from the + mentioned headers is always used. This is useful when the envelope sender is + mangled somehow; e.g. by the Sender Rewriting Scheme (SRS). + +Invalid values for the settings above will make the Sieve interpreter log a +warning and revert to the default values. + +Example +======= + +plugin { + # Use vacation-seconds + sieve_extensions = +vacation-seconds + + # One hour at minimum + sieve_vacation_min_period = 1h + + # Ten days default + sieve_vacation_min_period = 10d + + # Thirty days at maximum + sieve_vacation_max_period = 30d +} + diff --git a/pigeonhole/doc/extensions/vnd.dovecot.environment.txt b/pigeonhole/doc/extensions/vnd.dovecot.environment.txt new file mode 100644 index 0000000..59ed93a --- /dev/null +++ b/pigeonhole/doc/extensions/vnd.dovecot.environment.txt @@ -0,0 +1,48 @@ +Vnd.dovecot.environment Extension + +Relevant specifications +======================= + + doc/rfc/spec-bosch-sieve-dovecot-environment.txt + +Description +=========== + +The "vnd.dovecot.environment" extension builds upon the existing standard +"environment" extension, which allows Sieve scripts to access information about +their execution context, such as the name and version of the Sieve interpreter +implementation. The new "vnd.dovecot.environment" extension adds a few more +environment items that can be accessed by Sieve scripts. Additionally, it makes +the environment items available directly as variables [VARIABLES]. + +Configuration +============= + +The "vnd.dovecot.environment" extension is not available by default; it needs +to be added to the sieve_extensions or (rather) the sieve_global extensions +setting. + +Currently, the "vnd.dovecot.environment" extension has no specific settings. +However, this extension adds environment items with a "vnd.dovecot.config." +prefix that can be used to access part of the Dovecot configuration. An +environment item named "vnd.dovecot.config.identifier" yields the value of a +plugin setting called "sieve_env_identifier". + +Example +======= + +With the following configuration: + +plugin { + sieve = ~/.dovecot.sieve + + sieve_env_reject_reason = Please don't mail me. +} + +The following script will reject the message with the configured reason: + +require "reject"; +require "variables"; +require "vnd.dovecot.environment"; + +reject "${vnd.dovecot.config.reject_reason}"; diff --git a/pigeonhole/doc/extensions/vnd.dovecot.report.txt b/pigeonhole/doc/extensions/vnd.dovecot.report.txt new file mode 100644 index 0000000..c512607 --- /dev/null +++ b/pigeonhole/doc/extensions/vnd.dovecot.report.txt @@ -0,0 +1,54 @@ +Vnd.dovecot.report Extension + +Relevant specifications +======================= + + doc/rfc/spec-bosch-sieve-report.txt + +Description +=========== + +The "vnd.dovecot.report" extension provides the means to send Messaging Abuse +Reporting Format (MARF) reports (RFC 5965). This format is intended for +communications regarding email abuse and related issues. The "report" command +allows (partially) automating the exchange of these reports, which is +particularly useful when the Sieve script is executed for an IMAP event +(RFC 6785) that is triggered by direct user action. + +Configuration +============= + +The "vnd.dovecot.report" extension is not available by default; it needs +to be added to the sieve_extensions setting (or any of the alternatives). + +The "vnd.dovecot.report" extension has its own specific settings. The following +settings can be configured for the vacation extension (default values are +indicated): + + sieve_report_from = postmaster + Specifies what address is used for the "From:" header field in reports. + The following values are supported for this setting: + + "postmaster" - The postmaster_address configured for the LDA (default). + "sender" - The sender address is used. + "recipient" - The final recipient address is used. + "orig_recipient" - The original recipient is used. + "user_email" - The user's primary address is used. This is + configured with the "sieve_user_email" setting. If + that setting is unconfigured, "user_mail" is equal to + "recipient". + "<user@domain>" - Redirected messages are always sent from user@domain. + The angle brackets are mandatory. The null "<>" address + not supported and interpreted as "postmaster". + +Invalid values for the settings above will make the Sieve interpreter log a +warning and revert to the default values. + +Example +======= + +plugin { + sieve = file:~/sieve;active=~/.dovecot.sieve + + sieve_report_from = <reporter@example.com> +} diff --git a/pigeonhole/doc/locations/Makefile.am b/pigeonhole/doc/locations/Makefile.am new file mode 100644 index 0000000..d6be0df --- /dev/null +++ b/pigeonhole/doc/locations/Makefile.am @@ -0,0 +1,13 @@ +docfiles = \ + dict.txt \ + file.txt \ + ldap.txt + +if BUILD_DOCS +locations_docdir = $(sieve_docdir)/locations +locations_doc_DATA = $(docfiles) +endif + +EXTRA_DIST = \ + $(docfiles) + diff --git a/pigeonhole/doc/locations/Makefile.in b/pigeonhole/doc/locations/Makefile.in new file mode 100644 index 0000000..894eda9 --- /dev/null +++ b/pigeonhole/doc/locations/Makefile.in @@ -0,0 +1,576 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = doc/locations +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(locations_docdir)" +DATA = $(locations_doc_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +docfiles = \ + dict.txt \ + file.txt \ + ldap.txt + +@BUILD_DOCS_TRUE@locations_docdir = $(sieve_docdir)/locations +@BUILD_DOCS_TRUE@locations_doc_DATA = $(docfiles) +EXTRA_DIST = \ + $(docfiles) + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/locations/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/locations/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-locations_docDATA: $(locations_doc_DATA) + @$(NORMAL_INSTALL) + @list='$(locations_doc_DATA)'; test -n "$(locations_docdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(locations_docdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(locations_docdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(locations_docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(locations_docdir)" || exit $$?; \ + done + +uninstall-locations_docDATA: + @$(NORMAL_UNINSTALL) + @list='$(locations_doc_DATA)'; test -n "$(locations_docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(locations_docdir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(locations_docdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-locations_docDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-locations_docDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-locations_docDATA install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-locations_docDATA + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/doc/locations/dict.txt b/pigeonhole/doc/locations/dict.txt new file mode 100644 index 0000000..59cf958 --- /dev/null +++ b/pigeonhole/doc/locations/dict.txt @@ -0,0 +1,145 @@ +DICT Sieve Script Location Type + +Description +=========== + +This location type is used to retrieve Sieve scripts from a Dovecot dict lookup. +Such dictionaries use a file or an SQL database as backend. Refer to the Dovecot +dict documentation for more information on dict lookups. + +To retrieve a Sieve script from the dict database, two lookups are performed. +First, the name of the Sieve script is queried from the dict path +`/priv/sieve/name/<name>'. If the Sieve script exists, this yields a data ID +which in turn points to the actual script text. The script text is subsequently +queried from the dict path '/priv/sieve/data/<dict-id>'. + +The second query is only necessary when no compiled binary is available or when +the script has changed and needs to be recompiled. The data ID is used to detect +changes in the dict's underlying database. Changing a Sieve script in the +database must be done by first making a new script data item with a new data ID. +Then, the mapping from name to data ID must be changed to point to the new +script text, thereby changing the data ID returned from the name lookup, i.e. +the first query mentioned above. Script binaries compiled from Sieve scripts +contained in a dict database record the data ID. While the data ID contained in +the binary is identical to the one returned from the dict lookup, the binary is +assumed up-to-date. When the returned data ID is different, the new script text +is retrieved using the second query and compiled into a new binary containing +the updated data ID. + +Note that, by default, compiled binaries are not stored at all for Sieve scripts +retrieved from a dict database. The bindir= option needs to be specified in the +location specification. Refer to the INSTALL file for more general information +about configuration of script locations. + +Configuration +============= + +The script location syntax is specified as follows: + +location = dict:<dict-uri>[;<option>[=<value>][;...]] + +The following additional options are recognized: + + user=<username> + Overrides the user name used for the dict lookup. Normally, the name of the + user running the Sieve interpreter is used. + +If the name of the Script is left unspecified and not otherwise provided by the +Sieve interpreter, the name defaults to `default'. + +Examples +======== + +Example 1 +--------- + +This example is mainly useful for performing a quick test of the dict location +configuration without configuring an actual (SQL) database. For this example, a +very simple file dict is assumed to be contained in the file +/etc/dovecot/sieve.dict: + +priv/sieve/name/keep +1 +priv/sieve/name/discard +2 +priv/sieve/name/spam +3 +priv/sieve/data/1 +keep; +priv/sieve/data/2 +discard; +priv/sieve/data/3 +require ["fileinto", "mailbox"]; fileinto :create "spam"; + +To use this file dict for the main active script, you can change the +configuration as follows (e.g. in /etc/dovecot/conf.d/90-sieve.conf): + +plugin { + sieve = dict:file:/etc/dovecot/sieve.dict;name=keep;bindir=~/.sieve-bin +} + +The Sieve script named "keep" is retrieved from the file dict as the main +script. Binaries are stored in the ~/.sieve-bin directory. + +Example 2 +--------- + +This example uses a PostgreSQL database. Our database contains the following +table: + +CREATE TABLE user_sieve_scripts ( + id integer, + username varchar(40), + script_name varchar(256), + script_data varchar(10240), + + PRIMARY KEY (id), + UNIQUE(username, script_name) +); + +We create a file /etc/dovecot/dict-sieve-sql.conf with the following content: + +connect = host=localhost dbname=dovecot user=dovecot password=password +map { + pattern = priv/sieve/name/$script_name + table = user_sieve_scripts + username_field = username + value_field = id + fields { + script_name = $script_name + } +} +map { + pattern = priv/sieve/data/$id + table = user_sieve_scripts + username_field = username + value_field = script_data + fields { + id = $id + } +} + +These are the mappings used by the SQL dict. The first mapping is the name query +that yields the id of the Sieve script. The second mapping is the query used to +retrieve the Sieve script itself. + +Much like the dict configuration for mailbox quota, it is often not possible to +directly use an SQL dict because the SQL drivers are not linked to binaries such +as dovecot-lda and lmtp. You need to use the dict proxy service. Add the dict +URI to the dict section (typically located in your main dovecot.conf): + +dict { + sieve = pgsql:/etc/dovecot/dict-sieve-sql.conf.ext +} + +To use this SQL dict for the main active script, you can change the +configuration as follows (e.g. in /etc/dovecot/conf.d/90-sieve.conf): + +plugin { + sieve = dict:proxy::sieve;name=active;bindir=~/.sieve-bin +} + +This uses the proxy dict uri `proxy::sieve'. This refers to the `sieve =' entry +in the dict {...} section above. With this configuration, a Sieve script called +"main" is retrieved from the SQL dict. Binaries are stored in the ~/.sieve-bin +directory. diff --git a/pigeonhole/doc/locations/file.txt b/pigeonhole/doc/locations/file.txt new file mode 100644 index 0000000..1c291d9 --- /dev/null +++ b/pigeonhole/doc/locations/file.txt @@ -0,0 +1,48 @@ +FILE Sieve Script Location Type + +Description +=========== + +This location type is used to retrieve Sieve scripts from the file system. The +location can either point to a directory or to a regular file. If the location +points to a directory, a script called "name" is retrieved by reading a file +from that directory with the file name "name.sieve". + +When this location type is involved in a sieve_before/sieve_after script +sequence and the location points to a directory, all files in that directory +with a ".sieve" extension are part of the sequence. The sequence order of the +scripts in that directory is determined by the file names, using a normal 8bit +per-character comparison. + +Unless overridden using the `bindir=<path>' location option, compiled binaries +for scripts retrieved from the `file' location type are by default stored in the +same directory as where the script file was found if possible. Refer to the +INSTALL file for more general information about configuration of script +locations. + +Configuration +============= + +The script location syntax is specified as follows: + +location = file:<path>[;<option>[=<value>][;...]] + +The following additional options are recognized: + + active=<path> + When ManageSieve is used, one script in the storage can be active; i.e., + evaluated at delivery. For the `file' location, the active script in the + storage directory is pointed to by a symbolic link. This option configures + where this symbolic link is located. If the `file' location path points to + a regular file, this setting has no effect (and ManageSieve cannot be used). + +Example +======= + +plugin { + ... + sieve = file:~/sieve;active=~/.dovecot.sieve + + sieve_default = file:/var/lib/dovecot/;name=default +} + diff --git a/pigeonhole/doc/locations/ldap.txt b/pigeonhole/doc/locations/ldap.txt new file mode 100644 index 0000000..e69b1ee --- /dev/null +++ b/pigeonhole/doc/locations/ldap.txt @@ -0,0 +1,73 @@ +LDAP Sieve Script Location Type + +Description +=========== + +This location type is used to retrieve Sieve scripts from an LDAP database. To +retrieve a Sieve script from the LDAP database, at most two lookups are +performed. First, the LDAP entry containing the Sieve script is searched using +the specified LDAP search filter. If the LDAP entry changed since it was last +retrieved (or it was never retieved before), the attribute containing the actual +Sieve script is retrieved in a second lookup. In the first lookup, a special +attribute is read and checked for changes. Usually, this is the +`modifyTimestamp' attribute, but an alternative can be configured. + +Note that, by default, compiled binaries are not stored at all for Sieve scripts +retrieved from an LDAP database. The bindir= option needs to be specified in the +location specification. Refer to the INSTALL file for more general information +about configuration of script locations. + +Depending on how Pigeonhole was configured and compiled (refer to INSTALL file +for more information), LDAP support may only be available from a plugin called +`sieve_storage_ldap'. + +Configuration +============= + +If support for the LDAP location type is compiled as a plugin, it needs to be +added to the sieve_plugins setting before it can be used, e.g.: + +sieve_plugins = sieve_storage_ldap + +The script location syntax is specified as follows: + +location = ldap:<config-file>[;<option>[=<value>][;...]] + +The <config-file> is a filesystem path that points to a configuration file +containing the actual configuration for this LDAP script location. + +The following additional location options are recognized: + + user=<username> + Overrides the user name used for the lookup. Normally, the name of the + user running the Sieve interpreter is used. + +If the name of the Script is left unspecified and not otherwise provided by the +Sieve interpreter, the name defaults to `default'. + +The configuration file is based on the auth userdb/passdb LDAP configuration +(refer to Dovecot wiki at http://wiki2.dovecot.org/AuthDatabase/LDAP). The +following options are specific to the Sieve ldap location type: + + sieve_ldap_filter = (&(objectClass=posixAccount)(uid=%u)) + The LDAP search filter that is used to find the entry containing the Sieve + script. + + sieve_ldap_script_attr = mailSieveRuleSource + The name of the attribute containing the Sieve script itself. + + sieve_ldap_mod_attr = modifyTimestamp + The name of the attribute used to detect modifications to the LDAP entry. + +Examples +======== + +plugin { + sieve = ldap:/etc/dovecot/sieve-ldap.conf;bindir=~/.sieve-bin/ +} + +An example LDAP location configuration is available in this package as +doc/example-config/sieve-ldap.conf. + + + diff --git a/pigeonhole/doc/man/Makefile.am b/pigeonhole/doc/man/Makefile.am new file mode 100644 index 0000000..2d2af01 --- /dev/null +++ b/pigeonhole/doc/man/Makefile.am @@ -0,0 +1,46 @@ +pkgsysconfdir = $(sysconfdir)/dovecot +rundir = ${prefix}/var/run/dovecot + +SUFFIXES = .1.in .1 .7.in .7 + +dist_man1_MANS = \ + sieved.1 + +nodist_man1_MANS = \ + doveadm-sieve.1 \ + sievec.1 \ + sieve-dump.1 \ + sieve-test.1 \ + sieve-filter.1 + +nodist_man7_MANS = \ + pigeonhole.7 + +man_includefiles = \ + $(srcdir)/global-options-formatter.inc \ + $(srcdir)/global-options.inc \ + $(srcdir)/option-A.inc \ + $(srcdir)/option-S-socket.inc \ + $(srcdir)/option-u-user.inc \ + $(srcdir)/reporting-bugs.inc + +EXTRA_DIST = \ + doveadm-sieve.1.in \ + sievec.1.in \ + sieve-dump.1.in \ + sieve-test.1.in \ + sieve-filter.1.in \ + pigeonhole.7.in \ + sed.sh \ + $(man_includefiles) + +CLEANFILES = $(nodist_man1_MANS) $(nodist_man7_MANS) + +.1.in.1: $(man_includefiles) Makefile + $(SHELL) $(srcdir)/sed.sh $(srcdir) $(rundir) $(pkgsysconfdir) \ + $(pkglibexecdir) < $< > $@ +.7.in.7: $(man_includefiles) Makefile + $(SHELL) $(srcdir)/sed.sh $(srcdir) $(rundir) $(pkgsysconfdir) \ + $(pkglibexecdir) < $< > $@ + + diff --git a/pigeonhole/doc/man/Makefile.in b/pigeonhole/doc/man/Makefile.in new file mode 100644 index 0000000..b2bc957 --- /dev/null +++ b/pigeonhole/doc/man/Makefile.in @@ -0,0 +1,675 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = doc/man +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man1dir = $(mandir)/man1 +am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man7dir)" +man7dir = $(mandir)/man7 +NROFF = nroff +MANS = $(dist_man1_MANS) $(nodist_man1_MANS) $(nodist_man7_MANS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(dist_man1_MANS) $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkgsysconfdir = $(sysconfdir)/dovecot +rundir = ${prefix}/var/run/dovecot +SUFFIXES = .1.in .1 .7.in .7 +dist_man1_MANS = \ + sieved.1 + +nodist_man1_MANS = \ + doveadm-sieve.1 \ + sievec.1 \ + sieve-dump.1 \ + sieve-test.1 \ + sieve-filter.1 + +nodist_man7_MANS = \ + pigeonhole.7 + +man_includefiles = \ + $(srcdir)/global-options-formatter.inc \ + $(srcdir)/global-options.inc \ + $(srcdir)/option-A.inc \ + $(srcdir)/option-S-socket.inc \ + $(srcdir)/option-u-user.inc \ + $(srcdir)/reporting-bugs.inc + +EXTRA_DIST = \ + doveadm-sieve.1.in \ + sievec.1.in \ + sieve-dump.1.in \ + sieve-test.1.in \ + sieve-filter.1.in \ + pigeonhole.7.in \ + sed.sh \ + $(man_includefiles) + +CLEANFILES = $(nodist_man1_MANS) $(nodist_man7_MANS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .1.in .1 .7.in .7 +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/man/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/man/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man1: $(dist_man1_MANS) $(nodist_man1_MANS) + @$(NORMAL_INSTALL) + @list1='$(dist_man1_MANS) $(nodist_man1_MANS)'; \ + list2=''; \ + test -n "$(man1dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.1[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ + done; } + +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list='$(dist_man1_MANS) $(nodist_man1_MANS)'; test -n "$(man1dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) +install-man7: $(nodist_man7_MANS) + @$(NORMAL_INSTALL) + @list1='$(nodist_man7_MANS)'; \ + list2=''; \ + test -n "$(man7dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man7dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man7dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.7[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^7][0-9a-z]*$$,7,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man7dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man7dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man7dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man7dir)" || exit $$?; }; \ + done; } + +uninstall-man7: + @$(NORMAL_UNINSTALL) + @list='$(nodist_man7_MANS)'; test -n "$(man7dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^7][0-9a-z]*$$,7,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man7dir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(MANS) +installdirs: + for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man7dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man1 install-man7 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-man + +uninstall-man: uninstall-man1 uninstall-man7 + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-man1 install-man7 install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-man uninstall-man1 uninstall-man7 + +.PRECIOUS: Makefile + + +.1.in.1: $(man_includefiles) Makefile + $(SHELL) $(srcdir)/sed.sh $(srcdir) $(rundir) $(pkgsysconfdir) \ + $(pkglibexecdir) < $< > $@ +.7.in.7: $(man_includefiles) Makefile + $(SHELL) $(srcdir)/sed.sh $(srcdir) $(rundir) $(pkgsysconfdir) \ + $(pkglibexecdir) < $< > $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/doc/man/doveadm-sieve.1.in b/pigeonhole/doc/man/doveadm-sieve.1.in new file mode 100644 index 0000000..aed9337 --- /dev/null +++ b/pigeonhole/doc/man/doveadm-sieve.1.in @@ -0,0 +1,125 @@ +.\" Copyright (c) 2010-2018 Pigeonhole authors, see the included COPYING file +.TH DOVEADM\-SIEVE 1 "2016-02-29" "Pigeonhole for Dovecot v2.4" "Pigeonhole" +.SH NAME +doveadm\-sieve \- Commands related to handling Sieve scripts +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter "] " sieve_cmd " [" options "] [" arguments ] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +.PP +The +.B doveadm sieve +commands are part of the Pigeonhole Project (\fBpigeonhole\fR(7)), which adds +Sieve (RFC 5228) and ManageSieve (RFC 5804) support to the Dovecot secure IMAP +and POP3 server (\fBdovecot\fR(1)). The +.B doveadm sieve +commands can be used to manage Sieve filtering. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options-formatter@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I scriptname +Is the name of a +.IR Sieve\ script , +as visible to ManageSieve clients. +.IP +NOTE: For Sieve scripts that are stored on disk, this is the filename without the +".sieve" extension. +.\"------------------------------------------------------------------------ +.SH COMMANDS +.SS sieve put +.B doveadm sieve put +[\fB\-A\fP|\fB\-u\fP \fIuser\fP] +[\fB\-S\fP \fIsocket_path\fP] +.RB [ \-a ] +.IR scriptname +.PP +This command puts one new Sieve script in the script storage. The script +is read from standard input. If the script compiles successfully, it is stored +under the provided +.IR scriptname\ . +If the +.B \-a +option is present, the Sieve script is subsequently marked as the active script +for execution at delivery. +.\"------------------------------------------------------------------------ +.SS sieve get +.B doveadm sieve get +[\fB\-A\fP|\fB\-u\fP \fIuser\fP] +[\fB\-S\fP \fIsocket_path\fP] +.I scriptname +.PP +This command retrieves the Sieve script named +.IR scriptname . +.\"------------------------------------------------------------------------ +.SS sieve delete +.B doveadm sieve delete +[\fB\-A\fP|\fB\-u\fP \fIuser\fP] +[\fB\-S\fP \fIsocket_path\fP] +.RB [ \-a ] +.IR scriptname\ ... +.PP +This command deletes one or more Sieve scripts. The deleted script may not be the +active script, unless the +.B \-a +option is present. +.\"------------------------------------------------------------------------ +.SS sieve list +.B doveadm sieve list +[\fB\-A\fP|\fB\-u\fP \fIuser\fP] +[\fB\-S\fP \fIsocket_path\fP] +.I scriptname +.PP +Use this command to get an overview of existing Sieve scripts. +.\"------------------------------------------------------------------------ +.SS sieve rename +.B doveadm sieve rename +[\fB\-A\fP|\fB\-u\fP \fIuser\fP] +[\fB\-S\fP \fIsocket_path\fP] +.I old_name +.I new_name +.PP +The +.B sieve rename +command is used to rename the Sieve script +.I old_name +to +.IR new_name . +.\"------------------------------------------------------------------------ +.SS sieve activate +.B doveadm sieve activate +[\fB\-A\fP|\fB\-u\fP \fIuser\fP] +[\fB\-S\fP \fIsocket_path\fP] +.IR scriptname +.PP +This command marks the Sieve script named +.I scriptname +as the active script for execution at delivery. +.\"------------------------------------------------------------------------ +.SS sieve deactivate +.B doveadm sieve deactivate +[\fB\-A\fP|\fB\-u\fP \fIuser\fP] +[\fB\-S\fP \fIsocket_path\fP] +.I scriptname +.PP +This command deactivates Sieve processing. +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1) +.BR dovecot\-lda (1), +.BR pigeonhole (7) diff --git a/pigeonhole/doc/man/global-options-formatter.inc b/pigeonhole/doc/man/global-options-formatter.inc new file mode 100644 index 0000000..cb792e1 --- /dev/null +++ b/pigeonhole/doc/man/global-options-formatter.inc @@ -0,0 +1,46 @@ +.SH OPTIONS +Global +.BR doveadm (1) +.IR options : +.TP +.B \-D +Enables verbosity and debug messages. +.TP +.BI \-f\ formatter +Specifies the +.I formatter +for formatting the output. +Supported formatters are: +.RS +.TP +.B flow +prints each line with +.IB key = value +pairs. +.TP +.B pager +prints each +.IR key :\ value +pair on its own line and separates records with form feed character +.RB ( ^L ). +.TP +.B tab +prints a table header followed by tab separated value lines. +.TP +.B table +prints a table header followed by adjusted value lines. +.RE +.TP +.BI \-o\ setting = value +Overrides the configuration +.I setting +from +.I @pkgsysconfdir@/dovecot.conf +and from the userdb with the given +.IR value . +In order to override multiple settings, the +.B \-o +option may be specified multiple times. +.TP +.B \-v +Enables verbosity, including progress counter. diff --git a/pigeonhole/doc/man/global-options.inc b/pigeonhole/doc/man/global-options.inc new file mode 100644 index 0000000..bf99294 --- /dev/null +++ b/pigeonhole/doc/man/global-options.inc @@ -0,0 +1,21 @@ +.SH OPTIONS +Global +.BR doveadm (1) +.IR options : +.TP +.B \-D +Enables verbosity and debug messages. +.TP +.BI \-o\ setting = value +Overrides the configuration +.I setting +from +.I @pkgsysconfdir@/dovecot.conf +and from the userdb with the given +.IR value . +In order to override multiple settings, the +.B \-o +option may be specified multiple times. +.TP +.B \-v +Enables verbosity, including progress counter. diff --git a/pigeonhole/doc/man/option-A.inc b/pigeonhole/doc/man/option-A.inc new file mode 100644 index 0000000..256e939 --- /dev/null +++ b/pigeonhole/doc/man/option-A.inc @@ -0,0 +1,27 @@ +.TP +.B \-A +If the +.B \-A +option is present, the +.I command +will be performed for all users. +Using this option in combination with system users from +.B userdb { driver = passwd } +is not recommended, because it contains also users with a lower UID than +the one configured with the +.I first_valid_uid +setting. +.sp +When the SQL userdb module is used make sure that the +.I iterate_query +setting in +.I @pkgsysconfdir@/dovecot\-sql.conf.ext +matches your database layout. +When using the LDAP userdb module, make sure that the +.IR iterate_attrs " and " iterate_filter +settings in +.I @pkgsysconfdir@/dovecot-ldap.conf.ext +match your LDAP schema. +Otherwise +.BR doveadm (1) +will be unable to iterate over all users. diff --git a/pigeonhole/doc/man/option-S-socket.inc b/pigeonhole/doc/man/option-S-socket.inc new file mode 100644 index 0000000..2e0e374 --- /dev/null +++ b/pigeonhole/doc/man/option-S-socket.inc @@ -0,0 +1,10 @@ +.TP +.BI \-S\ socket_path +The option\(aqs argument is either an absolute path to a local UNIX domain +socket, or a hostname and port +.RI ( hostname : port ), +in order to connect a remote host via a TCP socket. +.sp +This allows an administrator to execute +.BR doveadm (1) +mail commands through the given socket. diff --git a/pigeonhole/doc/man/option-u-user.inc b/pigeonhole/doc/man/option-u-user.inc new file mode 100644 index 0000000..e861145 --- /dev/null +++ b/pigeonhole/doc/man/option-u-user.inc @@ -0,0 +1,20 @@ +.TP +.BI \-u\ user/mask +Run the +.I command +only for the given +.IR user . +It\(aqs also possible to use +.RB \(aq * \(aq +and +.RB \(aq ? \(aq +wildcards (e.g. \-u *@example.org). +.br +When neither the +.B \-A +option nor +.BI \-u\ user +was specified, the +.I command +will be executed with the environment of the +currently logged in user. diff --git a/pigeonhole/doc/man/pigeonhole.7.in b/pigeonhole/doc/man/pigeonhole.7.in new file mode 100644 index 0000000..18b081d --- /dev/null +++ b/pigeonhole/doc/man/pigeonhole.7.in @@ -0,0 +1,99 @@ +.\" Copyright (c) 2010-2018 Pigeonhole authors, see the included COPYING file +.TH "PIGEONHOLE" 7 "2015-02-21" "Pigeonhole for Dovecot v2.4" "Pigeonhole" +.\"------------------------------------------------------------------------ +.SH NAME +pigeonhole \- Overview of the Pigeonhole project\(aqs Sieve support for the +Dovecot secure IMAP and POP3 server +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +.PP +The Pigeonhole project <http://pigeonhole.dovecot.org> adds support for the +Sieve language (RFC 5228) and the ManageSieve protocol (RFC 5804) to the +Dovecot Secure IMAP and POP3 Server (\fBdovecot\fR(1)). In the literal sense, +a pigeonhole is a a hole or recess inside a dovecot for pigeons to nest in. +It is, however, also the name for one of a series of small, open compartments +in a cabinet used for filing or sorting mail. As a verb, it describes the act +of putting an item into one of those pigeonholes. The name \(dqPigeonhole\(dq +therefore well describes an important part of the functionality that this +project adds to Dovecot: sorting and filing e\-mail messages. +.PP +The Sieve language is used to specify how e\-mail needs to be processed. By +writing Sieve scripts, users can customize how messages are delivered, e.g. +whether they are forwarded or stored in special folders. Unwanted messages can +be discarded or rejected, and, when the user is not available, the Sieve +interpreter can send an automated reply. Above all, the Sieve language is meant +to be simple, extensible and system independent. And, unlike most other mail +filtering script languages, it does not allow users to execute arbitrary +programs. This is particularly useful to prevent virtual users from having full +access to the mail store. The intention of the language is to make it impossible +for users to do anything more complex (and dangerous) than write simple mail +filters. +.PP +Using the ManageSieve protocol, users can upload their Sieve scripts remotely, +without needing direct filesystem access through FTP or SCP. Additionally, a +ManageSieve server always makes sure that uploaded scripts are valid, preventing +compile failures at mail delivery. +.PP +The Pigeonhole project provides the following items: +.IP \(bu 4 +The LDA Sieve plugin for Dovecot\(aqs Local Delivery Agent (LDA) +(\fBdovecot\-lda\fR(1)) that facilitates the actual Sieve filtering upon +delivery. +.IP \(bu +The ManageSieve service that implements the ManageSieve protocol through which +users can remotely manage Sieve scripts on the server. +.IP \(bu +A plugin for Dovecot\(aqs +.BR doveadm (1) +command line tool that adds new the new +.BR doveadm-sieve (1) +commands for management of Sieve filtering. +.PP +The functionality and configuration of the LDA Sieve plugin and the ManageSieve +service is described in detail in the README and INSTALL files contained in the +Pigeonhole package and in the Dovecot Wiki +<http://wiki2.dovecot.org/Pigeonhole>. +.PP +The following command line tools are available outside of +.BR doveadm : +.TP +.BR sievec (1) +Compiles Sieve scripts into a binary representation for later execution. +.TP +.BR sieve\-test (1) +The universal Sieve test tool for testing the effect of a Sieve script on a +particular message. +.TP +.BR sieve\-filter (1) +Filters all messages in a particular source mailbox through a Sieve script. +.TP +.BR sieve\-dump (1) +Dumps the content of a Sieve binary file for (development) debugging purposes. +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH AUTHOR +Pigeonhole <http://pigeonhole.dovecot.org> and its manual pages were written by +the Pigeonhole authors <http://pigeonhole.dovecot.org/doc/AUTHORS>, mainly +Stephan Bosch <stephan at rename\-it.nl>, and are licensed under the terms of the +LGPLv2.1 license, which is the same license as Dovecot, see +<http://dovecot.org/doc/COPYING> for details. +.\"------------------------------------------------------------------------ +.SH "SEE ALSO" +.BR dovecot (1), +.BR dovecot\-lda (1), +.BR doveadm (1), +.BR doveadm-sieve (1), +.BR sieve\-dump (1), +.BR sieve\-test (1), +.BR sieve\-filter (1), +.BR sievec (1) +.\"------------------------------------- +.PP +Additional resources: +.IP "Dovecot website" +http://www.dovecot.org +.IP "Dovecot v2.x Wiki" +http://wiki2.dovecot.org/Pigeonhole +.IP "Pigeonhole website" +http://pigeonhole.dovecot.org diff --git a/pigeonhole/doc/man/reporting-bugs.inc b/pigeonhole/doc/man/reporting-bugs.inc new file mode 100644 index 0000000..1823ca2 --- /dev/null +++ b/pigeonhole/doc/man/reporting-bugs.inc @@ -0,0 +1,6 @@ +.SH REPORTING BUGS +Report bugs, including +.I doveconf \-n +output, to the Dovecot Mailing List <dovecot@dovecot.org>. +Information about reporting bugs is available at: +http://dovecot.org/bugreport.html diff --git a/pigeonhole/doc/man/sed.sh b/pigeonhole/doc/man/sed.sh new file mode 100644 index 0000000..6da3963 --- /dev/null +++ b/pigeonhole/doc/man/sed.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +SRCDIR="${1:-`pwd`}" +RUNDIR="${2:-/usr/local/var/run/dovecot}" +PKGSYSCONFDIR="${3:-/usr/local/etc/dovecot}" +PKGLIBEXECDIR="${4:-/usr/local/libexec/dovecot}" + +sed -e "/^@INCLUDE:global-options@$/{ + r ${SRCDIR}/global-options.inc + d + }" \ + -e "/^@INCLUDE:global-options-formatter@$/{ + r ${SRCDIR}/global-options-formatter.inc + d + }" \ + -e "/^@INCLUDE:option-A@$/{ + r ${SRCDIR}/option-A.inc + d + }" \ + -e "/^@INCLUDE:option-S-socket@$/{ + r ${SRCDIR}/option-S-socket.inc + d + }" \ + -e "/^@INCLUDE:option-u-user@$/{ + r ${SRCDIR}/option-u-user.inc + d + }" \ + -e "/^@INCLUDE:reporting-bugs@$/{ + r ${SRCDIR}/reporting-bugs.inc + d + }" | sed -e "s|@pkgsysconfdir@|${PKGSYSCONFDIR}|" \ + -e "s|@rundir@|${RUNDIR}|" \ + -e "s|@pkglibexecdir@|${PKGLIBEXECDIR}|" + diff --git a/pigeonhole/doc/man/sieve-dump.1.in b/pigeonhole/doc/man/sieve-dump.1.in new file mode 100644 index 0000000..7a79c68 --- /dev/null +++ b/pigeonhole/doc/man/sieve-dump.1.in @@ -0,0 +1,122 @@ +.\" Copyright (c) 2010-2018 Pigeonhole authors, see the included COPYING file +.TH "SIEVE\-DUMP" 1 "2016-04-05" "Pigeonhole for Dovecot v2.4" "Pigeonhole" +.\"------------------------------------------------------------------------ +.SH NAME +sieve\-dump \- Pigeonhole\(aqs Sieve script binary dump tool +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.B sieve\-dump +.RI [ options ] +.I sieve\-binary +.RI [ out\-file ] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +.PP +The \fBsieve\-dump\fP command is part of the Pigeonhole Project +(\fBpigeonhole\fR(7)), which adds Sieve (RFC 5228) support to the Dovecot +secure IMAP and POP3 server (\fBdovecot\fR(1)). +.PP +Using the \fBsieve\-dump\fP command, Sieve binaries, which are produced for +instance by \fBsievec\fP(1), can be transformed into a human\-readable textual +representation. This can provide valuable insight in how the Sieve script is +executed. This is also particularly useful to view corrupt binaries that can +result from bugs in the Sieve implementation. This tool is intended mainly for +development purposes, so normally system administrators and users will not need +to use this tool. +.PP +The format of the output is not explained here in detail, but it should be +relatively easy to understand. The Sieve binaries comprise a set of data blocks, +each of which can contain arbitrary data. For the base language implementation +two blocks are used: the first containing a specification of all required +language extensions and the second containing the main Sieve program. Compiled +Sieve programs are represented as flat byte code and therefore the dump of the +main program is a disassembly listing of the interpreter operations. Extensions +can define new operations and use additional blocks. Therefore, the output of +\fBsieve\-dump\fP depends greatly on the language extensions used when compiling +the binary. +.\"------------------------------------------------------------------------ +.SH OPTIONS +.TP +.BI \-c\ config\-file +Alternative Dovecot configuration file path. +.TP +.B \-D +Enable Sieve debugging. +.TP +.B \-h +Produce per\-block hexdump output of the whole binary instead of the normal +human\-readable output. +.TP +.BI \-o\ setting = value +Overrides the configuration +.I setting +from +.I @pkgsysconfdir@/dovecot.conf +and from the userdb with the given +.IR value . +In order to override multiple settings, the +.B \-o +option may be specified multiple times. +.TP +.BI \-u\ user +Run the Sieve script for the given \fIuser\fP. When omitted, the +.I command +will be executed with the environment of the currently logged in user. +.TP +.BI \-x\ extensions +Set the available extensions. The parameter is a space\-separated list of the +active extensions. By prepending the extension identifiers with \fB+\fP or +\fB\-\fP, extensions can be included or excluded relative to the configured set +of active extensions. If no extensions have a \fB+\fP or \fB\-\fP prefix, only +those extensions that are explicitly listed will be enabled. Unknown extensions +are ignored and a warning is produced. + +For example \fB\-x\fP \(dq+imapflags \-enotify\(dq will enable the deprecated +imapflags extension and disable the enotify extension. The rest of the active +extensions depends on the \fIsieve_extensions\fP and +\fIsieve_global_extensions\fP settings. By default, i.e. +when \fIsieve_extensions\fP and \fIsieve_global_extensions\fP remain +unconfigured, all supported extensions are available, except for deprecated +extensions or those that are still under development. + +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I sieve\-binary +Specifies the Sieve binary file that needs to be dumped. +.TP +.I out\-file +Specifies where the output must be written. This argument is optional. If +omitted, the output is written to \fBstdout\fR. +.\"------------------------------------------------------------------------ +.SH "EXIT STATUS" +.B sieve\-dump +will exit with one of the following values: +.TP 4 +.B 0 +Dump was successful. (EX_OK, EXIT_SUCCESS) +.TP +.B 1 +Operation failed. This is returned for almost all failures. +(EXIT_FAILURE) +.TP +.B 64 +Invalid parameter given. (EX_USAGE) +.\"------------------------------------------------------------------------ +.SH FILES +.TP +.I @pkgsysconfdir@/dovecot.conf +Dovecot\(aqs main configuration file. +.TP +.I @pkgsysconfdir@/conf.d/90\-sieve.conf +Sieve interpreter settings (included from Dovecot\(aqs main configuration file) +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH "SEE ALSO" +.BR dovecot (1), +.BR dovecot\-lda (1), +.BR sieve\-filter (1), +.BR sieve\-test (1), +.BR sievec (1), +.BR pigeonhole (7) diff --git a/pigeonhole/doc/man/sieve-filter.1.in b/pigeonhole/doc/man/sieve-filter.1.in new file mode 100644 index 0000000..1ce804b --- /dev/null +++ b/pigeonhole/doc/man/sieve-filter.1.in @@ -0,0 +1,253 @@ +.\" Copyright (c) 2010-2018 Pigeonhole authors, see the included COPYING file +.TH "SIEVE\-FILTER" 1 "2016-04-05" "Pigeonhole for Dovecot v2.4" "Pigeonhole" +.SH NAME +sieve\-filter \- Pigeonhole\(aqs Sieve mailbox filter tool + +.PP +\fBWARNING: \fRThis tool is still experimental. Read this manual carefully, and +backup any important mail before using this tool. Also note that some of the +features documented here are not actually implemented yet; this is clearly +indicated where applicable. +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.B sieve\-filter +.RI [ options ] +.I script\-file +.I source\-mailbox +.RI [ discard\-action ] +.SH DESCRIPTION +.PP +The \fBsieve\-filter\fP command is part of the Pigeonhole Project +(\fBpigeonhole\fR(7)), which adds Sieve (RFC 5228) support to the Dovecot +secure IMAP and POP3 server (\fBdovecot\fR(1)). +.PP +The Sieve language was originally meant for filtering messages upon delivery. +However, there are occasions when it is desirable to filter messages that are +already stored in a mailbox, for instance when a bug in a Sieve script caused +many messages to be delivered incorrectly. Using the sieve\-filter tool it is +possible to apply a Sieve script on all messages in a particular +\fIsource\-mailbox\fP, making it possible to delete messages, to store them in a +different mailbox, to change their content, and to change the assigned IMAP +flags and keywords. Attempts to send messages to the outside world are ignored +by default for obvious reasons, but, using the proper command line options, it +is possible to capture and handle outgoing mail as well. +.PP +If no options are specified, the sieve\-filter command runs in a simulation mode +in which it only prints what would be performed, without actually doing +anything. Use the \fB\-e\fP option to activate true script execution. Also, the +\fIsource\-mailbox\fP is opened read\-only by default, meaning that it normally +always remains unchanged. Use the \fB\-W\fP option to allow changes in the +\fIsource\-mailbox\fP. +.PP +Even with the \fB\-W\fP option enabled, messages in the \fIsource\-mailbox\fP +are only potentially modified or moved to a different folder. Messages are never +lost unless a \fIdiscard\-action\fP argument other than \fBkeep\fP (the default) +is specified. If the Sieve filter decides to store the message in the +\fIsource\-mailbox\fP, where it obviously already exists, it is never duplicated +there. In that case, the IMAP flags of the original message can be modified by +the Sieve interpreter using the \fIimap4flags\fP extension, provided that +\fB\-W\fP is specified. If the message itself is modified by the Sieve +interpreter (e.g. using the \fIeditheader\fP extension), a new message is stored +and the old one is expunged. However, if \fB-W\fP is omitted, the original +message is left untouched and the modifications are discarded. + +.SS CAUTION +Although this is a very useful tool, it can also be very destructive when used +improperly. A small bug in your Sieve script in combination with the wrong +command line options could cause it to discard the wrong e\-mails. And, even if +the \fIsource\-mailbox\fP is opened in read\-only mode to prevent such mishaps, +it can still litter other mailboxes with spurious copies of your e\-mails if +your Sieve script decides to do so. Therefore, users are advised to read this +manual carefully and to use the simulation mode first to check what the script +will do. And, of course: +.PP +\fBMAKING A BACKUP IS IMPERATIVE FOR ANY IMPORTANT MAIL!\fP + +.\"------------------------------------------------------------------------ +.SH OPTIONS +.TP +.BI \-c\ config\-file +Alternative Dovecot configuration file path. +.TP +.B \-C +Force compilation. By default, the compiled binary is stored on disk. When this +binary is found during the next execution of \fBsieve\-filter\fP and its +modification time is more recent than the script file, it is used and the script +is not compiled again. This option forces the script to be compiled, thus +ignoring any present binary. Refer to \fBsievec\fP(1) for more information about +Sieve compilation. +.TP +.B \-D +Enable Sieve debugging. +.TP +.B \-e +Turns on execution mode. By default, the sieve\-filter command runs in +simulation mode in which it changes nothing, meaning that no mailbox is altered +in any way and no actions are performed. It only prints what would be done. +Using this option, the sieve\-filter command becomes active and performs the +requested actions. +.TP +.BI \-m\ default\-mailbox +The mailbox where the (implicit) \fBkeep\fP Sieve action stores messages. This +is equal to the \fIsource\-mailbox\fP by default. Specifying a different folder +will have the effect of moving (or copying if \fB\-W\fP is omitted) all kept +messages to the indicated folder, instead of just leaving them in the +\fIsource\-mailbox\fP. Refer to the explanation of the \fIsource\-mailbox\fP +argument for more information on mailbox naming. +.TP +.BI \-o\ setting = value +Overrides the configuration +.I setting +from +.I @pkgsysconfdir@/dovecot.conf +and from the userdb with the given +.IR value . +In order to override multiple settings, the +.B \-o +option may be specified multiple times. +.TP +.BI \-q\ output\-mailbox\ \fB[not\ implemented\ yet]\fP +Store outgoing e\-mail into the indicated \fIoutput\-mailbox\fP. By default, +the sieve\-filter command ignores Sieve actions such as redirect, reject, +vacation and notify, but using this option outgoing messages can be appended to +the indicated mailbox. This option has no effect in simulation mode. Flags of +redirected messages are not preserved. +.TP +.BI \-Q\ mail\-command\ \fB[not\ implemented\ yet]\fP +Send outgoing e\-mail (e.g. as produced by redirect, reject and vacation) +through the specified program. By default, the sieve\-filter command ignores +Sieve actions such as redirect, reject, vacation and notify, but using this +option outgoing messages can be fed to the \fBstdin\fP of an external shell +command. This option has no effect in simulation mode. Unless you really know +what you are doing, \fBDO NOT USE THIS TO FEED MAIL TO SENDMAIL!\fP. +.TP +.BI \-s\ script\-file\ \fB[not\ implemented\ yet]\fP +Specify additional scripts to be executed before the main script. Multiple +\fB\-s\fP arguments are allowed and the specified scripts are executed +sequentially in the order specified at the command line. +.TP +.BI \-u\ user +Run the Sieve script for the given \fIuser\fP. When omitted, the +.I command +will be executed with the environment of the currently logged in user. +.TP +.B \-v +Produce verbose output during filtering. +.TP +.B \-W +Enables write access to the \fIsource\-mailbox\fP. This allows (re)moving the +messages from the \fIsource\-mailbox\fP, changing their contents, and changing +the assigned IMAP flags and keywords. +.TP +.BI \-x\ extensions +Set the available extensions. The parameter is a space\-separated list of the +active extensions. By prepending the extension identifiers with \fB+\fP or +\fB\-\fP, extensions can be included or excluded relative to the configured set +of active extensions. If no extensions have a \fB+\fP or \fB\-\fP prefix, only +those extensions that are explicitly listed will be enabled. Unknown extensions +are ignored and a warning is produced. + +For example \fB\-x\fP \(dq+imapflags \-enotify\(dq will enable the deprecated +imapflags extension and disable the enotify extension. The rest of the active +extensions depends on the \fIsieve_extensions\fP and +\fIsieve_global_extensions\fP settings. By default, i.e. +when \fIsieve_extensions\fP and \fIsieve_global_extensions\fP remain +unconfigured, all supported extensions are available, except for deprecated +extensions or those that are still under development. + +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I script\-file +Specifies the Sieve script to (compile and) execute. + +Note that this tool looks for a pre\-compiled binary file with a \fI.svbin\fP +extension and with basename and path identical to the specified script. Use the +\fB\-C\fP option to disable this behavior by forcing the script to be compiled +into a new binary. +.TP +.I source\-mailbox +Specifies the source mailbox containing the messages that the Sieve filter will +act upon. + +This is the name of a mailbox, as visible to IMAP clients, except in UTF-8 +format. The hierarchy separator between a parent and child mailbox is commonly +.RB \(aq / \(aq +or +.RB \(aq . \(aq, +but this depends on your selected mailbox storage format and +namespace configuration. The mailbox names may also require a namespace prefix. + +This mailbox is not modified unless the \fB\-W\fP option is specified. +.TP +.I discard\-action +Specifies what is done with messages in the \fIsource\-mailbox\fP that where not +kept or otherwise stored by the Sieve script; i.e. those messages that would +normally be discarded if the Sieve script were executed at delivery. +The \fIdiscard\-action\fP parameter accepts one of the following values: +.RS 7 +.TP +.BR keep\ (default) +Keep discarded messages in source mailbox. +.TP +.BI move\ mailbox +Move discarded messages to the indicated \fImailbox\fP. This is for instance +useful to move messages to a Trash mailbox. Refer to the explanation of +the \fIsource\-mailbox\fP argument for more information on mailbox naming. +.TP +.B delete +Flag discarded messages as \\DELETED. +.TP +.B expunge +Expunge discarded messages, meaning that these are removed irreversibly when the +tool finishes filtering. +.RE +.IP +When the \fB\-W\fP option is not specified, the \fIsource\-mailbox\fP is +immutable and the specified \fIdiscard\-action\fP has no effect. This means that +messages are at most \fIcopied\fP to a new location. In contrast, when the +\fB\-W\fP is specified, messages that are successfully stored somewhere else by +the Sieve script are \fBalways\fP expunged from the \fIsource\-mailbox\fP, with +the effect that these are thus \fImoved\fP to the new location. This happens +irrespective of the specified \fIdiscard\-action\fP. Remember: only discarded +messages are affected by the specified \fIdiscard\-action\fP. + +.\"------------------------------------------------------------------------ + +.SH EXAMPLES + +.TP +[...] + +.\"------------------------------------------------------------------------ +.SH "EXIT STATUS" +.B sieve\-filter +will exit with one of the following values: +.TP 4 +.B 0 +Sieve filter applied successfully. (EX_OK, EXIT_SUCCESS) +.TP +.B 1 +Operation failed. This is returned for almost all failures. +(EXIT_FAILURE) +.TP +.B 64 +Invalid parameter given. (EX_USAGE) +.\"------------------------------------------------------------------------ +.SH FILES +.TP +.I @pkgsysconfdir@/dovecot.conf +Dovecot\(aqs main configuration file. +.TP +.I @pkgsysconfdir@/conf.d/90\-sieve.conf +Sieve interpreter settings (included from Dovecot\(aqs main configuration file) +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH "SEE ALSO" +.BR dovecot (1), +.BR dovecot\-lda (1), +.BR sieve\-dump (1), +.BR sieve\-test (1), +.BR sievec (1), +.BR pigeonhole (7) diff --git a/pigeonhole/doc/man/sieve-test.1.in b/pigeonhole/doc/man/sieve-test.1.in new file mode 100644 index 0000000..65e5230 --- /dev/null +++ b/pigeonhole/doc/man/sieve-test.1.in @@ -0,0 +1,257 @@ +.\" Copyright (c) 2010-2018 Pigeonhole authors, see the included COPYING file +.TH "SIEVE\-TEST" 1 "2016-04-05" "Pigeonhole for Dovecot v2.4" "Pigeonhole" +.SH NAME +sieve\-test \- Pigeonhole\(aqs Sieve script tester +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.B sieve\-test +.RI [ options ] +.I script\-file +.I mail\-file +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +.PP +The \fBsieve\-test\fP command is part of the Pigeonhole Project +(\fBpigeonhole\fR(7)), which adds Sieve (RFC 5228) support to the Dovecot +secure IMAP and POP3 server (\fBdovecot\fR(1)). +.PP +Using the \fBsieve\-test\fP command, the execution of Sieve scripts can be +tested. This evaluates the script for the provided message, yielding a set of +Sieve actions. Unless the \fB\-e\fP option is specified, it does not actually +execute these actions, meaning that it does not store or forward the message +anywere. Instead, it prints a detailed list of what actions would normally take +place. Note that, even when \fB\-e\fP is specified, no messages are ever +transmitted to remote SMTP recipients. The outgoing messages are always printed +to \fBstdout\fP instead. +.PP +This is a very useful tool to debug the execution of Sieve scripts. It can be +used to verify newly installed scripts for the intended behaviour and it can +provide more detailed information about script execution problems that are +reported by the Sieve plugin, for example by tracing the execution and +evaluation of commands and tests respectively. +.\"------------------------------------------------------------------------ +.SH OPTIONS +.TP +.BI \-a\ orig\-recipient\-address +The original envelope recipient address. This is what Sieve\(aqs envelope test +will compare to when the \(dqto\(dq envelope part is requested. Some tests and +actions will also use this as the script owner\(aqs e\-mail address. If this +option is omitted, the recipient address is retrieved from the +\(dqEnvelope-To:\(dq, or \(dqTo:\(dq message headers. If none of these headers +is present either, the recipient address defaults to +\fIrecipient@example.com\fP. +.TP +.BI \-c\ config\-file +Alternative Dovecot configuration file path. +.TP +.B \-C +Force compilation. By default, the compiled binary is stored on disk. When this +binary is found during the next execution of \fBsieve\-test\fP and its +modification time is more recent than the script file, it is used and the script +is not compiled again. This option forces the script to be compiled, thus +ignoring any present binary. Refer to \fBsievec\fP(1) for more information about +Sieve compilation. +.TP +.B \-D +Enable Sieve debugging. +.TP +.BI \-d\ dump\-file +Causes a dump of the generated code to be written to the specified file. This is +identical to the dump produced by \fBsieve\-dump\fR(1). Using \(aq\-\(aq as +filename causes the dump to be written to \fBstdout\fP. +.TP +.BI \-e +Enables true execution of the set of actions that results from running the +script. In combination with the \fB\-l\fP parameter, the actual delivery of +messages can be tested. Note that this will not transmit any messages to remote +SMTP recipients. Such actions only print the outgoing message to \fBstdout\fP. +.TP +.BI \-f\ envelope\-sender +The envelope sender address (return path). This is what Sieve\(aqs envelope test +will compare to when the \(dqfrom\(dq envelope part is requested. Also, this is +where response messages are \(aqsent\(aq to. If this option is omitted, the sender +address is retrieved from the \(dqReturn-Path:\(dq, \(dqSender:\(dq or +\(dqFrom:\(dq message headers. If none of these headers is present either, +the sender envelope address defaults to \fIsender@example.com\fP. +.TP +.BI \-l\ mail\-location +The location of the user\(aqs mail store. The syntax of this option\(aqs +\fImail\-location\fP parameter is identical to what is used for the +mail_location setting in the Dovecot config file. This parameter is typically +used in combination with \fB\-e\fP to test the actual delivery of messages. If +\fB\-l\fP is omitted when \fB\-e\fP is specified, mail store actions like +fileinto and keep are skipped. +.TP +.BI \-m\ default\-mailbox +The mailbox where the keep action stores the message. This is \(dqINBOX\(dq +by default. +.TP +.BI \-o\ setting = value +Overrides the configuration +.I setting +from +.I @pkgsysconfdir@/dovecot.conf +and from the userdb with the given +.IR value . +In order to override multiple settings, the +.B \-o +option may be specified multiple times. +.TP +.BI \-r\ recipient\-address +The final envelope recipient address. Some tests and actions will +use this as the script owner\(aqs e\-mail address. For example, this is what is +used by the vacation action to check whether a reply is appropriate. If the +\fB\-r\fP option is omitted, the original envelope recipient address will be used +instead (see \fB\-a\fP option for more info). +.TP +.BI \-s\ script\-file +Specify additional scripts to be executed before the main script. Multiple +\fB\-s\fP arguments are allowed and the specified scripts are executed +sequentially in the order specified at the command +line. +.TP +.BI \-t\ trace\-file +Enables runtime trace debugging. Trace debugging provides detailed insight in +the operations performed by the Sieve script. Refer to the runtime trace +debugging section below. The trace information is written to the specified file. +Using '\-' as filename causes the trace data to be written to \fBstdout\fP. +.TP +.BI \-T\ trace\-option +Configures runtime trace debugging, which is enabled with the \fP\-t\fP option. +Refer to the runtime trace debugging section below. +.TP +.BI \-u\ user +Run the Sieve script for the given \fIuser\fP. When omitted, the +.I command +will be executed with the environment of the currently logged in user. +.TP +.BI \-x\ extensions +Set the available extensions. The parameter is a space\-separated list of the +active extensions. By prepending the extension identifiers with \fB+\fP or +\fB\-\fP, extensions can be included or excluded relative to the configured set +of active extensions. If no extensions have a \fB+\fP or \fB\-\fP prefix, only +those extensions that are explicitly listed will be enabled. Unknown extensions +are ignored and a warning is produced. + +For example \fB\-x\fP \(dq+imapflags \-enotify\(dq will enable the deprecated +imapflags extension and disable the enotify extension. The rest of the active +extensions depends on the \fIsieve_extensions\fP and +\fIsieve_global_extensions\fP settings. By default, i.e. +when \fIsieve_extensions\fP and \fIsieve_global_extensions\fP remain +unconfigured, all supported extensions are available, except for deprecated +extensions or those that are still under development. + +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I script\-file +Specifies the script to (compile and) execute. + +Note that this tool looks for a pre\-compiled binary file with a \fI.svbin\fP +extension and with basename and path identical to the specified script. Use the +\fB\-C\fP option to disable this behavior by forcing the script to be compiled +into a new binary. +.TP +.I mail\-file +Specifies the file containing the e\-mail message to test with. +.\"------------------------------------------------------------------------ +.SH USAGE +.SS RUNTIME TRACE DEBUGGING +.PP +Using the \fB\-t\fP option, the \fBsieve\-test\fP tool can be configured to +print detailed trace information on the Sieve script execution to a file or +standard output. For example, the encountered commands, the performed tests and +the matched values can be printed. +.PP +The runtime trace can be configured using the \fB\-T\fP option, which can be +specified multiple times. It can be used as follows: + +.TP 2 +\fB\-Tlevel=...\fP +Set the detail level of the trace debugging. One of the following values can +be supplied: +.RS 2 +.TP 3 +\fIactions\fP (default) +Only print executed action commands, like keep, fileinto, reject and redirect. +.TP +\fIcommands\fP +Print any executed command, excluding test commands. +.TP +\fItests\fP +Print all executed commands and performed tests. +.TP +\fImatching\fP +Print all executed commands, performed tests and the values matched in those +tests. +.RE +.TP 2 +\fB\-Tdebug\fP +Print debug messages as well. This is usually only useful for developers and +is likely to produce messy output. +.TP +\fB\-Taddresses\fP +Print byte code addresses for the current trace output. Normally, only the +current Sieve source code position (line number) is printed. The byte code +addresses are equal to those listed in a binary dump produced using the +\fB\-d\fP option or by the \fBsieve\-dump(1)\fP command. +.\"------------------------------------------------------------------------ +.SS DEBUG SIEVE EXTENSION +.PP +To improve script debugging, this Sieve implementation supports a custom Sieve +language extension called \(aqvnd.dovecot.debug\(aq. It adds the \fBdebug_log\fP +command that allows logging debug messages. +.PP +Example: +.PP +require \(dqvnd.dovecot.debug\(dq; +.PP +if header :contains \(dqsubject\(dq \(dqhello\(dq { +.PP + debug_log \(dqSubject header contains hello!\(dq; +.PP +} +.PP +Tools such as \fBsieve\-test\fP, \fBsievec\fP and \fBsieve\-dump\fP have support +for the vnd.dovecot.debug extension enabled by default and it is not necessary +to enable nor possible to disable the availability of the debug extension with +the \fB\-x\fP option. The logged messages are written to \fBstdout\fP in this +case. + +In contrast, for the actual Sieve plugin for the Dovecot LDA +(\fBdovecot\-lda\fR(1)) the vnd.dovecot.debug extension needs to be enabled +explicitly using the \fIsieve_extensions\fP setting. The messages are then +logged to the user's private script log file. If used in a global script, the +messages are logged through the default Dovecot logging facility. +.\"------------------------------------------------------------------------ +.SH "EXIT STATUS" +.B sieve\-test +will exit with one of the following values: +.TP 4 +.B 0 +Execution was successful. (EX_OK, EXIT_SUCCESS) +.TP +.B 1 +Operation failed. This is returned for almost all failures. +(EXIT_FAILURE) +.TP +.B 64 +Invalid parameter given. (EX_USAGE) +.\"------------------------------------------------------------------------ +.SH FILES +.TP +.I @pkgsysconfdir@/dovecot.conf +Dovecot\(aqs main configuration file. +.TP +.I @pkgsysconfdir@/conf.d/90\-sieve.conf +Sieve interpreter settings (included from Dovecot\(aqs main configuration file) +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH "SEE ALSO" +.BR dovecot (1), +.BR dovecot\-lda (1), +.BR sieve\-dump (1), +.BR sieve\-filter (1), +.BR sievec (1), +.BR pigeonhole (7) diff --git a/pigeonhole/doc/man/sievec.1.in b/pigeonhole/doc/man/sievec.1.in new file mode 100644 index 0000000..548bcca --- /dev/null +++ b/pigeonhole/doc/man/sievec.1.in @@ -0,0 +1,142 @@ +.\" Copyright (c) 2010-2018 Pigeonhole authors, see the included COPYING file +.TH "SIEVEC" 1 "2016-04-05" "Pigeonhole for Dovecot v2.4" "Pigeonhole" +.\"------------------------------------------------------------------------ +.SH NAME +sievec \- Pigeonhole\(aqs Sieve script compiler +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.B sievec +.RI [ options ] +.I script\-file +.RI [ out\-file ] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +.PP +The \fBsievec\fP command is part of the Pigeonhole Project +(\fBpigeonhole\fR(7)), which adds Sieve (RFC 5228) support to the Dovecot +secure IMAP and POP3 server (\fBdovecot\fR(1)). +.PP +Using the \fBsievec\fP command, Sieve scripts can be compiled into a binary +representation. The resulting binary can be used directly to process e\-mail +messages during the delivery process. The delivery of mail messages and \- by +means of the LDA Sieve plugin \- also the execution of Sieve scripts is +performed by Dovecot\(aqs local delivery agent (LDA) called \fBdovecot\-lda\fP(1). +Usually, it is not necessary to compile the Sieve script manually using +\fBsievec\fP, because \fBdovecot\-lda\fP will do this automatically if the binary +is missing. However, in some cases \fBdovecot\-lda\fP does not have permission to +write the compiled binary to disk, forcing it to recompile the script every time +it is executed. Using the \fBsievec\fP tool, this can be performed manually by +an authorized user to increase performance. +.PP +The Pigeonhole Sieve implementation recognizes files with a \fB.sieve\fP +extension as Sieve scripts and corresponding files with a \fB.svbin\fP extension +as the associated compiled binary. This means for example that Dovecot\(aqs LDA +process will first look for a binary file \(dqdovecot.svbin\(dq when it needs to +execute \(dqdovecot.sieve\(dq. It will compile a new binary when it is missing +or outdated. +.PP +The \fBsievec\fP command is also useful to verify Sieve scripts before using. +Additionally, with the \fB\-d\fP option it can output a textual (and thus +human\-readable) dump of the generated Sieve code to the specified file. The +output is then identical to what the \fBsieve\-dump\fP(1) command produces for a +stored binary file. This output is mainly useful to find bugs in the compiler +that yield corrupt binaries. +.\"------------------------------------------------------------------------ +.SH OPTIONS +.TP +.BI \-c\ config\-file +Alternative Dovecot configuration file path. +.TP +.B \-d +Don\(aqt write the binary to \fIout\-file\fP, but write a textual dump of the +binary instead. In this context, the \fIout\-file\fP value '\-' has special +meaning: it causes the the textual dump to be written to \fBstdout\fP. +The \fIout\-file\fP argument may also be omitted, which has the same effect +as '\-'. +The output is identical to what the \fBsieve\-dump\fP(1) command produces +for a compiled Sieve binary file. Note that this option is not allowed when the +\fIout\-file\fP argument is a directory. +.TP +.B \-D +Enable Sieve debugging. +.TP +.BI \-o\ setting = value +Overrides the configuration +.I setting +from +.I @pkgsysconfdir@/dovecot.conf +and from the userdb with the given +.IR value . +In order to override multiple settings, the +.B \-o +option may be specified multiple times. +.TP +.BI \-u\ user +Run the Sieve script for the given \fIuser\fP. When omitted, the +.I command +will be executed with the environment of the currently logged in user. +.TP +.BI \-x\ extensions +Set the available extensions. The parameter is a space\-separated list of the +active extensions. By prepending the extension identifiers with \fB+\fP or +\fB\-\fP, extensions can be included or excluded relative to the configured set +of active extensions. If no extensions have a \fB+\fP or \fB\-\fP prefix, only +those extensions that are explicitly listed will be enabled. Unknown extensions +are ignored and a warning is produced. + +For example \fB\-x\fP \(dq+imapflags \-enotify\(dq will enable the deprecated +imapflags extension and disable the enotify extension. The rest of the active +extensions depends on the \fIsieve_extensions\fP and +\fIsieve_global_extensions\fP settings. By default, i.e. +when \fIsieve_extensions\fP and \fIsieve_global_extensions\fP remain +unconfigured, all supported extensions are available, except for deprecated +extensions or those that are still under development. + +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I script\-file +Specifies the script to be compiled. If the \fIscript\-file\fP argument is a +directory, all files in that directory with a \fI.sieve\fP extension are +compiled into a corresponding \fI.svbin\fP binary file. The compilation is not +halted upon errors; it attempts to compile as many scripts in the directory as +possible. Note that the \fB\-d\fP option and the \fIout\-file\fP argument are +not allowed when the \fIscript\-file\fP argument is a directory. +.TP +.I out\-file +Specifies where the (binary) output is to be written. This argument is optional. +If this argument is omitted, a binary compiled from <scriptname>.sieve is saved +as <scriptname>.svbin. If this argument is omitted and \fB\-b\fP is specified, +the binary dump is output to \fBstdout\fP. +.\"------------------------------------------------------------------------ +.SH "EXIT STATUS" +.B sievec +will exit with one of the following values: +.TP 4 +.B 0 +Compile was successful. (EX_OK, EXIT_SUCCESS) +.TP +.B 1 +Operation failed. This is returned for almost all failures. +(EXIT_FAILURE) +.TP +.B 64 +Invalid parameter given. (EX_USAGE) +.\"------------------------------------------------------------------------ +.SH FILES +.TP +.I @pkgsysconfdir@/dovecot.conf +Dovecot\(aqs main configuration file. +.TP +.I @pkgsysconfdir@/conf.d/90\-sieve.conf +Sieve interpreter settings (included from Dovecot\(aqs main configuration file) +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH "SEE ALSO" +.BR dovecot (1), +.BR dovecot\-lda (1), +.BR sieve\-dump (1), +.BR sieve\-filter (1), +.BR sieve\-test (1), +.BR pigeonhole (7) diff --git a/pigeonhole/doc/man/sieved.1 b/pigeonhole/doc/man/sieved.1 new file mode 100644 index 0000000..7a4854a --- /dev/null +++ b/pigeonhole/doc/man/sieved.1 @@ -0,0 +1 @@ +.so man1/sieve-dump.1 diff --git a/pigeonhole/doc/plugins/Makefile.am b/pigeonhole/doc/plugins/Makefile.am new file mode 100644 index 0000000..4280aa6 --- /dev/null +++ b/pigeonhole/doc/plugins/Makefile.am @@ -0,0 +1,13 @@ +docfiles = \ + imap_filter_sieve.txt \ + imapsieve.txt \ + sieve_extprograms.txt + +if BUILD_DOCS +plugins_docdir = $(sieve_docdir)/plugins +plugins_doc_DATA = $(docfiles) +endif + +EXTRA_DIST = \ + $(docfiles) + diff --git a/pigeonhole/doc/plugins/Makefile.in b/pigeonhole/doc/plugins/Makefile.in new file mode 100644 index 0000000..73ab19c --- /dev/null +++ b/pigeonhole/doc/plugins/Makefile.in @@ -0,0 +1,576 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = doc/plugins +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(plugins_docdir)" +DATA = $(plugins_doc_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +docfiles = \ + imap_filter_sieve.txt \ + imapsieve.txt \ + sieve_extprograms.txt + +@BUILD_DOCS_TRUE@plugins_docdir = $(sieve_docdir)/plugins +@BUILD_DOCS_TRUE@plugins_doc_DATA = $(docfiles) +EXTRA_DIST = \ + $(docfiles) + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/plugins/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/plugins/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-plugins_docDATA: $(plugins_doc_DATA) + @$(NORMAL_INSTALL) + @list='$(plugins_doc_DATA)'; test -n "$(plugins_docdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(plugins_docdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(plugins_docdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(plugins_docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(plugins_docdir)" || exit $$?; \ + done + +uninstall-plugins_docDATA: + @$(NORMAL_UNINSTALL) + @list='$(plugins_doc_DATA)'; test -n "$(plugins_docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(plugins_docdir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(plugins_docdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-plugins_docDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-plugins_docDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-plugins_docDATA install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags-am uninstall uninstall-am \ + uninstall-plugins_docDATA + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/doc/plugins/imap_filter_sieve.txt b/pigeonhole/doc/plugins/imap_filter_sieve.txt new file mode 100644 index 0000000..78c4e59 --- /dev/null +++ b/pigeonhole/doc/plugins/imap_filter_sieve.txt @@ -0,0 +1,52 @@ +IMAP FILTER Sieve plugin for Pigeonhole + +Relevant specifications +======================= + + doc/rfc/draft-bosch-imap-filter-sieve-00.txt + +Introduction +============ + +Normally, Sieve filters can either be applied at initial mail delivery or +triggered by certain events in the Internet Message Access Protocol (IMAPSIEVE; +RFC 6785). The user can configure which Sieve scripts to run at these instances, +but it is not possible to trigger the execution of Sieve scripts manually. +However, this could be very useful; e.g, to test new Sieve rules and to +re-filter messages that were erroneously handled by an earlier version of the +Sieve scripts involved. + +Pigeonhole provides the imap_filter_sieve plugin, which provides a vendor- +defined IMAP extension called "FILTER=SIEVE". This adds a new "FILTER" command +that allows applying a mail filter (a Sieve script) on a set of messages that +match the specified searching criteria. + +This plugin is experimental and the specification is likely to change. + +Configuration +============= + +The IMAP FILTER Sieve plugin is activated by adding it to the mail_plugins +setting for the imap protocol: + +protocol imap { + mail_plugins = $mail_plugins imap_filter_sieve +} + +Currently, no other settings specific to this plugin are defined. It uses the +normal configuration settings used by the LDA Sieve plugin at delivery. + +The sieve_before and sieve_after scripts are currently ignored by this plugin. + +Example +------- + +protocol imap { + # Space separated list of plugins to load (default is global mail_plugins). + mail_plugins = $mail_plugins imap_filter_sieve +} + +plugin { + sieve_global = /usr/lib/dovecot/sieve-global.d +} + diff --git a/pigeonhole/doc/plugins/imapsieve.txt b/pigeonhole/doc/plugins/imapsieve.txt new file mode 100644 index 0000000..9601e97 --- /dev/null +++ b/pigeonhole/doc/plugins/imapsieve.txt @@ -0,0 +1,155 @@ +IMAPSIEVE plugins for Pigeonhole + +Relevant specifications +======================= + + doc/rfc/imapsieve.rfc6785.txt + +Introduction +============ + +As defined in the base specification, the Sieve language is used only during +delivery. However, in principle, it can be used at any point in the processing +of an email message. RFC 6785 defines the use of Sieve filtering in IMAP, +operating when messages are created or their attributes are changed. This +feature extends both Sieve and IMAP. Therefore, Pigeonhole provides both an +IMAP and a Sieve plugin. The IMAP plugin is called "imap_sieve" and the Sieve +plugin is called "sieve_imapsieve". + +The basic IMAPSIEVE capability allows attaching a Sieve script to a mailbox +(or any mailbox) by setting a special IMAP METADATA entry. This way, users can +configure Sieve scripts that are run for IMAP events in their mailboxes. The +Pigeonhole implementation also adds the ability for administrators to configure +Sieve scripts outside the user's control, that are run either before or after a +user's script if there is one. + +Dovecot-specific Environment Items +================================== + +The "imapsieve" extension defined in RFC 6785 defines additional environment +items for the "environment" extension defined in RFC 5183. Beyond those, Dovecot +defines a few more. These are available when the Dovecot-specific +"vnd.dovecot.imapsieve" extension is enabled using the "require" command. The +"vnd.dovecot.imapsieve" extension implicitly uses the "imapsieve" extension, so +that extension does not need to be enabled as well in that case. The following +Dovecot-specific environment items are added: + +vnd.dovecot.mailbox-from + The mailbox where the message is being copied or moved from (the source + mailbox). This environment item is only set when the Sieve script is executed + from an IMAP COPY or MOVE command. + +vnd.dovecot.mailbox-to + The mailbox where the message is being copied to (the destination mailbox). + If the Sieve script is not executed from an IMAP COPY or MOVE command, this + environment is always equal to the "imap.mailbox" environment item. Otherwise, + the "imap.mailbox" item points to the mailbox where the Sieve script is + executing for, which may actually be the source mailbox (see the + imapsieve_mailboxXXX_copy_source_after setting). + +Configuration +============= + +The IMAP plugin is activated by adding it to the mail_plugins setting for +the imap protocol: + +protocol imap { + mail_plugins = $mail_plugins imap_sieve +} + +This only will enable support for administrator scripts. User scripts are only +supported when additionally a Sieve URL is configured using the imapsieve_url +plugin setting. This URL points to the ManageSieve server that users need to use +to upload their Sieve scripts. This URL will be shown to the client in the IMAP +CAPABILITY response as IMAPSIEVE=<URL>. + +The Sieve plugin is activated by adding it to the sieve_plugins setting: + +sieve_plugins = sieve_imapsieve + +This plugin registers the "imapsieve" extension with the Sieve interpreter. This +extension is enabled implicitly, which means that it does not need to be added +to the "sieve_extensions" setting. + +Note that the "imapsieve" extension can only be used from IMAP. When it is used +in the active delivery script, it will cause runtime errors. To make a Sieve +script suitable for both delivery and IMAP, the availability of the extension +can be tested using the "ihave" test (RFC 5463) as usual. + +The following settings are recognized the "imap_sieve" plugin: + +imapsieve_url = + If configured, this setting enables support for user Sieve scripts in IMAP. + So, leave this unconfigured if you don't want users to have the ability to + associate Sieve scripts with mailboxes. The value is an URL pointing to the + ManageSieve server that users must use to upload their Sieve scripts. + +imapsieve_mailboxXXX_name = + This setting configures the name of a mailbox for which administrator scripts + are configured. The `XXX' in this setting is a sequence number, which allows + configuring multiple associations between Sieve scripts and mailboxes. The + settings defined hereafter with matching sequence numbers apply to the mailbox + named by this setting. The sequence of configured mailboxes ends at the first + missing "imapsieve_mailboxXXX_name" setting. This setting supports wildcards + with a syntax compatible with the IMAP LIST command, meaning that this + setting can apply to multiple or even all ("*") mailboxes. + +imapsieve_mailboxXXX_before = +imapsieve_mailboxXXX_after = + When an IMAP event of interest occurs, these sieve scripts are executed before + and after any user script respectively. These settings each specify the + location of a single sieve script. The semantics of these settings are very + similar to the "sieve_before" and "sieve_after" settings: the specified + scripts form a sequence together with the user script in which the next script + is only executed when an (implicit) keep action is executed. + +imapsieve_mailboxXXX_causes = + Only execute the administrator Sieve scripts for the mailbox configured with + "imapsieve_mailboxXXX_name" when one of the listed IMAPSIEVE causes apply. + This has no effect on the user script, which is always executed no matter the + cause. + +imapsieve_mailboxXXX_from = + Only execute the administrator Sieve scripts for the mailbox configured with + "imapsieve_mailboxXXX_name" when the message originates from the indicated + mailbox. This setting supports wildcards with a syntax compatible with the + IMAP LIST command + +imapsieve_mailboxXXX_copy_source_after = + When the cause is "COPY", run the specified Sieve script for the message in + the source mailbox after the Sieve script for the corresponding message in the + destination mailbox successfully finishes executing . This does not apply to + moved messages, since the message is removed from the source mailbox in that + case. + +imapsieve_expunge_discarded=no + When enabled, discarded messages (for which no keep action is in effect) will + be expunged immediately when the Sieve script execution is succcessful. + Normally, such messages are only marked with the "\Deleted" flag and will be + expunged only when the client explicitly issues an IMAP EXPUNGE command on the + mailbox at a later time. + +Example +------- + +protocol imap { + # Space separated list of plugins to load (default is global mail_plugins). + mail_plugins = $mail_plugins imap_sieve +} + +plugin { + sieve_plugins = sieve_imapsieve + + imapsieve_url = sieve://sieve.example.org + + # From elsewhere to Spam folder + imapsieve_mailbox1_name = Spam + imapsieve_mailbox1_causes = COPY + imapsieve_mailbox1_before = file:/usr/lib/dovecot/sieve/report-spam.sieve + # From Spam folder to elsewhere + imapsieve_mailbox2_name = * + imapsieve_mailbox2_from = Spam + imapsieve_mailbox2_causes = COPY + imapsieve_mailbox2_before = file:/usr/lib/dovecot/sieve/report-ham.sieve +} + diff --git a/pigeonhole/doc/plugins/sieve_extprograms.txt b/pigeonhole/doc/plugins/sieve_extprograms.txt new file mode 100644 index 0000000..4110fce --- /dev/null +++ b/pigeonhole/doc/plugins/sieve_extprograms.txt @@ -0,0 +1,182 @@ +Sieve Extprograms plugin for Pigeonhole + +Relevant specifications +======================= + + doc/rfc/spec-bosch-sieve-extprograms.txt + +Introduction +============ + +Sieve (RFC 5228) is a highly extensible machine language specifically tailored +for internet message filtering. For the Dovecot Secure IMAP server, Sieve +support is provided by the Pigeonhole Sieve plugin. This package includes a +plugin for Pigeonhole called "sieve_extprograms", which extends the Sieve +filtering implementation with action commands for invoking a predefined set of +external programs. Messages can be piped to or filtered through those programs +and string data can be input to and retrieved from those programs. + +The Sieve language is explicitly designed to be powerful enough to be useful yet +limited in order to allow for a safe server-side filtering system. Therefore, +the base specification of the language makes it impossible for users to do +anything more complex (and dangerous) than write simple mail filters. One of the +consequences of this security-minded design is that users cannot execute +external programs from their mail filter. Particularly for server-side filtering +setups in which mail accounts have no corresponding system account, allowing the +execution of arbitrary programs from the mail filter can be a significant +security risk. However, such functionality can also be very useful, for instance +to easily implement a custom action or external effect that Sieve normally +cannot provide. + +The "sieve_extprograms" plugin provides an extension to the Sieve filtering +language adding new action commands for invoking a predefined set of external +programs. To mitigate the security concerns, the external programs cannot be +chosen arbitrarily; the available programs are restricted through administrator +configuration. + +This extension is specific to the Pigeonhole Sieve implementation for the +Dovecot Secure IMAP server. It will therefore most likely not be supported by +web interfaces or GUI-based Sieve editors. This extension is primarily meant for +use in small setups or global scripts that are managed by the systems +administrator. + +Implementation Status +--------------------- + +The "vnd.dovecot.pipe", "vnd.dovecot.filter" and "vnd.dovecot.execute" Sieve +language extensions introduced by this plugin are vendor-specific with draft +status and their implementation for Pigeonhole is experimental, which means that +the language extensions are still subject to change and that the current +implementation is not thoroughly tested. + +Configuration +============= + +The plugin is activated by adding it to the sieve_plugins setting: + +sieve_plugins = sieve_extprograms + +This plugin registers the "vnd.dovecot.pipe", "vnd.dovecot.filter" and +"vnd.dovecot.execute" extensions with the Sieve interpreter. However, these +extensions are not enabled by default and thus need to be enabled explicitly. It +is recommended to restrict the use of these extensions to global context by +adding these to the "sieve_global_extensions" setting. If personal user scripts +also need to directly access external programs, the extensions need to be added +to the "sieve_extensions" setting. + +The commands introduced by the Sieve language extensions in this plugin can +directly pipe a message or string data to an external program (typically a shell +script) by forking a new process. Alternatively, these can connect to a unix +socket behind which a Dovecot script service is listening to start the external +program, e.g. to execute as a different user or for added security. + +The program name specified for the new Sieve "pipe", "filter" and "execute" +commands is used to find the program or socket in a configured directory. +Separate directories are specified for the sockets and the directly executed +binaries. The socket directory is searched first. Since the use of "/" in +program names is prohibited, it is not possible to build a hierarchical +structure. + +Directly forked programs are executed with a limited set of environment +variables: HOME, USER, HOST, SENDER, RECIPIENT and ORIG_RECIPIENT. Programs +executed through the script-pipe socket service currently have no environment +set at all. + +If a shell script is expected to read a message or string data, it must fully +read the provided input until the data ends with EOF, otherwise the Sieve action +invoking the program will fail. The action will also fail when the shell script +returns a nonzero exit code. Standard output is available for returning a +message (for the filter command) or string data (for the execute command) to the +Sieve interpreter. Standard error is written to the LDA log file. + +The three extensions introduced by this plugin - "vnd.dovecot.pipe", +"vnd.dovecot.filter" and "vnd.dovecot.pipe" - each have separate but similar +configuration. The settings that specify a time period are specified in +s(econds), unless followed by a d(ay), h(our) or m(inute) specifier character. +The following configuration settings are used, for which "<extension>" in the +setting name is replaced by either "pipe", "filter" or "execute" depending on +which extension is being configured. + +sieve_<extension>_socket_dir = + Points to a directory relative to the Dovecot base_dir where the plugin looks + for script service sockets. + +sieve_<extension>_bin_dir = + Points to a directory where the plugin looks for programs (shell scripts) to + execute directly and pipe messages to. + +sieve_<extension>_exec_timeout = 10s + Configures the maximum execution time after which the program is forcibly + terminated. + +sieve_<extension>_input_eol = crlf + Determines the end-of-line character sequence used for the data piped to + external programs. The default is currently "crlf", which represents a + sequence of the carriage return (CR) and line feed (LF) characters. This + matches the Internet Message Format (RFC5322) and what Sieve itself uses as a + line ending. Set this setting to "lf" to use a single LF character instead. + +Examples +-------- + +Example 1: socket service for "pipe" and "execute" + +plugin { + sieve = ~/.dovecot.sieve + + sieve_plugins = sieve_extprograms + sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.execute + + # pipe sockets in /var/run/dovecot/sieve-pipe + sieve_pipe_socket_dir = sieve-pipe + + # execute sockets in /var/run/dovecot/sieve-execute + sieve_execute_socket_dir = sieve-execute +} + +service sieve-pipe-script { + # This script is executed for each service connection + executable = script /usr/lib/dovecot/sieve-extprograms/sieve-pipe-action.sh + + # use some unprivileged user for execution + user = dovenull + + # socket name is program-name in Sieve (without sieve-pipe/ prefix) + unix_listener sieve-pipe/sieve-pipe-script { + } +} + +service sieve-execute-action { + # This script is executed for each service connection + executable = script /usr/lib/dovecot/sieve-extprograms/sieve-execute-action.sh + + # use some unprivileged user for execution + user = dovenull + + # socket name is program-name in Sieve (without sieve-execute/ prefix) + unix_listener sieve-execute/sieve-execute-action { + } +} + +Example 2: direct execution for "pipe" and "filter" + +plugin { + sieve = ~/.dovecot.sieve + + sieve_plugins = sieve_extprograms + sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.filter + + # This directory contains the scripts that are available for the pipe command. + sieve_pipe_bin_dir = /usr/lib/dovecot/sieve-pipe + + # This directory contains the scripts that are available for the filter + # command. + sieve_filter_bin_dir = /usr/lib/dovecot/sieve-filter +} + +Using +===== + +Refer to doc/rfc/spec-bosch-sieve-extprograms.txt for a specification of the +Sieve language extensions. + diff --git a/pigeonhole/dovecot-pigeonhole.m4 b/pigeonhole/dovecot-pigeonhole.m4 new file mode 100644 index 0000000..1ccff82 --- /dev/null +++ b/pigeonhole/dovecot-pigeonhole.m4 @@ -0,0 +1,62 @@ +# pigeonhole.m4 - Check presence of pigeonhole -*-Autoconf-*- +#. + +# serial 5 + +AC_DEFUN([DC_PIGEONHOLE],[ + AC_ARG_WITH(pigeonhole, + [ --with-pigeonhole=DIR Pigeonhole base directory], + pigeonholedir="$withval", + [ + pg_prefix=$prefix + test "x$pg_prefix" = xNONE && pg_prefix=$ac_default_prefix + pigeonholedir="$pg_prefix/include/dovecot/sieve" + ] + ) + + AC_MSG_CHECKING([for pigeonhole in "$pigeonholedir"]) + + top=`pwd` + cd $pigeonholedir + pigeonholedir=`pwd` + cd $top + AC_SUBST(pigeonholedir) + + PIGEONHOLE_TESTSUITE= + if test -f "$pigeonholedir/src/lib-sieve/sieve.h"; then + AC_MSG_RESULT([found]) + pigeonhole_incdir="$pigeonholedir" + LIBSIEVE_INCLUDE='\ + -I$(pigeonhole_incdir) \ + -I$(pigeonhole_incdir)/src/lib-sieve \ + -I$(pigeonhole_incdir)/src/lib-sieve/util \ + -I$(pigeonhole_incdir)/src/lib-sieve/plugins/copy \ + -I$(pigeonhole_incdir)/src/lib-sieve/plugins/enotify \ + -I$(pigeonhole_incdir)/src/lib-sieve/plugins/imap4flags \ + -I$(pigeonhole_incdir)/src/lib-sieve/plugins/mailbox \ + -I$(pigeonhole_incdir)/src/lib-sieve/plugins/variables' + PIGEONHOLE_TESTSUITE="${pigeonholedir}/src/testsuite/testsuite" + elif test -f "$pigeonholedir/sieve.h"; then + AC_MSG_RESULT([found]) + pigeonhole_incdir="$pigeonholedir" + LIBSIEVE_INCLUDE='-I$(pigeonhole_incdir)' + else + AC_MSG_RESULT([not found]) + AC_MSG_NOTICE([ + Pigeonhole Sieve headers not found from $pigeonholedir and they + are not installed in the Dovecot include path, use --with-pigeonhole=PATH + to give path to Pigeonhole sources or installed headers.]) + AC_MSG_ERROR([pigeonhole not found]) + fi + + DISTCHECK_CONFIGURE_FLAGS="$DISTCHECK_CONFIGURE_FLAGS --with-pigeonhole=$pigeonholedir" + + AM_CONDITIONAL(PIGEONHOLE_TESTSUITE_AVAILABLE, ! test -z "$PIGEONHOLE_TESTSUITE") + + pigeonhole_incdir="$pigeonholedir" + + AC_SUBST(pigeonhole_incdir) + + AC_SUBST(LIBSIEVE_INCLUDE) + AC_SUBST(PIGEONHOLE_TESTSUITE) +]) diff --git a/pigeonhole/dummy-config.h.in b/pigeonhole/dummy-config.h.in new file mode 100644 index 0000000..1f1e1bf --- /dev/null +++ b/pigeonhole/dummy-config.h.in @@ -0,0 +1,106 @@ +/* dummy-config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#undef HAVE_DLFCN_H + +/* Define if your compiler has -fno-sanitize=nonnull-attribute */ +#undef HAVE_FNO_SANITIZE_NONNULL_ATTRIBUTE + +/* Define if your compiler has -fsanitize=implicit-integer-truncation */ +#undef HAVE_FSANITIZE_IMPLICIT_INTEGER_TRUNCATION + +/* Define if your compiler has -fsanitize=integer */ +#undef HAVE_FSANITIZE_INTEGER + +/* Define if your compiler has -fsanitize=local-bounds */ +#undef HAVE_FSANITIZE_LOCAL_BOUNDS + +/* Define if your compiler has -fsanitize=nullability */ +#undef HAVE_FSANITIZE_NULLABILITY + +/* Define if your compiler has -fsanitize=undefined */ +#undef HAVE_FSANITIZE_UNDEFINED + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the <sasl.h> header file. */ +#undef HAVE_SASL_H + +/* Define to 1 if you have the <sasl/sasl.h> header file. */ +#undef HAVE_SASL_SASL_H + +/* Define to build unfinished features/extensions. */ +#undef HAVE_SIEVE_UNFINISHED + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define if your compiler supports undefined sanitizers */ +#undef HAVE_UNDEFINED_SANITIZER + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have ldap_initialize */ +#undef LDAP_HAVE_INITIALIZE + +/* Define if you have ldap_start_tls_s */ +#undef LDAP_HAVE_START_TLS_S + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Pigeonhole ABI version */ +#undef PIGEONHOLE_ABI_VERSION + +/* Define to the full name of Pigeonhole for Dovecot. */ +#undef PIGEONHOLE_NAME + +/* Define to the version of Pigeonhole for Dovecot. */ +#undef PIGEONHOLE_VERSION + +/* LDAP support is built in */ +#undef SIEVE_BUILTIN_LDAP + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Build with LDAP support */ +#undef STORAGE_LDAP diff --git a/pigeonhole/examples/elvey.sieve b/pigeonhole/examples/elvey.sieve new file mode 100644 index 0000000..869f1c9 --- /dev/null +++ b/pigeonhole/examples/elvey.sieve @@ -0,0 +1,153 @@ +# Example Sieve Script +# Author: Matthew Elvey (Slightly modified to remove syntax and context errors) +# URL: http://www.elvey.com/it/sieve/SieveScript.txt + +# Initial version completed and put in place 4/1/02 by Matthew Elvey (firstname@lastname.com ; I've checked and it's not a valid address.); Copyright (C).and.current as of 5/19/2002 +#Change log: +#+ spam[:high]; major reordering; +DFC,BugTraq, PB up +Economist, FolderPath corrections +#+ redid .0 matches. +Korean + whitelist +@f(useful once I start bouncing mail!) +#+open mag, simplifications, to fm=spamNOTwhite, Bulk changes, IETF rules, +lst +#Reword spam bounce.+scalable@ re-correction+++Work+activate Spam Optimization, etc... +#oops high = 2x threshold, so 2x1 is 2! Too low. To @fm:bounce. Added tons of comments. +require ["fileinto", "reject", "vacation", "envelope", "regex"]; + +if header :contains "subject" ["un eject", "lastname.com/spamoff.htm agreed to"] { #I give out "uneject" to people to let them bypass the spam or size filters. + keep; +} elsif header :contains "subject" ["ADV:", "bounceme", "2002 Gov Grants", #bounceme is useful for testing. + "ADV:ADLT", "ADV-ADULT", "ADULT ADVERTISEMENT"] { #Subject text required by various US State laws + reject text: + Hello. The server content filter/spam detector I use has bounced your message. It appears to be spam. + + I do not accept spam/UCE (Unsolicited Commercial Email). + +Please ask me how to bypass this filter if your email is not UCE. In that case, I am sorry about this +highly unusual error. The filter is >99% accurate. + + (This is an automated message; I will not be aware that your message did not get through if I do not hear from you again.) + + -Firstname + + (P.S. You may also override the filter if you accept the terms at http://www.lastname.com/spamoff.htm, + by including "lastname.com/spamoff.htm agreed to." in the subject.) +. + ; +} +# LINE 30. + elsif size :over 10M { # (note that the four leading dots get "stuffed" to three) + + reject text: + Message NOT delivered! + This system normally accepts email that is less than 10MB in size, because that is how I configured it. + You may want to put your file on a server and send me the URL. + Or, you may request override permission and/or unreject instructions via another (smaller) email. + Sorry for the inconvenience. + + Thanks, + +.... Firstname + (This is an automated message; I will not be aware that your message did not get through if I do not hear from you again.) + + Unsolicited advertising sent to this E-Mail address is expressly prohibited + under USC Title 47, Section 227. Violators are subject to charge of up to + $1,500 per incident or treble actual costs, whichever is greater. +. + ; +#LINE 47. +} elsif header :contains "From" "Firstname@lastname.com" { #if I send myself email, leave it in the Inbox. + keep; #next, is the processing for the various mailing lists I'm on. +} elsif header :contains ["Sender", "X-Sender", "Mailing-List", "Delivered-To", "List-Post", "Subject", "To", "Cc", "From", "Reply-to", "Received"] "burningman" { + fileinto "INBOX.DaBurn"; +} elsif header :contains ["Subject", "From", "Received"] ["E*TRADE", "Datek", "TD Waterhouse", "NetBank"] { + fileinto "INBOX.finances.status"; +} elsif header :contains "subject" "\[pacbell" { + fileinto "INBOX.pacbell.dslreports"; +} elsif header :contains "From" ["owner-te-wg ", "te-wg ", "iana.org"] { + fileinto "INBOX.lst.IETF"; +} elsif header :contains ["Mailing-List", "Subject", "From", "Received"] ["Red Hat", "Double Funk Crunch", "@economist.com", "Open Magazine", "@nytimes.com", "mottimorell", "Harrow Technology Report"] { + fileinto "INBOX.lst.interesting"; +} elsif header :contains ["Mailing-List", "Subject", "From", "Received", "X-LinkName"] ["DJDragonfly", "Ebates", "Webmonkey", "DHJ8091@aol.com", "Expedia Fare Tracker", "SoulShine", "Martel and Nabiel", "\[ecc\]"] { + fileinto "INBOX.lst.lame"; +} elsif header :contains ["Subject", "From", "To"] ["guru.com", "monster.com", "hotjobs", "dice.com", "linkify.com"] { #job boards and current clients. + fileinto "INBOX.lst.jobs"; +} elsif header :contains "subject" "\[yaba" { + fileinto "INBOX.rec.yaba"; +} elsif header :contains ["to", "cc"] "scalable@" { + fileinto "INBOX.lst.scalable"; +} elsif header :contains ["Sender", "To", "Return-Path", "Received"] "NTBUGTRAQ@listserv.ntbugtraq.com" { + fileinto "INBOX.lst.bugtraq"; +} elsif header :contains "subject" "Wired" { + fileinto "INBOX.lst.wired"; +#LINE 72. +} elsif anyof (header :contains "From" ["postmaster", "daemon", "abuse"], header :contains "Subject" ["warning:", "returned mail", "failure notice", "undelivered mail"] ) { +keep; #this one is important - don't want to miss any bounce messages! +#LINE 77. +} elsif anyof (header :contains "From" ["and here I put a whitelist of pretty much all the email addresses in my address book - it's several pages..."]) { + fileinto "INBOX.white"; +# better than keep; +# LINE 106. + + +} elsif anyof (address :all :is ["To", "CC", "BCC"] "Firstname.lastname@fastmail.fm", #a couple people send to this, but I have have all their addrs in whitelist so OK. + header :matches "X-Spam-score" ["9.?" , "10.?", "9", "10", "11.?", "12.?" ,"13.?", "14.?", "11", "12","13", "14", "15.?", "16.?", "17.?" ,"18.?", "19.?", "15", "16", "17" ,"18", "19", "2?.?", "2?", "3?.?" , "3?", "40"]) { #"5.?", "6.?", "5", "6" "7.?" , "8.?" , "7", "8" + reject text: + Hello. The server content filter/spam detector I use has bounced your message. It appears to be spam. + + I do not accept spam/UCE (Unsolicited Commercial Email). + +Please ask me how to bypass this filter if your email is not UCE. In that case, I am sorry about this +highly unusual error. The filter is >99% accurate. + + (This is an automated message; I will not be aware that your message did not get through if I do not hear from you again.) + + -Firstname + + (P.S. You may also override the filter if you accept the terms at http://www.lastname.com/spamoff.htm, + by including "lastname.com/spamoff.htm agreed to." in the subject.) +. + ; +#LINE 127. + +} elsif +header :matches "X-Spam" ["spam", "high"] { if #optimization idea line 1/2 + header :matches "X-Spam-score" ["5.?", "6.?", "5", "6"] { + fileinto "INBOX.Spam.5-7"; +} elsif header :matches "X-Spam-score" ["7.?" , "8.?" , "7", "8"] { + fileinto "INBOX.Spam.7-9"; +#} elsif header :matches "X-Spam-score" ["9.?" , "10.?" , "9", "10"] { #These lines obsoleted by reject text rule above, but others will find 'em useful! +# fileinto "INBOX.Spam.9-11"; +#} elsif header :matches "X-Spam-score" ["11.?" , "12.?" ,"13.?" , "14.?", "11" , "12" ,"13" , "14"] { +# fileinto "INBOX.Spam.11-15"; +#} elsif header :matches "X-Spam-score" ["15.?" , "16.?" ,"17.?" ,"18.?" , "19.?", "15" , "16" ,"17" ,"18" , "19"] { +# fileinto "INBOX.Spam.15-20"; +#} elsif header :matches "X-Spam-score" ["2?.?", "2?" ] { +# fileinto "Inbox.Spam.20-30"; +#} elsif header :matches "X-Spam-score" ["3?.?" , "3?", "40"] { +#fileinto "Inbox.Spam.30-40"; + } #optimization idea line 2/2 + +#LINE 149. + +} elsif header:contains ["Content-Type","Subject"] ["ks_c_5601-1987","euc_kr","euc-kr"]{ + fileinto "Inbox.Spam.kr"; #block Korean; it's prolly spam and I certainly can't read it. +} elsif header :contains "Received" "yale.edu" { + fileinto "INBOX.Yale"; #if it made it past all the filters above, it's probably of interest. + } elsif anyof (header :contains "Subject" ["HR 1910", "viagra", "MLM", " "," " ], # common in spam. (prolly redundant to SpamAssassin.) + not exists ["From", "Date"], #RFC822 violations common in spam. + header :contains ["Sender", "X-Sender", "Mailing-List", "X-Apparently-From", "X-Version", "X-Sender-IP", "Received", "Return-Path", "Delivered-To", "List-Post", "Date", "Subject", "To", "Cc", "From", "Reply-to", "X-AntiAbuse", "Content-Type", "Received", "X-LinkName"] ["btamail.net.cn", "@arabia.com" ] ) { #spam havens. + fileinto "INBOX.GreyMail"; +} elsif header :contains ["Precedence", "Priority", "X-Priority", "Mailing-List", "Subject", "From", "Received", "X-LinkName"] ["Bulk", "Newsletter"] { + fileinto "INBOX.Bulk Precedence"; +} elsif header :contains ["to", "cc", "Received"] ["IT@lastname.com", "mail.freeservers.com"] { + fileinto "INBOX.lastname.IT"; +} elsif header :contains ["To", "CC"] "Firstname@lastname.com" { + fileinto "INBOX.lastname.non-BCC"; +} +#LINE 167. +#END OF SCRIPT. Implied 'keep' is part of the Sieve spec. + + + + + + + diff --git a/pigeonhole/examples/jerry.sieve b/pigeonhole/examples/jerry.sieve new file mode 100644 index 0000000..ff8a922 --- /dev/null +++ b/pigeonhole/examples/jerry.sieve @@ -0,0 +1,224 @@ +# Example Sieve Script +# Author: Jerry +# URL: http://www.emaildiscussions.com/showthread.php?postid=145322#post145322 + +require ["fileinto", "reject", "vacation", "regex", "relational", +"comparator-i;ascii-numeric"]; + + +#### BLACKLIST - BOUNCE ANYTHING THAT MATCHES +# From individual addresses + if header :contains "from" + [ + "username@example.com", + "username@example.net" + ] + { reject "Message bounced by server content filter"; stop; } + +# From domains + elsif header :contains "from" + [ + "example.com", + "example.net" + ] + { reject "Message bounced by server content filter"; stop; } + + + +#### BLACKLIST - DELETE ANYTHING THAT MATCHES +# From individual addresses + elsif header :contains "from" + [ + "username@example.com", + "username@example.net" + ] + { discard; stop; } + +# From domains + elsif header :contains "from" + [ + "example.com", + "example.net" + ] + { discard; stop; } + +# I just added the following section after the joe-job +# that we all suffered at the hands of "inbox.com". +# The "myusername" is MY username at FastMail. +# DISCARDing this mail instead of directing it to a +# SPAM folder kept me from going over quota repeatedly. + +# To individual addresses + elsif header :contains "to" + [ + "myusername@inbox.com", + "myusername@example.net" + ] + { discard; stop; } + + elsif allof + ( + not anyof + ( +#### WHITELIST - KEEP ANYTHING THAT MATCHES +# From individual addresses + header :contains "from" + [ + "username@example.com", + "username@example.net" + ], + +# From trusted domains + header :contains "from" + [ + "example.com", + "example.net" + ], + +# Specific "to" address (mailing lists etc) + header :contains ["to", "cc"] + [ + "username@example.com", + "username@example.net" + ], + +# Specific "subject" keywords + header :contains "subject" + [ + "code_word_for_friend_#1", + "code_word_for_friend_#2" + ] + + ), + anyof + ( + +# Filter by keywords in subject or from headers + header :contains ["subject", "from"] + [ + "adilt", "adult", "advertise", "affordable", + "as seen on tv", "antenna", "alarm", + "background check", "bankrupt", "bargain", + "best price", "bikini", "boost reliability", + "brand new", "breast", "business directory", + "business opportunity", "based business", "best + deal", "bachelor's", "benefits", "cable", + "career", "casino", "celeb", "cheapest", "child + support", "cd-r", "catalog", "classified ad", + "click here", "coed", "classmate", "commerce", + "congratulations", "credit", "cruise", "cds", + "complimentary", "columbia house", "crushlink", + "debt", "detective", "diploma", "directv", + "directtv", "dish", "dream vacation", "deluxe", + "drug", "dvds", "dvd movie", "doubleclick", + "digital tv", "erotic", "exciting new", + "equalamail", "fantastic business", "fat + burning", "financial independence", "finalist", + "for life", "financing", "fitness", "fixed + rate", "four reports", "free!", "free + business", "from home", "funds", "fbi know", + "fortune", "gambl", "getaway", "girls", "great + price", "guaranteed", "get big", "get large", + "giveaway", "hard core", "hardcore", "home + document imaging", "home employment directory", + "homeowner", "home owner", "homeworker", "home + security", "home video", "immediate release", + "information you requested", "income", + "inkjet", "insurance", "interest rate", + "invest", "internet connection", "join price", + "judicial judgment", "just released", "know + your rights", "legal", "license", "loan", "long + distance", "look great", "low interest", + "low-interest", "low rate", "lust", "lbs", + "make money", "market", "master card", + "mastercard", "meg web", "merchant account", + "millionaire", "mini-vacation", "mortgage", + "master's", "magazine", "nasty", "new car", + "nigeria", "nude", "nympho", "naked", + "obligation", "online business", "opportunity", + "pager", "paying too much", "pda", "penis", + "pennies", "pills", "porn", "pounds", + "pre-approved", "prescri", "prscri", "prize", + "prostate", "printer ink", "quote", "refinanc", + "remove fat", "removing fat", "reward", + "sales", "satellite", "saw your site", + "scrambler", "sex", "smoking", "snoring", "some + people succeed", "special invitation", "special + offer", "stock", "saving", "singles", "teen", + "ticket", "tired of", "truth about anyone", + "the best", "ucking", "unbelievable", + "uncensored", "uncollected", "unlimited", "USA + domains", "urgent", "valium", "viagra", + "venture capital", "virgin", "visa", "vitamin", + "waist", "wealth", "webcam", "weight", "win a", + "winner", "win one", "work smarter", "work at + home", "xxx", "younger", "your web site", "your + money", "your date is wait", + "!!!", "$", "%", "10K" + ], + +# Filter when the subject is all uppercase (no lowercase) + header :regex :comparator + "i;octet" "subject" "^[^[:lower:]]+$", + +# Filter using regular expressions on the subject + header :regex "subject" + [ + "start.+business", "live.+auction", + "discover.+card", "pay.+college", "apr$", + "apr[^[:alnum:]]", "adv[^[:alnum:]]", + "free.+(coupon|info|install|money)", + "free.+(phone|sample|test|trial)", + "(buy|sell).+(house|home)" + ], + +# Filter with tracker codes in the subject + header :regex "subject" + "[[:space:].\-_]{4}#?\[?[[:alnum:]-]+\]?$", + +# Filter spam with no to/from address set + not exists ["To", "From"], + +# Filter spam not addressed to me +# Put here all of your own addresses (and alias) that you expect +# mail addressed to. I found a lot of my spam didn't have my +# name in the TO or CC fields at all -- it must have been in the +# BCC (which doesn't show in the headers). I can still get BCC +# mail from legitimate sources because everyone in my address +# book is on the WHITELIST above. + + not header :contains ["to", "cc"] + [ + "myusername@example.com", + "myusername@example.net" + ] + + ) + ) + { fileinto "INBOX.1_spam"; } + + + +#### Virus Filter + elsif header :contains ["subject", "from"] + [ + "infected file rejected", + "infected file rejected" + ] + { fileinto "INBOX.1_virus"; } + + +#### Telephone Alerts +# Any message that gets this far should not be spam, +# and a copy gets sent to my cell-phone as a TEXT message. + + elsif header :contains ["to", "cc"] + [ + "myusername@example.com", + "myaliasname@example.com" + ] + { redirect "2135551234@mobile.example.net"; keep; } + + + +# END OF SCRIPT diff --git a/pigeonhole/examples/mjohnson.sieve b/pigeonhole/examples/mjohnson.sieve new file mode 100644 index 0000000..802ecd8 --- /dev/null +++ b/pigeonhole/examples/mjohnson.sieve @@ -0,0 +1,421 @@ +# Example Sieve Script +# Author: Matthew Johnson +# URL: http://wiki.fastmail.fm/index.php?title=MatthewJohnson + +########################################################################## +####### SIEVE SCRIPT by Matthew Johnson - MRJ Solutions, Inc. ########### +####### Email me at mailto:mattjohnson2005@gmail.com ## +####### Code Version: 12JUN2004 ########### +########################################################################## +require ["envelope", "fileinto", "reject", "vacation", "regex", "relational", + "comparator-i;ascii-numeric"]; +# +# todo: +# change to a nested format with +# allof()s and nots. +# add "in address book" check. ex:"header :is :comparator "i;octet" "X-Spam-Known-Sender" "yes"" +# finish reformating lines to <= 75 col (for web edit box) +# and delete rulers. +# Mine Michael Klose script for ideas. +# Check out the update to the Sieve pages on the Fastmail Wiki. +# + +#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+ +require ["envelope", "fileinto", "reject", "vacation", "regex", + "relational", "comparator-i;ascii-numeric"]; + + + +# BLACKLIST - Mails to discard, drop on the floor. +# -high spam values except those delivered to me +# -Chinese content except for low spam values +# -virus rejected notifications +# -known spam addresses +# -newsletters that refuse my removal requests +# -twit-list +# -double twit-list +# -other + + +#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+ +if anyof + ( + allof # combo test one - high spam values except for mail to/from me + ( + # spam score is greater or equal to 14 + header :value "ge" :comparator "i;ascii-numeric" + ["X-Spam-score"] ["14"], + not header :contains "X-Spam-Score" "-", + not header :contains "X-Spam-Score" "0.0", + not header :contains ["to","from","cc","bcc","received"] + [ + # do not discard email to me, will file or discard + # as spam later if needed + "matt@zeta.net", + "matthew@bigsc.com", + "matthew_johnson@bigsmallcompany.com", + "mmm@spend.com", + "finger@spend.com", + "myyaacct@yahoo.com" + ] + ), # end allof + allof #combo test two - chinese content except for low spam values + ( + anyof + ( + header :regex "Subject" "^=\\?(gb|GB)2312\\?", # Chinese ecoding at subject + header :regex "Subject" "^=\\?big5\\?", # Other kind of Chinese mail + + # Chinese content type + header :contains "Content-Type" + [ + "GB2312", + "big5" + ] + ), #end anyof + not anyof + ( + #We have to check the sign and the value separately: ascii-numeric, defined at + #header :contains "X-Spam-Score" "-", + header :value "lt" :comparator "i;ascii-numeric" "X-Spam-Score" "3" + ) #end not anyof + ), # end allof - test two + + # single tests + + # discard fastmail virus notifications + header :is ["subject"] ["Infected file rejected"], + + # black list, invalid addresses receiving a large amount of spam + # or spam bounces,rejected zeta.net accounts. + header :contains ["X-Delivered-to"] + + ["eagleeye@zeta.net","ealgeeye@zeta.net", + "alica.thiele@zeta.net", "2005@theta.com", + "jimlovingu2@zeta.net", + "alpha@zeta.net", + "JoshuaS@zeta.net", + "donnaf@zeta.net", + "pspinks@zeta.net", + "jsherman@zeta.net", + "holly@zeta.net", + "clabarca@zeta.net", + "meghanr@zeta.net", + "rtaylor@zeta.net", + "lboone@zeta.net", + "brower@zeta.net", + "jenj@zeta.net", + "cbackus@zeta.net", + "spengles@zeta.net", + "adams@zeta.net", + "dsmith@zeta.net", + "jwilderman@zeta.net", + "TimF@zeta.net", + "zd@zeta.net", + "louise@zeta.net"] + + # single 'not' tests + # ---out for testing--- not header :is :comparator "i;octet" "X-Spam-Known-Sender" "yes" + ) # end anyof() +{ + discard; + stop; +} + + +# +# WHITELIST - Keep these mails and put them in the inbox +# (some kept getting put in Junk Mail) +# Family, Friends, Current Vendors, Customers +# Contents of fastmail address book. +# +#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+ +if anyof ( header :contains ["from","to","cc","bcc"] + [ "notification@eBay.com", + "MAILER-DAEMON@zeta.net", + "USPS_Track_Confirm@usps.com", + "credit.services@target.com", + "Comcast_Paydirect@comcast.net", + "mary@zeta.net", + "betty@zeta.net", + "andmanymore@zeta.net" + ], + header :is :comparator "i;octet" "X-Spam-Known-Sender" "yes" + ) +{ + fileinto "INBOX"; + stop; +} + +# redirects +if header :contains ["to", "cc"] "mary1@zeta.net" + { + redirect "mary@zeta.net"; + stop; + } + + +# +# +Spam filtering by score on 3, 5 and 14(above). +# +# +if header :value "ge" :comparator "i;ascii-numeric" ["X-Spam-score"] ["5"] { + fileinto "INBOX.Junk Mail.ge5"; + stop; +#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+ +} elsif header :value "ge" :comparator "i;ascii-numeric" ["X-Spam-score"] ["3"] { + fileinto "INBOX.Junk Mail.ge3"; + stop; +} + + +# Potential Blacklist, start with soft discard, then migrate to full discard above +# +# Blacklist (2nd) During testing, throw into "Junk Mail.discard" until +# ready to discard. +# +if anyof + ( + # rejects for accounts across all domains + header :contains ["X-Delivered-to"] + [ + "drjoe@","VX@", + "alfa@zeta.net", + "media@zeta.net", + "zeta@zeta.net", + "xyz@zeta.net" + ], + + # other criteria - weird message from this account + header :contains ["from"] ["Charlie Root"], + # mailers that are always sending spam returns to me + header :contains ["from"] ["MAILER-DAEMON@aol.com"] , + header :contains ["from"] ["MAILER-DAEMON@otenet.gr"] , + + # common account names that I don't use in any of my domains and that spammers like + header :contains ["X-Delivered-to"] + [ "biz@","sales@","support@", "service@", "reg@", + "registration@", "regisration@", "root@", "webmaster@", "noreply@" + ], + # zeta.net common account names to reject + header :contains ["X-Delivered-to"] ["info@zeta.net"], + # bigsc.com rejects + header :contains ["X-Delivered-to"] ["info@bigsc.com"], + # theta.com rejects + header :contains ["X-Delivered-to"] ["info@theta.com"], + header :contains ["X-Delivered-to"] ["reg@theta.com"] +#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+ + # saves for use maybe later + # header :contains ["X-Delivered-to"] ["webmaster@zeta.net"], + # header :contains ["X-Delivered-to"] ["webmaster@theta.com"], + # header :contains ["X-Delivered-to"] ["sales@bs.com"], + # header :contains ["X-Delivered-to"] ["sales@theta.com"], + # header :contains ["X-Delivered-to"] ["sales@bigsc.com"], + # header :contains ["X-Delivered-to"] "root@zeta.net", + + ) #end anyof() 2nd blacklist +{ + + fileinto "INBOX.Junk Mail.discard"; + stop; +} + + +# +Greylist, move to "INBOX.Junk Mail.greylist" +# +# 'Soft' Blacklist ?Greylist? +# + +#annoying person(s) that send questionable attachments +# look at occationally +if header :contains "from" "alex@yahoo.com" +{ + fileinto "INBOX.Junk Mail.greylist"; +} elsif header :contains "subject" "MAILER-DAEMON@fastmail.fm" + # non-person, but might + # want to look at it while + # figuring issues +{ + fileinto "INBOX.Junk Mail.greylist"; + stop; +} + +# +Spammy domains to filter +# +# domains that are known to be present in spam +# +if header :contains ["from", "received"] [".ru",".jp", ".kr", ".pt", + ".pl",".at",".cz",".cn",".lu" ] +{ + fileinto "INBOX.Junk Mail.discard"; + stop; +} + + +# +# Annoying newsletters that won't unsubscribe me, reject +# + +if anyof ( + #annoying newsletters + header :contains ["from"] "VistaPrintNews", # 2003 + header :contains ["from"] "newsletter@briantracyintl.com", # 2003 + header :contains ["from"] "info@yogalist.com", # 2003 + header :contains ["from"] "The Angela Larson Real Estate Team", + header :contains ["from"] "Brian Tracy" + ) +#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+ +{ + reject "I HAVE TRIED TO UNSUBSCRIBE; I DO NOT WANT YOUR NEWSLETTER; PLEASE UNSUBSCRIBE ME"; + stop; +} + + + + +# +# Suspected zeta.net user from/to Zeta Institute, NY - reject +# +# +# +if header :contains ["X-Delivered-to","from"] + [ + # aaaaNEW_ENTRIES_ABOVE ################################### + "neville@zeta.net", + "animika@zeta.net", + "linda@zeta.net", + "jerry@zeta.net", + "adamS@zeta.net", + "lkdamon@zeta.net", + "AdamS@zeta.net", + "DConnor@zeta.net", + "LOUISR@zeta.net", + + # Start of Alpha ############################################# + "Allanv@zeta.net", + "AmberJ@zeta.net", + "DANDERSON@zeta.net", + "Jonas@zeta.net", + "KarenE@zeta.net", + "J.R.C.@zeta.net", # check to see if this is working + "PMackey@zeta.net", + + "adrienne@zeta.net","alpha@zeta.net","amina@zeta.net", + "anamika@zeta.net", + "claborca@zeta.net","communications@zeta.net", + "cz241@zeta.net", + "dee@zeta.net", + "ellenb@zeta.net","evis@zeta.net", + "frivera@zeta.net", + "gblack@zeta.net","gbrown@zeta.net","george@zeta.net","grace@zeta.net", + "happygolucky@zeta.net","hsp@zeta.net", + "ila@zeta.net", + "jacqueline_fenatifa@zeta.net","jlengler@zeta.net", + "joel@zeta.net","jolsen@zeta.net", "jsherman@zeta.net", + "kronjeklandish@zeta.net","kwilcox@zeta.net","bettyb@zeta.net", + "laurie@zeta.net","llmansell@zeta.net", + "louise@zeta.net","lzollo@zeta.net", + "mcraft@zeta.net","meganB@zeta.net","mwezi@zeta.net", + "nanwile@zeta.net", + "zetasound@zeta.net", + "peter@zeta.net", + "randi@zeta.net", "rcbackus@zeta.net", "registration@zeta.net", + "registration@omgea.org", + "rtaylor@zeta.net", + "sdonnarumma@zeta.net","stephanR@zeta.net","suzanne@zeta.net","suzzane@zeta.net", + "taryngaughan_dn@zeta.net" + # zzzzEND_OF_LIST#### + ] #end of Xdelivered-to list for possible zeta institute users + +{ + reject text: + ERROR: Your email has not been delivered. + + You have reached the mailer at zeta.net + + Perhaps you want to send to Zeta Institute in DillyDally, NY, USA? + + Use USER@zeta.net for them + + or try registration@zeta.net + Check the website at http://www.zeta.net/zeta/contact/ + Call Registration at 1 800 944 1001. + + or use this information: + + Zeta Institute + 150 River Drive + DillyDally, NY 12666 + Registration: 800-900-0000 + Ph: 845-200-0000 + Fax: 845-200-0001 + registration@zeta.net + + sincerely, POSTMASTER +. +; + fileinto "Inbox.Junk Mail.ezeta"; + stop; + } +#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+ +# +Move messages into folders +# +# Process other messages into separate folders +# + # newsletters and mail lists +if header :contains ["subject"] + [ "newsletter", "[tc-ieee-", "[icntc", + "JUG News", "Xdesksoftware", + "announcement" ] +{ + fileinto "INBOX.Newsletters"; +} elsif header :contains ["from","subject"] ["Anthony Robbins"] { + fileinto "INBOX.Newsletters"; +} elsif header :contains ["from","subject"] ["MN Entrepreneurs","ME!"] { + fileinto "INBOX.Newsletters"; +} elsif header :contains ["from","received"] "adc.apple.com" { + fileinto "INBOX.Newsletters"; +} elsif header :contains "from" "wnewadmn@ieee.org" { + fileinto "INBOX.Newsletters"; +} elsif header :contains "from" "@lb.bcentral.com" { # techworthy@lb.bcentral.com + fileinto "INBOX.Newsletters"; +} elsif header :contains "from" "announcement@netbriefings.com" { #st paul company + fileinto "INBOX.Newsletters"; +} elsif header :contains "from" "newsletter@eletters.extremetech.com" { #semi-annoying rag + fileinto "INBOX.Newsletters"; +#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+ +# my newsletter throw-away addresses +} elsif header :contains "to" ["microcenter@zeta.net","nmha@zeta.net"] { + fileinto "INBOX.Newsletters"; + +#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+ +# +# Alerts mailbox +} elsif header :contains ["subject", "from"] + [ + "Alert", # F-Prot virus alert service, matches: + # "FRISK Virus Alert" + # or use s:FRISK Virus Alert: + # or use f:support@f-prot.com + "Payment", # Alerts from other payments + "credit.services@target.com", # Target Card Payments + "notify@quickbase.com" # Tic Talkers Database changes + ] +{ + fileinto "INBOX.Alerts"; + stop; +} + +# +Announcements from Dave Rolm, forward +# +# Perl Announcements from Dave Rolm +if header :contains "from" "dave@other.org" +{ + fileinto "Inbox"; + keep; +} +#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+ +####################################################################### +#### END OF SIEVE SCRIPT by Matthew Johnson - MRJ Solutions, Inc. ##### +################ email me at mailto:mattjohnson2005@gmail.com # + diff --git a/pigeonhole/examples/mklose.sieve b/pigeonhole/examples/mklose.sieve new file mode 100644 index 0000000..598cffb --- /dev/null +++ b/pigeonhole/examples/mklose.sieve @@ -0,0 +1,303 @@ +# Example Sieve Script +# Author: Michael Klose +# URL: http://wiki.fastmail.fm/index.php?title=MichaelKloseSieveScript + +require ["fileinto", "reject", "vacation", "regex", "relational", "comparator-i;ascii-numeric"]; + +# Experimental + +# End experimental + + + +# ---------------------------------------------- +# Discard messages (high Spam values) +# ---------------------------------------------- + +if anyof + ( + allof + ( + #Spam score > 17? + #We have to check the sign and the value separately: ascii-numeric, defined at http://www.ietf.org/rfc/rfc2244.txt, doesn't see minus signs or decimal points ("-" or "."). + header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "17", + not header :contains "X-Spam-Score" "-", + + not header :contains ["to","cc"] + [ + "@my-domain.de", + "myemail@myotherdomain.us", + "myotheremail@myotherdomain.us", + "myotheremail2@myotherdomain.us" + # Do not discard stuff going to me - gets filed into Junk later + ], + not header :contains "from" + [ + "lockergnome.com", + "Excite@info.excite.com" # gets filed into Junk later + ] + + + ), + allof + ( + header :contains "X-LinkName" "hotmail", # OR anything from Hotmail with low spam + allof + ( + header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "7", + not header :contains "X-Spam-Score" "-" + ) + ), + + # Black List + + header :contains "from" + [ + "ahbbcom@cncorn.com", + "Darg. B." + ], + + # Chinese Encoding at BEGINNING of Subject + + allof + ( + anyof + ( + header :regex "Subject" "^=\\?(gb|GB)2312\\?", # Chinese ecoding at subject + header :regex "Subject" "^=\\?big5\\?", # Other kind of Chinese mail + + # Chinese content type + + header :contains "Content-Type" + [ + "GB2312", + "big5" + ] + ), + not anyof + ( + #Spam score > -4? <sic> - ascii-numeric ignores the ".9"!. -Or is this correct? + #We have to check the sign and the value separately: ascii-numeric, defined at http://www.ietf.org/rfc/rfc2244.txt, doesn't see minus signs or decimal points ("-" or "."). + + header :contains "X-Spam-Score" "-", + header :value "lt" :comparator "i;ascii-numeric" "X-Spam-Score" "4" + ) + ) + ) + +{ + + + # discard; + + if header :contains "X-LinkName" "hotmail" + { discard; } + else + { fileinto "INBOX.Junk.Reject"; } + # I used to reject this stuff, but I wanted to know what I was rejecting, and this stuck. + stop; +} + + + +# Addresses that need to be forwarded to a different domain here before spam checking +# ******************************Michael - I don't understand what you're doing here! -elvey +# REPLY: this here is actually used to forward stuff addressed to my sister (using my domain) +# to her - without using one of the own-domain aliases. + +if header :contains ["to", "cc"] + [ + "bla@blabla.de", + "bla2@blabla.us", + "bla3@blabla.us" + ] + { + redirect "otheremailaddress@something.com"; + redirect "anotheremailadress@something.com"; + stop; + } + + +# File into a folder before Spam filtering + +if header :contains ["to","cc"] + [ + "important@mydomain.us", + "important2@mydomain.us" + ] + { + fileinto "Inbox.Important"; + stop; + } + + + +# ------------------------------------------- +# Filing rules +# ------------------------------------------- + + +# Pre-SPAM + + +if size :over 750K + { + fileinto "INBOX.largemail"; + stop; + } + + +if header :contains "from" + [ + +# White list 1 (with SMS notification) + + "Fred Bloggs", + "f.bloggs@hotmail.com", + "myboss@somecompany.com", + "Trisha", + "endofauction@ebay.de" # I want to know about end of auctions + ] + { + fileinto "Inbox"; + + # Send an SMS + redirect "smsgateway@somegateway.de"; + keep; + + stop; + } + + # Advertising I want to receive, which normally ends up in the SPAM filter + + if anyof + ( + header :contains "from" + + [ + +# Advertising whitelist + + "Mark Libbert", + "newsletter@snapfish.dom" + ], + header :contains "Return-Path" "mailings@gmx.dom" + ) + { fileinto "INBOX.Ads"; } + elsif header :contains "from" + [ + "newsletter@neuseelandhaus.dom", + "Lockergnome", + "CNET News.com" + ] + { fileinto "INBOX.Newsletter"; + + + +# Spam protection + + +} elsif anyof + ( + + #Spam assasin + allof + ( + header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "6", + not header :contains "X-Spam-Score" "-", + not anyof # White list + ( + header :contains "From" # Whitelist From addresses + [ + "CNN Quick News", + "FastMail.FM Support", + "lockergnome.com" + ] + ) + ), + + # User defined + + # Filter out Femalename1234z12@ spam (base64 encoded) + allof + ( + header :regex "From" "alpha:{2,}digit:{2,}alpha:+digit:{2,}@", + header :contains "Content-Type" "multipart/mixed" + ), + # Filter our Spam with invalid headers. You can see this because FM adds + # @fastmail.fm to them. For safty, check that mklose@ @michael-klose mkmail@gmx do + # not appear + + # Mklose: addition: The only negative side effect I have seen of the condition below + # is that it catches the FM newsletters. So far I find them in the spam occasionly + # but since they are so few, I have never bothered changing this to not catch them. + + allof + ( + header :contains "To" "@fastmail.fm", # I do not have a fastmail address # This doesn't catch BCC's; you should be checking the envelop instead. -elvey + not header :contains ["To", "CC", "Reply-To"] ["klose","mkmail@gmx.dom", "chaospower"] + ) + ) + { + fileinto "INBOX.Junk"; + stop; + } + + +# Post Spam-protection + + elsif header :contains ["to", "cc"] "gpc@gnu.dom" { + fileinto "INBOX.GPC"; +} elsif header :contains ["to", "cc"] "alfs\-discuss@linuxfromscratch.dom" { + fileinto "INBOX.LFS-Support.ALFS"; +} elsif header :contains "subject" "(usagi\-users" { + fileinto "INBOX.Usagi"; +} elsif anyof (header :contains "Subject" "\[eplus-de\]", header :contains "Reply-To" "eplus-de") { + fileinto "INBOX.E-Plus"; +} elsif header :contains ["to", "cc"] "lfs\-support@linuxfromscratch.dom" { + fileinto "INBOX.LFS-Support"; +} elsif header :contains ["to", "cc"] "netdev@oss.sgi.dom" { + fileinto "INBOX.NetDev"; +} elsif header :contains ["to", "cc"] "lfs\-dev@linuxfromscratch.dom" { + fileinto "INBOX.LFS-DEV"; +} elsif header :contains "from" "GMX Best Price" { + fileinto "INBOX.Werbung"; +} elsif header :contains "subject" "RHN Errata Alert" { + fileinto "INBOX.Notifications"; +} elsif header :contains "from" + [ + "EmailDiscussions.com Mailer", + "help1@dungorm.dom" + ] { + fileinto "INBOX.Notifications"; +} elsif header :contains "subject" "\[Gaim\-commits\]" { + fileinto "INBOX.Notifications"; +} elsif header :contains "subject" "\[Bug" { + fileinto "INBOX.Notifications.Bugzilla"; +} elsif header :contains "X-LinkName" "hotmail" { + fileinto "INBOX.Old Hotmail.new"; +} + + +# ----------------------------------------------------------------------- +# SMS notifications and forwarding +# ----------------------------------------------------------------------- + +if allof + ( + header :contains "to" ["@mydomain1.de","email@mydomain2.us","email2@somedomain"], + not header :contains "from" + [ + +# This avoids sending SMS notifications if I am the sender + + "@mydomain1.de", + "myotheremail@somedomain.de", + "myotheremail@someotherdomain.de" + ] + ) + { + redirect "smsgateway@somegateway.com"; + keep; + } + diff --git a/pigeonhole/examples/relational.rfc5231.sieve b/pigeonhole/examples/relational.rfc5231.sieve new file mode 100644 index 0000000..81c66d3 --- /dev/null +++ b/pigeonhole/examples/relational.rfc5231.sieve @@ -0,0 +1,33 @@ +require ["relational", "comparator-i;ascii-numeric", "fileinto"]; + +if header :value "lt" :comparator "i;ascii-numeric" + ["x-priority"] ["3"] +{ + fileinto "Priority"; +} + +elsif address :count "gt" :comparator "i;ascii-numeric" + ["to"] ["5"] +{ + # everything with more than 5 recipients in the "to" field + # is considered SPAM + fileinto "SPAM"; +} + +elsif address :value "gt" :all :comparator "i;ascii-casemap" + ["from"] ["M"] +{ + fileinto "From N-Z"; +} else { + fileinto "From A-M"; +} + +if allof ( + address :count "eq" :comparator "i;ascii-numeric" + ["to", "cc"] ["1"] , + address :all :comparator "i;ascii-casemap" + ["to", "cc"] ["me@foo.example.com"] ) +{ + fileinto "Only me"; +} + diff --git a/pigeonhole/examples/rfc3028.sieve b/pigeonhole/examples/rfc3028.sieve new file mode 100644 index 0000000..e8f6972 --- /dev/null +++ b/pigeonhole/examples/rfc3028.sieve @@ -0,0 +1,58 @@ +# +# Example Sieve Filter +# Declare any optional features or extension used by the script +# +require ["fileinto", "reject"]; + +# +# Reject any large messages (note that the four leading dots get +# "stuffed" to three) +# +if size :over 1M + { + reject text: +Please do not send me large attachments. +Put your file on a server and send me the URL. +Thank you. +.... Fred +. +; + stop; + } +# + +# Handle messages from known mailing lists +# Move messages from IETF filter discussion list to filter folder +# +if header :is "Sender" "owner-ietf-mta-filters@imc.org" + { + fileinto "filter"; # move to "filter" folder + } +# +# Keep all messages to or from people in my company +# +elsif address :domain :is ["From", "To"] "example.com" + { + keep; # keep in "In" folder + } + +# +# Try and catch unsolicited email. If a message is not to me, +# or it contains a subject known to be spam, file it away. +# +elsif anyof (not address :all :contains + ["To", "Cc", "Bcc"] "me@example.com", + header :matches "subject" + ["*make*money*fast*", "*university*dipl*mas*"]) + { + # If message header does not contain my address, + # it's from a list. + fileinto "spam"; # move to "spam" folder + } + else + { + # Move all other (non-company) mail to "personal" + # folder. + fileinto "personal"; + } + diff --git a/pigeonhole/examples/sanjay.sieve b/pigeonhole/examples/sanjay.sieve new file mode 100644 index 0000000..1a4d622 --- /dev/null +++ b/pigeonhole/examples/sanjay.sieve @@ -0,0 +1,171 @@ +# Example Sieve Script +# Author: SanjaySheth +# URL: http://wiki.fastmail.fm/index.php?title=SanjaySieveSpamFilter + +require "fileinto"; + +if anyof ( + + # Blacklisted sender domains + header :contains ["from", "Received", "X-Sender", "Sender", + "To","CC","Subject","X-Mail-from"] + [ "123greetings", "allfreewebsite.com", + "new-fields.com","atlasrewards","azogle.com", + "bannerport.net","bettingextreme.com","bigemailoffers.com", + "BlingMail.com", + "beyondoffers.net", ".biz ", ".biz]", + "cavalrymail.com","ciol.com","citywire.co.uk", + "cosmicclick.com", + "consumergamblingreport","creativemailoffers.com","creativeoffers.com", + "daily-promotions.com", + "dailypromo.","dailypromotions.", + "dandyoffers","dlbdirect", + "e54.org", "email-specials.net","email-ware.com","emailoffersondemand", + "emailbargain.com","emailofferz","emailrewardz","etoll.net","emailvalues.com", + "evaluemarketing.com","exitrequest.com", + "fantastic-bargain.com","fpsamplesmail.com","freelotto", + "findtv.com", "freddysfabulousfinds.com", + "genuinerewards.com", + "hotdailydeal.com","hulamediamail","hy-e.net", + "inboxbargains.com","idealemail.com", + "jackpot.com","jpmailer.com", + "lolita","lund.com.br", + "mafgroup.com","mailasia.com","mailtonic.net","migada.com","ms83.com", + "nationaloffers.com","nexdeals.com ", + "offercatch.com","offermagnet.com","offerservice.net","offertime.com", + "offersdaily.net","optnetwork.net", + "ombramarketing.com","on-line-offers.com","outblaze.com", + "permissionpass","primetimedirect.net","productsontheweb.net", + "rapid-e.net","recessionspecials", "redmoss","remit2india", + "sampleoffers.com","savingsmansion.com","sendoutmail.com","simpleoffers.com", + "specialdailydeals4u.com","Select-Point.net", + "speedyvalues.com","sportsoffers","sporttime.info","suntekglobal.com", + "superstorespecials.com", "synapseconnect","sunsetterawnings.com", + "thefreesamplenews","truemail.net", + "ub-kool","ultimatesports.info","uniquemailoffers","utopiad.com", + "unixlovers.net", + "valuesdirect","virtualoffers.net", + "wagerzine", "webdpoffrz", + "yestshirt.com", + "z-offer.com", "zipido.com" + ], + + # Blacklisted ip subnets due to excessive spam from them + header :contains "Received" + [ "[4.63.221.224", + "[24.244.141.112", + "[61.171.253.177", + "[63.123.149.", "[63.209.206.", "(63.233.30.73", "[63.251.200.", + "[64.41.183.","[64.49.250.", "[64.57.188.", "[64.57.221.", + "[64.62.204.", + "[64.70.17.", "[64.70.44.", "[64.70.53.", + "[64.39.27.6", "[64.39.27.7","[64.191.25.","[64.191.36.", + "[64.191.9.", + "[64.125.181.", "[64.191.123.", "[64.191.23.", "[64.239.182.", + "[65.211.3.", + "[66.46.150.", "[66.62.162.", "[66.118.170.", "[66.129.124.", + "[66.205.217.", "[66.216.111.", "[66.239.204.", + "[67.86.69.", + "[80.34.206.", "[80.80.98.", + "[81.72.233.13", + "[128.242.120.", + "[157.238.18", + "[168.234.195.18]", + "[193.253.198.57", + "[194.25.83.1", + "[200.24.129.", "[200.161.203.", + "[202.164.182.76]","[202.57.69.116", + "[203.19.220.","[203.22.104.","[203.22.105.", + "[204.188.52.", + "[205.153.154.203", + "[206.26.195.", "[206.154.33.","[206.169.178", + "[207.142.3.", + "[208.46.5.","[208.187.", + "[209.164.27.","[209.236.", + "[210.90.75.129]", + "[211.101.138.199","[211.185.7.125]","[211.239.231.", + "[212.240.95.", + "[213.47.250.139", "[213.225.61.", + "[216.22.79.","[216.39.115.","[216.99.240.", + "[216.126.32.", "[216.187.123.","[217.36.124.53", + "[218.145.25","[218.52.71.103","[218.158.136.115", + "[218.160.42.74", "[218.242.112.4]" + ], + + # Blacklisted SpamAssassin flags + header :contains ["SPAM", "X-Spam-hits"] + ["ADDRESSES_ON_CD","ACT_NOW","ADULT_SITE", "ALL_CAP_PORN", + "AMATEUR_PORN", "AS_SEEN_ON", + "BAD_CREDIT", "BALANCE_FOR_LONG_20K", "BARELY_LEGAL", "BEEN_TURNED_DOWN", + "BANG_GUARANTEE", "BANG_MONEY","BASE64_ENC_TEXT", + "BAYES_99","BAYES_90", + "BE_BOSS", "BEST_PORN", "BULK_EMAIL", + "CASINO", "CONSOLIDATE_DEBT", "COPY_ACCURATELY", "COPY_DVD", + "DIET", "DO_IT_TODAY","DOMAIN_4U2", + "EMAIL_MARKETING","EMAIL_ROT13", "EXPECT_TO_EARN","EARN_MONEY", + "FIND_ANYTHING", "FORGED_AOL_RCVD", + "FORGED_HOTMAIL_RCVD", "FORGED_YAHOO_RCVD", + "FORGED_RCVD_TRAIL", "FORGED_JUNO_RCVD", + "FORGED_MUA_", + "FREE_MONEY","FREE_PORN", + "GENTLE_FEROCITY", "GET_PAID", "GUARANTEED_STUFF", "GUARANTEED_100_PERCENT", + "HAIR_LOSS", "HIDDEN_ASSETS", "HGH,", "HOME_EMPLOYMENT","HOT_NASTY","HTTP_ESCAPED_HOST", + "HTTP_USERNAME_USED","HTML_FONT_INVISIBLE", + "IMPOTENCE","INVALID_MSGID","INVESTMENT", + "LESBIAN","LIVE_PORN","LOSE_POUNDS", + "MARKETING_PARTNERS", "MORTGAGE_OBFU", "MORTGAGE_RATES", + "NIGERIAN_SCAM", "NIGERIAN_TRANSACTION_1", "NIGERIAN_BODY", "NUMERIC_HTTP_ADDR", + "NO_MX_FOR_FROM","NO_DNS_FOR_FROM", + "OBFUSCATING_COMMENT", "ONLINE_PHARMACY", + "PENIS_ENLARGE", + "PREST_NON_ACCREDITED", "PURE_PROFIT","PORN_4", + "RCVD_IN_DSBL", "RCVD_IN_OSIRUSOFT_COM","RCVD_IN_BL_SPAMCOP_NET", "RCVD_IN_SBL", + "RCVD_IN_MULTIHOP_DSBL", "RCVD_IN_RELAYS_ORDB_ORG", "RCVD_IN_UNCONFIRMED_DSBL", + "RCVD_FAKE_HELO_DOTCOM", "RCVD_IN_RFCI", "RCVD_IN_NJABL","RCVD_IN_SORBS", + "REFINANCE", "REVERSE_AGING", + "SAVE_ON_INSURANCE","SPAM_REDIRECTOR", "STOCK_ALERT", "STOCK_PICK", "STRONG_BUY", + "SEE_FOR_YOURSELF", "SUPPLIES_LIMITED", + "THE_BEST_RATE","TONER", + "UNSECURED_CREDIT", + "VACATION_SCAM", "VIAGRA", "VJESTIKA", + "WHILE_SUPPLIES", "WORK_AT_HOME", + "X_OSIRU_DUL", "X_OSIRU_SPAMWARE_SITE", "X_OSIRU_SPAM_SRC" + ], + + + # Blacklisted subjects + + header :contains ["From","Subject"] + [" penis ", + "ADV:", "adult dvd", "adult movie", "adultdirect", "adultemail", + "background check", "bankrupt", "boobs", "business opportunity","big@boss.com", + "casino", "cash guarantee", + "debt free", "diet bread", "ebay secrets", "erection", + "financial freedom", "free credit", + "gambl", "gov grants", "jackpot", + "life insurance", "lottery", "lotto", + "mortgage", "nude", "OTCBB", + "penis", "porn", "promotion", "proven System", + " rape ", + " sex ", "skin resurfacing", "special offer", + "ultimate software", "viagra", "V1AGRA", "vivatrim", + "win money","work from home", "xxx" + ], + + # often spam emails to multiple addresses with same name & different domain + header :matches ["To","CC"] + ["*fastmail*fastmail*fastmail*fastmail*fastmail*"], + + # Almost all emails from these domains is spam (at least for me) + header :contains ["from", "received"] + [".ru ",".jp ", ".kr ", ".pt ",".pl ",".at ",".cz ", + ".ru>",".jp>", ".kr>", ".pt>", ".pl>",".at>",".cz>"], + + # Really high SpamAssassin scores (15.0+) + header :matches ["X-Spam-score","X-Remote-Spam-score"] [ + "1?.?", "2?.?", "3?.?", "4?.?", "5?.?", "6?.?" # 10.0 to 69.9 + ] +) { + fileinto "INBOX.Spam.discard"; + stop; +} diff --git a/pigeonhole/examples/sieve_examples.sieve b/pigeonhole/examples/sieve_examples.sieve new file mode 100644 index 0000000..6e7ca17 --- /dev/null +++ b/pigeonhole/examples/sieve_examples.sieve @@ -0,0 +1,73 @@ +# Example Sieve Script +# Author: unknown +# URL: http://wiki.fastmail.fm/index.php?title=MoreSieveExamples + +require ["fileinto", "reject"]; + +###BYPASSES### + +if anyof ( + header :contains ["From"] "friend1", + header :contains ["From"] "friend12", + header :contains ["From"] "friend3", + header :contains ["From"] "friendsdomanin", + header :contains ["Subject"] "elephant" ##a safeword + ) + { + fileinto "INBOX"; + stop; + } + +###BIG MESSAGE PROTECTION +if size :over 5000K { + reject "Message over 5MB size limit. Please contact me before sending this."; +} + +##SPAM FILTERING## +if header :contains ["X-Spam"] "high" { + discard; + stop; +} +if header :contains ["X-Spam-Flag"] "HIGH" { + discard; + stop; +} +if header :contains ["X-Spam"] "spam" { + fileinto "INBOX.spam"; #emails forwarded from my unviersity account get SA tagged like this + stop; +} +if header :contains ["X-Spam-Flag"] "YES" { + fileinto "INBOX.spam"; + stop; +} + +####LOCAL SPAM RULES####### +if header :contains ["From"] "bannerport" { discard; stop; } ##keyword filters for when SA doesn't quite catch them +if header :contains ["To"] "MATT NOONE" { discard; stop; } +###AUTO management rules### + +####Student Digest stuff#### ### Examples of boolean OR rules +if anyof ( + header :contains ["X-BeenThere"] "student-digest@list.xxx.edu", + header :contains ["X-BeenThere"] "firstyear-digest@list.xxx.edu", + header :contains ["X-BeenThere"] "secondyear-digest@list.xxx.edu", + header :contains ["X-BeenThere"] "thirdyear-digest@list.xxx.edu", + header :contains ["X-BeenThere"] "fourthyear-digest@list.xxx.edu" + ) + { + fileinto "INBOX.lists.digests"; + stop; + } +if allof ( ###A Boolean AND rule + header :contains ["From"] "buddy1", + header :contains ["To"] "myotheraddress" + ) + { + fileinto "INBOX.scc.annoy"; + stop; + } + +#other local rules +if header :contains ["Subject"] "helmreich" { fileinto "INBOX.lists.helmreich"; stop; } +if header :contains ["Subject"] "helmcomm" { fileinto "INBOX.lists.helmreich"; stop; } +if header :contains ["Subject"] "packeteer" { fileinto "INBOX.lists"; stop; } diff --git a/pigeonhole/examples/subaddress.rfc5233.sieve b/pigeonhole/examples/subaddress.rfc5233.sieve new file mode 100644 index 0000000..9e0177c --- /dev/null +++ b/pigeonhole/examples/subaddress.rfc5233.sieve @@ -0,0 +1,23 @@ +require ["envelope", "subaddress", "fileinto"]; + +# In this example the same user account receives mail for both +# "ken@example.com" and "postmaster@example.com" + +# File all messages to postmaster into a single mailbox, +# ignoring the :detail part. +if envelope :user "to" "postmaster" { + fileinto "inbox.postmaster"; + stop; +} + +# File mailing list messages (subscribed as "ken+mta-filters"). +if envelope :detail "to" "mta-filters" { + fileinto "inbox.ietf-mta-filters"; +} + +# Redirect all mail sent to "ken+foo". +if envelope :detail "to" "foo" { + redirect "ken@example.net"; +} + + diff --git a/pigeonhole/examples/vacation.sieve b/pigeonhole/examples/vacation.sieve new file mode 100644 index 0000000..660b9c5 --- /dev/null +++ b/pigeonhole/examples/vacation.sieve @@ -0,0 +1,23 @@ +require ["fileinto","reject", "vacation"]; +if allof (header :contains "X-Spam-Flag" "YES") +{ + discard ; +} + +elsif allof (header :contains "subject" "<quation>") +{ +vacation +:addresses "<name@domain.ru>" +:subject "<Answear>" +:mime "MIME-Version: 1.0 +Content-Type: text/html; charset=KOI8-R +Content-Transfer-Encoding: 7bit +<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"> +<HTML><HEAD><META http-equiv=Content-Type content=\"text/html; charset=windows-KOI8-R\"> +</HEAD><BODY>123</BODY></HTML>"; + discard ; +} +else +{ + keep; +} diff --git a/pigeonhole/examples/vivil.sieve b/pigeonhole/examples/vivil.sieve new file mode 100644 index 0000000..bce7507 --- /dev/null +++ b/pigeonhole/examples/vivil.sieve @@ -0,0 +1,94 @@ +# Example Sieve Script +# Author: Vivil +# URL: http://wiki.fastmail.fm/index.php?title=Vivil +# Removed unused notify require + +# ************************************************************************* +require ["envelope", "fileinto", "reject", "vacation", "regex", "relational", +"comparator-i;ascii-numeric"]; + + +if size :over 2048K { + reject "Message not delivered; size over limit accepted by recipient"; + stop; +} + +#because of the use of elsif below, none of the "stop;"'s below are needed, but they're good 'defensive programming'. Only the one above is actually needed. + +redirect "login@gmail.dom"; + +if header :contains ["from","cc"] +[ + "from-begin@beginbeginbeginbeginbeginbeginbeginbeginbegin.fr", + "sex.com newsletter", + "ad@gator.com", + "newsletter@takecareof.com", + "from-end@endendendendendendendendendendendendendendendend.fr" +] +{ + discard; + stop; +} + +elsif header :contains ["from"] +[ + "mygirlfriend-who-use-incredimail@foo.dom" +] +{ + fileinto "INBOX.PRIORITY"; + stop; +} + +#use of "to" field detection next lines is ONLY USEFUL FOR DOMAIN NAME OWNERS if you forward your mail to your fastmail account, some virus/spam send mail to well known addresses as info@willemijns.dom i never use... + +elsif header :contains ["to","cc"] +[ + "to-begin@beginbeginbeginbeginbeginbeginbeginbeginbegin.fr", + "FTPsebastien@willemijns.dom", + "info@willemijns.dom", + "webmaster@willemijns.dom", + "to-end@endendendendendendendendendendendendendendendend.fr" +] +{ + discard; + stop; +} + +elsif header :contains ["subject"] +[ + "subject-begin@beginbeginbeginbeginbeginbeginbeginbeginbegin.fr", + "Undeliverable mail: Registration is accepted", + "subject-end@endendendendendendendendendendendendendendendend.fr" +] +{ + discard; + stop; +} +elsif header :value "ge" :comparator "i;ascii-numeric" ["X-Spam-score"] ["6"] { + fileinto "INBOX.Junk Mail"; + stop; +} +elsif header :contains "from" "reflector@launay.dom" { + fileinto "INBOX.TEST"; + stop; +} +elsif header :contains "from" "do-not-reply@franconews.dom" { + fileinto "INBOX.TEST"; + stop; +} +elsif header :contains "from" "devnull@news.telefonica.dom" { + fileinto "INBOX.TEST"; + stop; +} +elsif header :contains ["to"] ["sebastien@willemijns.dom"] { + fileinto "INBOX.PRIORITY"; + stop; +} +elsif header :contains ["to"] ["seb@willemijns.dom"] { + fileinto "INBOX.PRIORITY"; + stop; +} +else { + fileinto "INBOX"; +} +# ******************************************************************** diff --git a/pigeonhole/install-sh b/pigeonhole/install-sh new file mode 100755 index 0000000..ec298b5 --- /dev/null +++ b/pigeonhole/install-sh @@ -0,0 +1,541 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2020-11-14.01; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +# Create dirs (including intermediate dirs) using mode 755. +# This is like GNU 'install' as of coreutils 8.32 (2020). +mkdir_umask=22 + +backupsuffix= +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -p pass -p to $cpprog. + -s $stripprog installed files. + -S SUFFIX attempt to back up existing files, with suffix SUFFIX. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG + +By default, rm is invoked with -f; when overridden with RMPROG, +it's up to you to specify -f if you want it. + +If -S is not specified, no backups are attempted. + +Email bug reports to bug-automake@gnu.org. +Automake home page: https://www.gnu.org/software/automake/ +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -p) cpprog="$cpprog -p";; + + -s) stripcmd=$stripprog;; + + -S) backupsuffix="$2" + shift;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + # Don't chown directories that already exist. + if test $dstdir_status = 0; then + chowncmd="" + fi + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dstbase=`basename "$src"` + case $dst in + */) dst=$dst$dstbase;; + *) dst=$dst/$dstbase;; + esac + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + case $dstdir in + */) dstdirslash=$dstdir;; + *) dstdirslash=$dstdir/;; + esac + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + # The $RANDOM variable is not portable (e.g., dash). Use it + # here however when possible just to lower collision chance. + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + + trap ' + ret=$? + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null + exit $ret + ' 0 + + # Because "mkdir -p" follows existing symlinks and we likely work + # directly in world-writeable /tmp, make sure that the '$tmpdir' + # directory is successfully created first before we actually test + # 'mkdir -p'. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null + fi + trap '' 0;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=${dstdirslash}_inst.$$_ + rmtmp=${dstdirslash}_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && + { test -z "$stripcmd" || { + # Create $dsttmp read-write so that cp doesn't create it read-only, + # which would cause strip to fail. + if test -z "$doit"; then + : >"$dsttmp" # No need to fork-exec 'touch'. + else + $doit touch "$dsttmp" + fi + } + } && + $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # If $backupsuffix is set, and the file being installed + # already exists, attempt a backup. Don't worry if it fails, + # e.g., if mv doesn't support -f. + if test -n "$backupsuffix" && test -f "$dst"; then + $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null + fi + + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/pigeonhole/ltmain.sh b/pigeonhole/ltmain.sh new file mode 100755 index 0000000..21e5e07 --- /dev/null +++ b/pigeonhole/ltmain.sh @@ -0,0 +1,11251 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 + +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 + +# Copyright (C) 1996-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +PROGRAM=libtool +PACKAGE=libtool +VERSION="2.4.6 Debian-2.4.6-15" +package_revision=2.4.6 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-01-20.17; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac +fi + +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" + fi" +done + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed <conftest.nl >conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' <conftest.nl >conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac + + +## ----------------- ## +## Standard options. ## +## ----------------- ## + +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. + +opt_dry_run=false +opt_quiet=false +opt_verbose=false + +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= + +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue + +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all + + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='[0m' + tc_bold='[1m'; tc_standout='[7m' + tc_red='[31m'; tc_green='[32m' + tc_blue='[34m'; tc_cyan='[36m' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1+=\\ \$func_quote_for_eval_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1=\$$1\\ \$func_quote_for_eval_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" + fi +} + + +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () +{ + $debug_cmd + + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} + + +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () +{ + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_for_eval ARG... +# -------------------------- +# Aesthetically quote ARGs to be evaled later. +# This function returns two values: +# i) func_quote_for_eval_result +# double-quoted, suitable for a subsequent eval +# ii) func_quote_for_eval_unquoted_result +# has all characters that are still active within double +# quotes backslashified. +func_quote_for_eval () +{ + $debug_cmd + + func_quote_for_eval_unquoted_result= + func_quote_for_eval_result= + while test 0 -lt $#; do + case $1 in + *[\\\`\"\$]*) + _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; + *) + _G_unquoted_arg=$1 ;; + esac + if test -n "$func_quote_for_eval_unquoted_result"; then + func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" + else + func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" + fi + + case $_G_unquoted_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_quoted_arg=\"$_G_unquoted_arg\" + ;; + *) + _G_quoted_arg=$_G_unquoted_arg + ;; + esac + + if test -n "$func_quote_for_eval_result"; then + func_append func_quote_for_eval_result " $_G_quoted_arg" + else + func_append func_quote_for_eval_result "$_G_quoted_arg" + fi + shift + done +} + + +# func_quote_for_expand ARG +# ------------------------- +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + $debug_cmd + + case $1 in + *[\\\`\"]*) + _G_arg=`$ECHO "$1" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; + *) + _G_arg=$1 ;; + esac + + case $_G_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_arg=\"$_G_arg\" + ;; + esac + + func_quote_for_expand_result=$_G_arg +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_for_expand "$_G_cmd" + eval "func_notquiet $func_quote_for_expand_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_for_expand "$_G_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2015-10-07.11; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + _G_rc_run_hooks=false + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook funcions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + if eval $_G_hook '"$@"'; then + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + _G_rc_run_hooks=: + fi + done + + $_G_rc_run_hooks && func_run_hooks_result=$_G_hook_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, you may remove/edit +# any options that you action, and then pass back the remaining unprocessed +# options in '<hooked_function_name>_result', escaped suitably for +# 'eval'. In this case you also must return $EXIT_SUCCESS to let the +# hook's caller know that it should pay attention to +# '<hooked_function_name>_result'. Returning $EXIT_FAILURE signalizes that +# arguments are left untouched by the hook and therefore caller will ignore the +# result variable. +# +# Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# # No change in '$@' (ignored completely by this hook). There is +# # no need to do the equivalent (but slower) action: +# # func_quote_for_eval ${1+"$@"} +# # my_options_prep_result=$func_quote_for_eval_result +# false +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# args_changed=false +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: +# args_changed=: +# ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# args_changed=: +# ;; +# *) # Make sure the first unrecognised option "$_G_opt" +# # is added back to "$@", we could need that later +# # if $args_changed is true. +# set dummy "$_G_opt" ${1+"$@"}; shift; break ;; +# esac +# done +# +# if $args_changed; then +# func_quote_for_eval ${1+"$@"} +# my_silent_option_result=$func_quote_for_eval_result +# fi +# +# $args_changed +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# false +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll also need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options_finish [ARG]... +# ---------------------------- +# Finishing the option parse loop (call 'func_options' hooks ATM). +func_options_finish () +{ + $debug_cmd + + _G_func_options_finish_exit=false + if func_run_hooks func_options ${1+"$@"}; then + func_options_finish_result=$func_run_hooks_result + _G_func_options_finish_exit=: + fi + + $_G_func_options_finish_exit +} + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + _G_rc_options=false + + for my_func in options_prep parse_options validate_options options_finish + do + if eval func_$my_func '${1+"$@"}'; then + eval _G_res_var='$'"func_${my_func}_result" + eval set dummy "$_G_res_var" ; shift + _G_rc_options=: + fi + done + + # Save modified positional parameters for caller. As a top-level + # options-parser function we always need to set the 'func_options_result' + # variable (regardless the $_G_rc_options value). + if $_G_rc_options; then + func_options_result=$_G_res_var + else + func_quote_for_eval ${1+"$@"} + func_options_result=$func_quote_for_eval_result + fi + + $_G_rc_options +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propagate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning $EXIT_SUCCESS (otherwise $EXIT_FAILURE is returned). +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + _G_rc_options_prep=false + if func_run_hooks func_options_prep ${1+"$@"}; then + _G_rc_options_prep=: + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result + fi + + $_G_rc_options_prep +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + func_parse_options_result= + + _G_rc_parse_options=false + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + if func_run_hooks func_parse_options ${1+"$@"}; then + eval set dummy "$func_run_hooks_result"; shift + _G_rc_parse_options=: + fi + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_match_parse_options=: + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + if test $# = 0 && func_missing_arg $_G_opt; then + _G_rc_parse_options=: + break + fi + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) _G_rc_parse_options=: ; break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift + _G_match_parse_options=false + break + ;; + esac + + $_G_match_parse_options && _G_rc_parse_options=: + done + + + if $_G_rc_parse_options; then + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + func_parse_options_result=$func_quote_for_eval_result + fi + + $_G_rc_parse_options +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + _G_rc_validate_options=false + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + if func_run_hooks func_validate_options ${1+"$@"}; then + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result + _G_rc_validate_options=: + fi + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + $_G_rc_validate_options +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 +} + + +# func_missing_arg ARGNAME +# ------------------------ +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $debug_cmd + + func_error "Missing argument for '$1'." + exit_cmd=exit +} + + +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () +{ + $debug_cmd + + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} + + +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} + + +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () +{ + $debug_cmd + + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () +{ + $debug_cmd + + $warning_func ${1+"$@"} +} + + +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname $scriptversion Debian-2.4.6-15 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to <bug-libtool@gnu.org>. +GNU libtool home page: <http://www.gnu.org/s/libtool/>. +General help using GNU software: <http://www.gnu.org/gethelp/>." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." +} + + +# func_config +# ----------- +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + + +# func_features +# ------------- +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test yes = "$build_libtool_libs"; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test yes = "$build_old_libs"; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + + +# func_enable_tag TAGNAME +# ----------------------- +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname=$1 + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + + +# func_check_version_match +# ------------------------ +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false + + nonopt= + preserve_args= + + _G_rc_lt_options_prep=: + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + *) + _G_rc_lt_options_prep=false + ;; + esac + + if $_G_rc_lt_options_prep; then + # Pass back the list of options. + func_quote_for_eval ${1+"$@"} + libtool_options_prep_result=$func_quote_for_eval_result + fi + + $_G_rc_lt_options_prep +} +func_add_hook func_options_prep libtool_options_prep + + +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + _G_rc_lt_parse_options=false + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_match_lt_parse_options=: + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"} ; shift + _G_match_lt_parse_options=false + break + ;; + esac + $_G_match_lt_parse_options && _G_rc_lt_parse_options=: + done + + if $_G_rc_lt_parse_options; then + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + libtool_parse_options_result=$func_quote_for_eval_result + fi + + $_G_rc_lt_parse_options +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote_for_eval ${1+"$@"} + libtool_validate_options_result=$func_quote_for_eval_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + + + +## ----------- ## +## Main. ## +## ----------- ## + +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if 'file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case $lalib_p_line in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test yes = "$lalib_p" +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $debug_cmd + + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# 'FILE.' does not work on cygwin managed mounts. +func_source () +{ + $debug_cmd + + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case $lt_sysroot:$1 in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result='='$func_stripname_result + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $debug_cmd + + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with '--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' + else + write_lobj=none + fi + + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T <<EOF +# $write_libobj - a libtool object file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object=$write_lobj + +# Name of the non-PIC object +non_pic_object=$write_oldobj + +EOF + $MV "${write_libobj}T" "$write_libobj" + } +} + + +################################################## +# FILE NAME AND PATH CONVERSION HELPER FUNCTIONS # +################################################## + +# func_convert_core_file_wine_to_w32 ARG +# Helper function used by file name conversion functions when $build is *nix, +# and $host is mingw, cygwin, or some other w32 environment. Relies on a +# correctly configured wine environment available, with the winepath program +# in $build's $PATH. +# +# ARG is the $build file name to be converted to w32 format. +# Result is available in $func_convert_core_file_wine_to_w32_result, and will +# be empty on error (or when ARG is empty) +func_convert_core_file_wine_to_w32 () +{ + $debug_cmd + + func_convert_core_file_wine_to_w32_result=$1 + if test -n "$1"; then + # Unfortunately, winepath does not exit with a non-zero error code, so we + # are forced to check the contents of stdout. On the other hand, if the + # command is not found, the shell will set an exit code of 127 and print + # *an error message* to stdout. So we must check for both error code of + # zero AND non-empty stdout, which explains the odd construction: + func_convert_core_file_wine_to_w32_tmp=`winepath -w "$1" 2>/dev/null` + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $debug_cmd + + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result= + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $debug_cmd + + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $debug_cmd + + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $debug_cmd + + if test -z "$2" && test -n "$1"; then + func_error "Could not determine host file name corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result=$1 + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $debug_cmd + + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " '$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result=$3 + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $debug_cmd + + case $4 in + $1 ) func_to_host_path_result=$3$func_to_host_path_result + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via '$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $debug_cmd + + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $debug_cmd + + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result=$1 +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result=$func_convert_core_msys_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via '$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $debug_cmd + + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd=func_convert_path_$func_stripname_result + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $debug_cmd + + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result=$1 +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + +# func_mode_compile arg... +func_mode_compile () +{ + $debug_cmd + + # Get the compilation command and the source file. + base_compile= + srcfile=$nonopt # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg=$arg + arg_mode=normal + ;; + + target ) + libobj=$arg + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify '-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs=$IFS; IFS=, + for arg in $args; do + IFS=$save_ifs + func_append_quoted lastarg "$arg" + done + IFS=$save_ifs + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg=$srcfile + srcfile=$arg + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with '-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj=$func_basename_result + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from '$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name '$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test yes = "$build_old_libs"; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test yes = "$need_locks"; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test warn = "$need_locks"; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test yes = "$build_libtool_libs"; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test no != "$pic_mode"; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test yes = "$suppress_opt"; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test yes = "$compiler_c_o"; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test no != "$need_locks"; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a 'standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to '-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the '--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the 'install' or 'cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with '-') are ignored. + +Every other argument is treated as a filename. Files ending in '.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. + +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode '$opt_mode'" + ;; + esac + + echo + $ECHO "Try '$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test : = "$opt_help"; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + $SED '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $debug_cmd + + # The first argument is the command name. + cmd=$nonopt + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "'$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "'$file' was not linked with '-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir=$func_dirname_result + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir=$func_dirname_result + ;; + + *) + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir=$absdir + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic=$magic + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file=$progdir/$program + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file=$progdir/$program + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd=\$cmd$args + fi +} + +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $debug_cmd + + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "'$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument '$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and '=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_quiet && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the '$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $debug_cmd + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac + then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=false + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=: ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the '$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir=$func_dirname_result + destname=$func_basename_result + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "'$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "'$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir=$func_dirname_result + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking '$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname=$1 + shift + + srcname=$realname + test -n "$relink_command" && srcname=${realname}T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme=$stripme + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try 'ln -sf' first, because the 'ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib=$destdir/$realname + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name=$func_basename_result + instname=$dir/${name}i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest=$destfile + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to '$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test yes = "$build_old_libs"; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext= + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=.exe + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script '$wrapper'" + + finalize=: + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test no = "$fast_install" && test -n "$relink_command"; then + $opt_dry_run || { + if $finalize; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file=$func_basename_result + outputname=$tmpdir/$file + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_quiet || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink '$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file=$outputname + else + func_warning "cannot relink '$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name=$func_basename_result + + # Set up the ranlib parameters. + oldlib=$destdir/$name + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run '$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test install = "$opt_mode" && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms=${my_outputname}S.c + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist=$output_objdir/$my_outputname.nm + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* External symbol declarations for the compiler. */\ +" + + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols=$output_objdir/$outputname.exp + $opt_dry_run || { + $RM $export_symbols + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from '$dlprefile'" + func_basename "$dlprefile" + name=$func_basename_result + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename= + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname"; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename=$func_basename_result + else + # no lafile. user explicitly requested -dlpreopen <import library>. + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename"; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 </dev/null >/dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + $my_pic_p && pic_flag_for_symtable=" $pic_flag" + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + + # Transform the symbol file into the correct name. + symfileobj=$output_objdir/${my_outputname}S.$objext + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for '$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $debug_cmd + + win32_libid_type=unknown + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s|.*|import| + p + q + } + }'` + ;; + esac + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $debug_cmd + + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $debug_cmd + + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1"; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result= + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test yes = "$lock_old_archive_extraction"; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $debug_cmd + + my_gentop=$1; shift + my_oldlibs=${1+"$@"} + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib=$func_basename_result + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" + cd "$darwin_curdir" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result=$my_oldobjs +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory where it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test yes = "$fast_install"; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + \$ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat <<EOF + +/* $cwrappersource - temporary wrapper executable for $objdir/$outputname + Generated by $PROGRAM (GNU $PACKAGE) $VERSION + + The $output program cannot be directly executed until all the libtool + libraries that it depends on are installed. + + This wrapper executable should never be moved out of the build directory. + If it is, it will not operate correctly. +*/ +EOF + cat <<"EOF" +#ifdef _MSC_VER +# define _CRT_SECURE_NO_DEPRECATE 1 +#endif +#include <stdio.h> +#include <stdlib.h> +#ifdef _MSC_VER +# include <direct.h> +# include <process.h> +# include <io.h> +#else +# include <unistd.h> +# include <stdint.h> +# ifdef __CYGWIN__ +# include <io.h> +# endif +#endif +#include <malloc.h> +#include <stdarg.h> +#include <assert.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/stat.h> + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* declarations of non-ANSI functions */ +#if defined __MINGW32__ +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined __CYGWIN__ +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined other_platform || defined ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined _MSC_VER +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +#elif defined __MINGW32__ +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined __CYGWIN__ +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined other platforms ... */ +#endif + +#if defined PATH_MAX +# define LT_PATHMAX PATH_MAX +#elif defined MAXPATHLEN +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free (stale); stale = 0; } \ +} while (0) + +#if defined LT_DEBUGWRAPPER +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <<EOF +#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) +# define externally_visible volatile +#else +# define externally_visible __attribute__((externally_visible)) volatile +#endif +externally_visible const char * MAGIC_EXE = "$magic_exe"; +const char * LIB_PATH_VARNAME = "$shlibpath_var"; +EOF + + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + func_to_host_path "$temp_rpath" + cat <<EOF +const char * LIB_PATH_VALUE = "$func_to_host_path_result"; +EOF + else + cat <<"EOF" +const char * LIB_PATH_VALUE = ""; +EOF + fi + + if test -n "$dllsearchpath"; then + func_to_host_path "$dllsearchpath:" + cat <<EOF +const char * EXE_PATH_VARNAME = "PATH"; +const char * EXE_PATH_VALUE = "$func_to_host_path_result"; +EOF + else + cat <<"EOF" +const char * EXE_PATH_VARNAME = ""; +const char * EXE_PATH_VALUE = ""; +EOF + fi + + if test yes = "$fast_install"; then + cat <<EOF +const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */ +EOF + else + cat <<EOF +const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */ +EOF + fi + + + cat <<"EOF" + +#define LTWRAPPER_OPTION_PREFIX "--lt-" + +static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX; +static const char *dumpscript_opt = LTWRAPPER_OPTION_PREFIX "dump-script"; +static const char *debug_opt = LTWRAPPER_OPTION_PREFIX "debug"; + +int +main (int argc, char *argv[]) +{ + char **newargz; + int newargc; + char *tmp_pathspec; + char *actual_cwrapper_path; + char *actual_cwrapper_name; + char *target_name; + char *lt_argv_zero; + int rval = 127; + + int i; + + program_name = (char *) xstrdup (base_name (argv[0])); + newargz = XMALLOC (char *, (size_t) argc + 1); + + /* very simple arg parsing; don't want to rely on getopt + * also, copy all non cwrapper options to newargz, except + * argz[0], which is handled differently + */ + newargc=0; + for (i = 1; i < argc; i++) + { + if (STREQ (argv[i], dumpscript_opt)) + { +EOF + case $host in + *mingw* | *cygwin* ) + # make stdout use "unix" line endings + echo " setmode(1,_O_BINARY);" + ;; + esac + + cat <<"EOF" + lt_dump_script (stdout); + return 0; + } + if (STREQ (argv[i], debug_opt)) + { + lt_debug = 1; + continue; + } + if (STREQ (argv[i], ltwrapper_option_prefix)) + { + /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX + namespace, but it is not one of the ones we know about and + have already dealt with, above (inluding dump-script), then + report an error. Otherwise, targets might begin to believe + they are allowed to use options in the LTWRAPPER_OPTION_PREFIX + namespace. The first time any user complains about this, we'll + need to make LTWRAPPER_OPTION_PREFIX a configure-time option + or a configure.ac-settable value. + */ + lt_fatal (__FILE__, __LINE__, + "unrecognized %s option: '%s'", + ltwrapper_option_prefix, argv[i]); + } + /* otherwise ... */ + newargz[++newargc] = xstrdup (argv[i]); + } + newargz[++newargc] = NULL; + +EOF + cat <<EOF + /* The GNU banner must be the first non-error debug message */ + lt_debugprintf (__FILE__, __LINE__, "libtool wrapper (GNU $PACKAGE) $VERSION\n"); +EOF + cat <<"EOF" + lt_debugprintf (__FILE__, __LINE__, "(main) argv[0]: %s\n", argv[0]); + lt_debugprintf (__FILE__, __LINE__, "(main) program_name: %s\n", program_name); + + tmp_pathspec = find_executable (argv[0]); + if (tmp_pathspec == NULL) + lt_fatal (__FILE__, __LINE__, "couldn't find %s", argv[0]); + lt_debugprintf (__FILE__, __LINE__, + "(main) found exe (before symlink chase) at: %s\n", + tmp_pathspec); + + actual_cwrapper_path = chase_symlinks (tmp_pathspec); + lt_debugprintf (__FILE__, __LINE__, + "(main) found exe (after symlink chase) at: %s\n", + actual_cwrapper_path); + XFREE (tmp_pathspec); + + actual_cwrapper_name = xstrdup (base_name (actual_cwrapper_path)); + strendzap (actual_cwrapper_path, actual_cwrapper_name); + + /* wrapper name transforms */ + strendzap (actual_cwrapper_name, ".exe"); + tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1); + XFREE (actual_cwrapper_name); + actual_cwrapper_name = tmp_pathspec; + tmp_pathspec = 0; + + /* target_name transforms -- use actual target program name; might have lt- prefix */ + target_name = xstrdup (base_name (TARGET_PROGRAM_NAME)); + strendzap (target_name, ".exe"); + tmp_pathspec = lt_extend_str (target_name, ".exe", 1); + XFREE (target_name); + target_name = tmp_pathspec; + tmp_pathspec = 0; + + lt_debugprintf (__FILE__, __LINE__, + "(main) libtool target name: %s\n", + target_name); +EOF + + cat <<EOF + newargz[0] = + XMALLOC (char, (strlen (actual_cwrapper_path) + + strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1)); + strcpy (newargz[0], actual_cwrapper_path); + strcat (newargz[0], "$objdir"); + strcat (newargz[0], "/"); +EOF + + cat <<"EOF" + /* stop here, and copy so we don't have to do this twice */ + tmp_pathspec = xstrdup (newargz[0]); + + /* do NOT want the lt- prefix here, so use actual_cwrapper_name */ + strcat (newargz[0], actual_cwrapper_name); + + /* DO want the lt- prefix here if it exists, so use target_name */ + lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1); + XFREE (tmp_pathspec); + tmp_pathspec = NULL; +EOF + + case $host_os in + mingw*) + cat <<"EOF" + { + char* p; + while ((p = strchr (newargz[0], '\\')) != NULL) + { + *p = '/'; + } + while ((p = strchr (lt_argv_zero, '\\')) != NULL) + { + *p = '/'; + } + } +EOF + ;; + esac + + cat <<"EOF" + XFREE (target_name); + XFREE (actual_cwrapper_path); + XFREE (actual_cwrapper_name); + + lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */ + lt_setenv ("DUALCASE", "1"); /* for MSK sh */ + /* Update the DLL searchpath. EXE_PATH_VALUE ($dllsearchpath) must + be prepended before (that is, appear after) LIB_PATH_VALUE ($temp_rpath) + because on Windows, both *_VARNAMEs are PATH but uninstalled + libraries must come first. */ + lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE); + lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE); + + lt_debugprintf (__FILE__, __LINE__, "(main) lt_argv_zero: %s\n", + nonnull (lt_argv_zero)); + for (i = 0; i < newargc; i++) + { + lt_debugprintf (__FILE__, __LINE__, "(main) newargz[%d]: %s\n", + i, nonnull (newargz[i])); + } + +EOF + + case $host_os in + mingw*) + cat <<"EOF" + /* execv doesn't actually work on mingw as expected on unix */ + newargz = prepare_spawn (newargz); + rval = (int) _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz); + if (rval == -1) + { + /* failed to start process */ + lt_debugprintf (__FILE__, __LINE__, + "(main) failed to launch target \"%s\": %s\n", + lt_argv_zero, nonnull (strerror (errno))); + return 127; + } + return rval; +EOF + ;; + *) + cat <<"EOF" + execv (lt_argv_zero, newargz); + return rval; /* =127, but avoids unused variable warning */ +EOF + ;; + esac + + cat <<"EOF" +} + +void * +xmalloc (size_t num) +{ + void *p = (void *) malloc (num); + if (!p) + lt_fatal (__FILE__, __LINE__, "memory exhausted"); + + return p; +} + +char * +xstrdup (const char *string) +{ + return string ? strcpy ((char *) xmalloc (strlen (string) + 1), + string) : NULL; +} + +const char * +base_name (const char *name) +{ + const char *base; + +#if defined HAVE_DOS_BASED_FILE_SYSTEM + /* Skip over the disk name in MSDOS pathnames. */ + if (isalpha ((unsigned char) name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + return base; +} + +int +check_executable (const char *path) +{ + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(check_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if ((stat (path, &st) >= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + size_t tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined HAVE_DOS_BASED_FILE_SYSTEM + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined HAVE_DOS_BASED_FILE_SYSTEM + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = (size_t) (q - p); + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (STREQ (str, pat)) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + size_t len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + size_t orig_value_len = strlen (orig_value); + size_t add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[--len] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $debug_cmd + + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $debug_cmd + + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # what system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll that has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + os2dllname= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=false + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module=$wl-single_module + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg=$1 + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir=$arg + prev= + continue + ;; + dlfiles|dlprefiles) + $preload || { + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=: + } + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test no = "$dlself"; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test dlprefiles = "$prev"; then + dlself=yes + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test dlfiles = "$prev"; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols=$arg + test -f "$arg" \ + || func_fatal_error "symbol file '$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex=$arg + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + if test none != "$pic_object"; then + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + fi + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file '$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; + precious_regex) + precious_files_regex=$arg + prev= + continue + ;; + release) + release=-$arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test rpath = "$prev"; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds=$arg + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg=$arg + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "'-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test X-export-symbols = "X$arg"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between '-L' and '$1'" + else + func_fatal_error "need path for '-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test X-lc = "X$arg" || test X-lm = "X$arg"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test X-lc = "X$arg" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test X-lc = "X$arg" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test X-lc = "X$arg" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test X-lc = "X$arg" && continue + ;; + esac + elif test X-lc_r = "X$arg"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -mllvm) + prev=mllvm + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module=$wl-multi_module + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -os2dllname) + prev=os2dllname + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -specs=* GCC specs files + # -stdlib=* select c++ std lib with clang + # -fsanitize=* Clang/GCC memory and address sanitizer + # -fuse-ld=* Linker select flags for GCC + # -static-* direct GCC to link specific libraries statically + # -fcilkplus Cilk Plus language extension features for C/C++ + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ + -specs=*|-fsanitize=*|-fuse-ld=*|-static-*|-fcilkplus) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + fi + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + test none = "$pic_object" || { + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + } + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test dlfiles = "$prev"; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test dlprefiles = "$prev"; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the '$prevarg' option requires an argument" + + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname=$func_basename_result + libobjs_save=$libobjs + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + + func_dirname "$output" "/" "" + output_objdir=$func_dirname_result$objdir + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test lib = "$linkmode"; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=false + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test lib,link = "$linkmode,$pass"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs=$tmp_deplibs + fi + + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs + deplibs= + fi + if test prog = "$linkmode"; then + case $pass in + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; + esac + fi + if test lib,dlpreopen = "$linkmode,$pass"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs=$dlprefiles + fi + if test dlopen = "$pass"; then + # Collect dlpreopened libraries + save_deplibs=$deplibs + deplibs= + fi + + for deplib in $libs; do + lib= + found=false + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test lib = "$linkmode"; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib=$searchdir/lib$name$search_ext + if test -f "$lib"; then + if test .la = "$search_ext"; then + found=: + else + found=false + fi + break 2 + fi + done + done + if $found; then + # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll=$l + done + if test "X$ll" = "X$old_library"; then # only static version available + found=false + func_dirname "$lib" "" "." + ladir=$func_dirname_result + lib=$ladir/$old_library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + *.ltframework) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test conv = "$pass" && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + if test scan = "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "'-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test link = "$pass"; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=false + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=: + fi + ;; + pass_all) + valid_a_lib=: + ;; + esac + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + fi + ;; + esac + continue + ;; + prog) + if test link != "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=: + continue + ;; + esac # case $deplib + + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "'$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir=$func_dirname_result + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test conv = "$pass"; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib=$l + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + + # This library was specified with -dlopen. + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test -z "$dlname" || + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir=$ladir + fi + ;; + esac + func_basename "$lib" + laname=$func_basename_result + + # Find the relevant object directory and library name. + if test yes = "$installed"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir + else + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir + fi + test yes = "$hardcode_automatic" && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir=$ladir + absdir=$abs_ladir + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + fi + case $host in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test lib = "$linkmode"; then + deplibs="$dir/$old_library $deplibs" + elif test prog,link = "$linkmode,$pass"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test prog = "$linkmode" && test link != "$pass"; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if $linkalldeplibs; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test prog,link = "$linkmode,$pass"; then + if test -n "$library_names" && + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + # Make sure the rpath contains only unique directories. + case $temp_rpath: in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test built = "$use_static_libs" && test yes = "$installed"; then + use_static_libs=no + fi + if test -n "$library_names" && + { test no = "$use_static_libs" || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc* | *os2*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test no = "$installed"; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule= + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule=$dlpremoduletest + break + fi + done + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + echo + if test prog = "$linkmode"; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname=$1 + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname=$dlname + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc* | *os2*) + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + esac + eval soname=\"$soname_spec\" + else + soname=$realname + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot=$soname + func_basename "$soroot" + soname=$func_basename_result + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from '$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for '$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test prog = "$linkmode" || test relink != "$opt_mode"; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test no = "$hardcode_direct"; then + add=$dir/$linklib + case $host in + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir=-L$dir ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we cannot + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library"; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add=$dir/$old_library + fi + elif test -n "$old_library"; then + add=$dir/$old_library + fi + fi + esac + elif test no = "$hardcode_minus_L"; then + case $host in + *-*-sunos*) add_shlibpath=$dir ;; + esac + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + relink) + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test yes != "$lib_linked"; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test prog = "$linkmode"; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test prog = "$linkmode" || test relink = "$opt_mode"; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add=-l$name + elif test yes = "$hardcode_automatic"; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib + else + add=$libdir/$linklib + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir=-L$libdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + fi + + if test prog = "$linkmode"; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test prog = "$linkmode"; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test yes = "$build_libtool_libs"; then + # Not a shared library + if test pass_all != "$deplibs_check_method"; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system cannot link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test yes = "$module"; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test lib = "$linkmode"; then + if test -n "$dependency_libs" && + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs=$temp_deplibs + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test no != "$link_all_deplibs"; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path=$deplib ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + path= + fi + fi + ;; + *) + path=-L$absdir/$objdir + ;; + esac + else + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "'$deplib' seems to be moved" + + path=-L$absdir + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test link = "$pass"; then + if test prog = "$linkmode"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test dlopen != "$pass"; then + test conv = "$pass" || { + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + } + + if test prog,link = "$linkmode,$pass"; then + vars="compile_deplibs finalize_deplibs" + else + vars=deplibs + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i= + ;; + esac + if test -n "$i"; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test prog = "$linkmode"; then + dlfiles=$newdlfiles + fi + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "'-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "'-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs=$output + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form 'libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" + + if test no != "$need_lib_prefix"; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" + + install_libdir=$1 + + oldlibs= + if test -z "$rpath"; then + if test yes = "$build_libtool_libs"; then + # Building a libtool convenience library. + # Some compilers have problems with a '.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "'-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs=$IFS; IFS=: + set dummy $vinfo 0 0 0 + shift + IFS=$save_ifs + + test -n "$7" && \ + func_fatal_help "too many parameters to '-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major=$1 + number_minor=$2 + number_revision=$3 + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # that has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|freebsd-elf|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_revision + ;; + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_minor + lt_irix_increment=no + ;; + *) + func_fatal_configuration "$modename: unknown library version type '$version_type'" + ;; + esac + ;; + no) + current=$1 + revision=$2 + age=$3 + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac + ;; + + freebsd-aout) + major=.$current + versuffix=.$current.$revision + ;; + + freebsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + irix | nonstopux) + if test no = "$lt_irix_increment"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring=$verstring_prefix$major.$revision + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test 0 -ne "$loop"; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring_prefix$major.$iface:$verstring + done + + # Before this point, $major must not contain '.'. + major=.$major + versuffix=$major.$revision + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision + + # Add in all the interfaces that we are compatible with. + loop=$age + while test 0 -ne "$loop"; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring:$iface.0 + done + + # Make executables depend on our current version. + func_append verstring ":$current.0" + ;; + + qnx) + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current + ;; + + sunos) + major=.$current + versuffix=.$current.$revision + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 file systems. + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + + *) + func_fatal_configuration "unknown library version type '$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring=0.0 + ;; + esac + if test no = "$need_version"; then + versuffix= + else + versuffix=.0.0 + fi + fi + + # Remove version info from name if versioning should be avoided + if test yes,no = "$avoid_version,$need_version"; then + major= + versuffix= + verstring= + fi + + # Check to see if the archive will have undefined symbols. + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi + fi + else + # Don't allow undefined symbols. + allow_undefined_flag=$no_undefined_flag + fi + + fi + + func_generate_dlsyms "$libname" "$libname" : + func_append libobjs " $symfileobj" + test " " = "$libobjs" && libobjs= + + if test relink != "$opt_mode"; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles=$dlfiles + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles=$dlprefiles + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test yes = "$build_libtool_libs"; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test yes = "$build_libtool_need_lc"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release= + versuffix= + major= + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c <<EOF + int main() { return 0; } +EOF + $opt_dry_run || $RM conftest + if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then + ldd_output=`ldd conftest` + for i in $deplibs; do + case $i in + -l*) + func_stripname -l '' "$i" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $i "*) + func_append newdeplibs " $i" + i= + ;; + esac + fi + if test -n "$i"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + deplib_matches=`eval "\\$ECHO \"$library_names_spec\""` + set dummy $deplib_matches; shift + deplib_match=$1 + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0; then + func_append newdeplibs " $i" + else + droppeddeps=yes + echo + $ECHO "*** Warning: dynamic linker does not accept needed library $i." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which I believe you do not have" + echo "*** because a test_compile did reveal that the linker did not use it for" + echo "*** its dynamic dependency list that programs get resolved with at runtime." + fi + fi + ;; + *) + func_append newdeplibs " $i" + ;; + esac + done + else + # Error occurred in the first compile. Let's try to salvage + # the situation: Compile a separate program for each library. + for i in $deplibs; do + case $i in + -l*) + func_stripname -l '' "$i" + name=$func_stripname_result + $opt_dry_run || $RM conftest + if $LTCC $LTCFLAGS -o conftest conftest.c $i; then + ldd_output=`ldd conftest` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $i "*) + func_append newdeplibs " $i" + i= + ;; + esac + fi + if test -n "$i"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + deplib_matches=`eval "\\$ECHO \"$library_names_spec\""` + set dummy $deplib_matches; shift + deplib_match=$1 + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0; then + func_append newdeplibs " $i" + else + droppeddeps=yes + echo + $ECHO "*** Warning: dynamic linker does not accept needed library $i." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because a test_compile did reveal that the linker did not use this one" + echo "*** as a dynamic dependency that programs can get resolved with at runtime." + fi + fi + else + droppeddeps=yes + echo + $ECHO "*** Warning! Library $i is needed by this library but I was not able to" + echo "*** make it link in! You will probably need to install it or some" + echo "*** library that it depends on before this library will be fully" + echo "*** functional. Installing it before continuing would be even better." + fi + ;; + *) + func_append newdeplibs " $i" + ;; + esac + done + fi + ;; + file_magic*) + set dummy $deplibs_check_method; shift + file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + if test -n "$file_magic_glob"; then + libnameglob=`func_echo_all "$libname" | $SED -e $file_magic_glob` + else + libnameglob=$libname + fi + test yes = "$want_nocaseglob" && nocaseglob=`shopt -p nocaseglob` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + if test yes = "$want_nocaseglob"; then + shopt -s nocaseglob + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib=$potent_lib + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib=$potent_lib # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs= + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test none = "$deplibs_check_method"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test yes = "$droppeddeps"; then + if test yes = "$module"; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test no = "$allow_undefined"; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs=$new_libs + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test yes = "$hardcode_into_libs"; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname=$1 + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname=$realname + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib=$output_objdir/$realname + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + func_dll_def_p "$export_symbols" || { + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols=$export_symbols + export_symbols= + always_export_symbols=yes + } + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs=$IFS; IFS='~' + for cmd1 in $cmds; do + IFS=$save_ifs + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test yes = "$try_normal_branch" \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=$output_objdir/$output_la.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs=$tmp_deplibs + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test yes = "$compiler_needs_object" && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test : != "$skipped_export" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test yes = "$compiler_needs_object"; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-$k.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test -z "$objlist" || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test 1 -eq "$k"; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-$k.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-$k.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + } + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs=$IFS; IFS='~' + for cmd in $concat_cmds; do + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + ${skipped_export-false} && { + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + } + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs=$IFS; IFS='~' + for cmd in $cmds; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test yes = "$module" || test yes = "$export_dynamic"; then + # On all known operating systems, these are identical. + dlname=$soname + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "'-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object '$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj=$output + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + else + gentop=$output_objdir/${obj}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + + # Create the old-style object. + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + + output=$obj + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + test yes = "$build_libtool_libs" || { + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + } + + if test -n "$pic_flag" || test default != "$pic_mode"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output=$libobj + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "'-release' is ignored for programs" + + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test CXX = "$tagname"; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs=$new_libs + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath=$rpath + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath=$rpath + + if test -n "$libobjs" && test yes = "$build_old_libs"; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" false + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=: + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=false + ;; + *cygwin* | *mingw* ) + test yes = "$build_libtool_libs" || wrappers_required=false + ;; + *) + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false + fi + ;; + esac + $wrappers_required || { + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command=$compile_command$compile_rpath + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + fi + + exit $exit_status + } + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test yes = "$no_install"; then + # We don't need to create a wrapper script. + link_command=$compile_var$compile_command$compile_rpath + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host"; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience + build_libtool_libs=no + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) + oldobjs="$old_deplibs $non_pic_objects" + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac + + if test -n "$addlibs"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase=$func_basename_result + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj"; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test -z "$oldobjs"; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test yes = "$build_old_libs" && old_library=$libname.$libext + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test yes = "$hardcode_automatic"; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test yes = "$installed"; then + if test -z "$install_libdir"; then + break + fi + output=$output_objdir/${outputname}i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name=$func_basename_result + func_resolve_sysroot "$deplib" + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs=$newdependency_libs + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles=$newdlprefiles + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles=$newdlprefiles + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test -n "$bindir"; then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result/$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test no,yes = "$installed,$need_relink"; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $debug_cmd + + RM=$nonopt + files= + rmforce=false + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=: ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir + else + odir=$dir/$objdir + fi + func_basename "$file" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir + + # Remember odir for removal later, being careful to avoid duplicates + if test clean = "$opt_mode"; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif $rmforce; then + continue + fi + + rmfiles=$file + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case $opt_mode in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && test none != "$pic_object"; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && test none != "$non_pic_object"; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test clean = "$opt_mode"; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the $objdir's in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi + +test -z "$opt_mode" && { + help=$generic_help + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode '$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# where we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/pigeonhole/m4/dovecot.m4 b/pigeonhole/m4/dovecot.m4 new file mode 100644 index 0000000..037d5e4 --- /dev/null +++ b/pigeonhole/m4/dovecot.m4 @@ -0,0 +1,609 @@ +dnl dovecot.m4 - Check presence of dovecot -*-Autoconf-*- +dnl +dnl Copyright (C) 2010 Dennis Schridde +dnl +dnl This file is free software; the authors give +dnl unlimited permission to copy and/or distribute it, with or without +dnl modifications, as long as this notice is preserved. + +# serial 34 + +dnl +dnl Check for support for D_FORTIFY_SOURCE=2 +dnl + +AC_DEFUN([AC_CC_D_FORTIFY_SOURCE],[ + AC_REQUIRE([gl_UNKNOWN_WARNINGS_ARE_ERRORS]) + AS_IF([test "$enable_hardening" = yes], [ + case "$host" in + *) + gl_COMPILER_OPTION_IF([-O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2], [ + CFLAGS="$CFLAGS -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2" + ], + [], + [AC_LANG_PROGRAM()] + ) + esac + ]) +]) + +dnl * gcc specific options +AC_DEFUN([DC_DOVECOT_CFLAGS],[ + AS_IF([test "x$ac_cv_c_compiler_gnu" = "xyes"], [ + dnl -Wcast-qual -Wcast-align -Wconversion -Wunreachable-code # too many warnings + dnl -Wstrict-prototypes -Wredundant-decls # may give warnings in some systems + dnl -Wmissing-format-attribute -Wmissing-noreturn -Wwrite-strings # a couple of warnings + CFLAGS="$CFLAGS -Wall -W -Wmissing-prototypes -Wmissing-declarations -Wpointer-arith -Wchar-subscripts -Wformat=2 -Wbad-function-cast" + + AS_IF([test "$have_clang" = "yes"], [ + AC_TRY_COMPILE([ + #if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 3) + # error new clang + #endif + ],,,[ + dnl clang 3.3+ unfortunately this gives warnings with hash.h + CFLAGS="$CFLAGS -Wno-duplicate-decl-specifier" + ]) + ], [ + dnl This is simply to avoid warning when building strftime() wrappers.. + CFLAGS="$CFLAGS -fno-builtin-strftime" + ]) + + AC_TRY_COMPILE([ + #if __GNUC__ < 4 + # error old gcc + #endif + ],,[ + dnl gcc4 + CFLAGS="$CFLAGS -Wstrict-aliasing=2" + ]) + + dnl Use std=gnu99 if we have new enough gcc + old_cflags=$CFLAGS + CFLAGS="-std=gnu99" + AC_TRY_COMPILE([ + ],, [ + CFLAGS="$CFLAGS $old_cflags" + ], [ + CFLAGS="$old_cflags" + ]) + + ]) +]) + +AC_DEFUN([AC_LD_WHOLE_ARCHIVE], [ + LD_WHOLE_ARCHIVE= + LD_NO_WHOLE_ARCHIVE= + AC_MSG_CHECKING([for linker option to include whole archive]) + ld_help="`$CC -Wl,-help 2>&1`" + case "$ld_help" in + *"--whole-archive"*) + LD_WHOLE_ARCHIVE="--whole-archive" + LD_NO_WHOLE_ARCHIVE="--no-whole-archive" + ;; + esac + AS_IF([test "x$LD_WHOLE_ARCHIVE" != "x"], + [AC_MSG_RESULT([-Wl,$LD_WHOLE_ARCHIVE])], + [AC_MSG_RESULT([not supported])] + ) + AC_SUBST([LD_WHOLE_ARCHIVE]) + AC_SUBST([LD_NO_WHOLE_ARCHIVE]) + AM_CONDITIONAL([HAVE_WHOLE_ARCHIVE], [test "x$LD_WHOLE_ARCHIVE" != "x"]) +]) + +dnl +dnl Check for -z now and -z relro linker flags +dnl +dnl Copyright (C) 2013 Red Hat, Inc. +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License, or (at your option) any later version. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library. If not, see +dnl <http://www.gnu.org/licenses/>. +dnl + +AC_DEFUN([AC_LD_RELRO],[ + RELRO_LDFLAGS= + AS_IF([test "$enable_hardening" = yes], [ + AC_MSG_CHECKING([for how to force completely read-only GOT table]) + ld_help=`$CC -Wl,-help 2>&1` + case $ld_help in + *"-z relro"*) RELRO_LDFLAGS="-Wl,-z -Wl,relro" ;; + esac + case $ld_help in + *"-z now"*) RELRO_LDFLAGS="$RELRO_LDFLAGS -Wl,-z -Wl,now" ;; + esac + AS_IF([test "x$RELRO_LDFLAGS" != "x"], + [AC_MSG_RESULT([$RELRO_LDFLAGS])], + [AC_MSG_RESULT([unknown])] + ) + ]) + AC_SUBST([RELRO_LDFLAGS]) +]) + +dnl +dnl Check for support for position independent executables +dnl +dnl Copyright (C) 2013 Red Hat, Inc. +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License, or (at your option) any later version. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library. If not, see +dnl <http://www.gnu.org/licenses/>. +dnl + +AC_DEFUN([AC_CC_PIE],[ + AC_REQUIRE([gl_UNKNOWN_WARNINGS_ARE_ERRORS]) + PIE_CFLAGS= + PIE_LDFLAGS= + + AS_IF([test "$enable_hardening" = yes], [ + OLD_CFLAGS=$CFLAGS + case "$host" in + *-*-mingw* | *-*-msvc* | *-*-cygwin* ) + ;; dnl All code is position independent on Win32 target + *) + CFLAGS="-fPIE -DPIE" + gl_COMPILER_OPTION_IF([-pie], [ + PIE_CFLAGS="-fPIE -DPIE" + PIE_LDFLAGS="-pie" + ], [ + dnl some versions of clang require -Wl,-pie instead of -pie + gl_COMPILER_OPTION_IF([[-Wl,-pie]], [ + PIE_CFLAGS="-fPIE -DPIE" + PIE_LDFLAGS="-Wl,-pie" + ], [AC_MSG_RESULT([not supported])], + [AC_LANG_PROGRAM()] + ) + ], + [AC_LANG_PROGRAM()] + ) + esac + CFLAGS=$OLD_CFLAGS + ]) + AC_SUBST([PIE_CFLAGS]) + AC_SUBST([PIE_LDFLAGS]) +]) + +dnl +dnl Check for support for Retpoline +dnl + +AC_DEFUN([AC_CC_RETPOLINE],[ + AC_ARG_WITH(retpoline, + AS_HELP_STRING([--with-retpoline=<choice>], [Retpoline mitigation choice (default: keep)]), + with_retpoline=$withval, + with_retpoline=keep) + + AC_REQUIRE([gl_UNKNOWN_WARNINGS_ARE_ERRORS]) + AS_IF([test "$enable_hardening" = yes], [ + case "$host" in + *) + gl_COMPILER_OPTION_IF([-mfunction-return=$with_retpoline], + [CFLAGS="$CFLAGS -mfunction-return=$with_retpoline"], + [], + [AC_LANG_PROGRAM()] + ) + gl_COMPILER_OPTION_IF([-mindirect-branch=$with_retpoline], [ + CFLAGS="$CFLAGS -mindirect-branch=$with_retpoline" + ], + [], + [AC_LANG_PROGRAM()] + ) + esac + ]) +]) + +dnl +dnl Check for support for -fstack-protector or -strong +dnl + +AC_DEFUN([AC_CC_F_STACK_PROTECTOR],[ + AC_REQUIRE([gl_UNKNOWN_WARNINGS_ARE_ERRORS]) + AS_IF([test "$enable_hardening" = yes], [ + case "$host" in + *) + gl_COMPILER_OPTION_IF([-fstack-protector-strong], [ + CFLAGS="$CFLAGS -fstack-protector-strong" + ], + [ + gl_COMPILER_OPTION_IF([-fstack-protector], [ + CFLAGS="$CFLAGS -fstack-protector" + ], [], [AC_LANG_PROGRAM()]) + ], + [AC_LANG_PROGRAM()] + ) + esac + ]) +]) + +AC_DEFUN([DC_DOVECOT_MODULEDIR],[ + AC_ARG_WITH(moduledir, + [ --with-moduledir=DIR Base directory for dynamically loadable modules], + [moduledir="$withval"], + [moduledir="$dovecot_moduledir"] + ) + AC_SUBST(moduledir) +]) + +AC_DEFUN([DC_PLUGIN_DEPS],[ + _plugin_deps=yes + AC_MSG_CHECKING([whether OS supports plugin dependencies]) + case "$host_os" in + darwin*) + dnl OSX loads the plugins twice, which breaks stuff + _plugin_deps=no + ;; + esac + AC_MSG_RESULT([$_plugin_deps]) + AM_CONDITIONAL([DOVECOT_PLUGIN_DEPS], [test "x$_plugin_deps" = "xyes"]) + unset _plugin_deps +]) + +AC_DEFUN([DC_DOVECOT_TEST_WRAPPER],[ + AC_ARG_VAR([VALGRIND], [Path to valgrind]) + AC_PATH_PROG(VALGRIND, valgrind, reject) + AS_IF([test "$VALGRIND" != reject], [ + cat > run-test.sh <<_DC_EOF +#!/bin/sh +top_srcdir=\$[1] +shift + +if test "\$NOUNDEF" != ""; then + noundef="--undef-value-errors=no" +else + noundef="" +fi + +if test "\$NOCHILDREN" != ""; then + trace_children="--trace-children=no" +else + trace_children="--trace-children=yes" +fi + +skip_path="\$top_srcdir/run-test-valgrind.exclude" +if test -r "\$skip_path" && grep -w -q "\$(basename \$[1])" "\$skip_path"; then + NOVALGRIND=true +fi + +if test "\$NOVALGRIND" != ""; then + \$[*] + ret=\$? +else + test_out="test.out~\$\$" + trap "rm -f \$test_out" 0 1 2 3 15 + supp_path="\$top_srcdir/run-test-valgrind.supp" + if test -r "\$supp_path"; then + $VALGRIND -q \$trace_children --error-exitcode=213 --leak-check=full --gen-suppressions=all --suppressions="\$supp_path" --log-file=\$test_out \$noundef \$[*] + else + $VALGRIND -q \$trace_children --error-exitcode=213 --leak-check=full --gen-suppressions=all --log-file=\$test_out \$noundef \$[*] + fi + ret=\$? + if test -s \$test_out; then + cat \$test_out + ret=1 + fi +fi +if test \$ret != 0; then + echo "Failed to run: \$[*]" >&2 +fi +exit \$ret +_DC_EOF + RUN_TEST='$(LIBTOOL) execute $(SHELL) $(top_builddir)/run-test.sh $(top_srcdir)' + ], [ + RUN_TEST='' + ]) + AC_SUBST(RUN_TEST) +]) + +dnl Substitute every var in the given comma separated list +AC_DEFUN([AX_SUBST_L],[ + m4_foreach([__var__], [$@], [AC_SUBST(__var__)]) +]) + +AC_DEFUN([DC_DOVECOT_HARDENING],[ + AC_ARG_ENABLE(hardening, + AS_HELP_STRING([--enable-hardening=yes], [Enable various hardenings (default: yes)]), + enable_hardening=$enableval, + enable_hardening=yes) + + AC_MSG_CHECKING([Whether to enable hardening]) + AC_MSG_RESULT([$enable_hardening]) + + AC_CC_PIE + AC_CC_F_STACK_PROTECTOR + AC_CC_D_FORTIFY_SOURCE + AC_CC_RETPOLINE + AC_LD_RELRO + DOVECOT_WANT_UBSAN +]) + +AC_DEFUN([DC_DOVECOT_FUZZER],[ + AC_ARG_WITH(fuzzer, + AS_HELP_STRING([--with-fuzzer=clang], [Build with clang fuzzer (default: no)]), + with_fuzzer=$withval, + with_fuzzer=no) + AS_IF([test x$with_fuzzer = xclang], [ + CFLAGS="$CFLAGS -fsanitize=fuzzer-no-link" + # use $LIB_FUZZING_ENGINE for linking if it exists + FUZZER_LDFLAGS=${LIB_FUZZING_ENGINE--fsanitize=fuzzer} + # May need to use CXXLINK for linking, which wants sources to + # be compiled with -fPIE + FUZZER_CPPFLAGS='$(AM_CPPFLAGS) -fPIE -DPIE' + ], [test x$with_fuzzer != xno], [ + AC_MSG_ERROR([Unknown fuzzer $with_fuzzer]) + ]) + AC_SUBST([FUZZER_CPPFLAGS]) + AC_SUBST([FUZZER_LDFLAGS]) + AM_CONDITIONAL([USE_FUZZER], [test "x$with_fuzzer" != "xno"]) + +]) + +AC_DEFUN([DC_DOVECOT],[ + AC_ARG_WITH(dovecot, + [ --with-dovecot=DIR Dovecot base directory], + [ dovecotdir="$withval" ], [ + dc_prefix=$prefix + test "x$dc_prefix" = xNONE && dc_prefix=$ac_default_prefix + dovecotdir="$dc_prefix/lib/dovecot" + ] + ) + + AC_ARG_WITH(dovecot-install-dirs, + [AC_HELP_STRING([--with-dovecot-install-dirs], + [Use install directories configured for Dovecot (default)])], + AS_IF([test x$withval = xno], [ + use_install_dirs=no + ], [ + use_install_dirs=yes + ]), + use_install_dirs=yes) + + AC_MSG_CHECKING([for "$dovecotdir/dovecot-config"]) + AS_IF([test -f "$dovecotdir/dovecot-config"], [ + AC_MSG_RESULT([$dovecotdir/dovecot-config]) + ], [ + AC_MSG_RESULT([not found]) + AC_MSG_NOTICE([]) + AC_MSG_NOTICE([Use --with-dovecot=DIR to provide the path to the dovecot-config file.]) + AC_MSG_ERROR([dovecot-config not found]) + ]) + + old=`pwd` + cd $dovecotdir + abs_dovecotdir=`pwd` + cd $old + DISTCHECK_CONFIGURE_FLAGS="--with-dovecot=$abs_dovecotdir --without-dovecot-install-dirs" + + dnl Make sure dovecot-config doesn't accidentically override flags + ORIG_CFLAGS="$CFLAGS" + ORIG_LDFLAGS="$LDFLAGS" + ORIG_BINARY_CFLAGS="$BINARY_CFLAGS" + ORIG_BINARY_LDFLAGS="$BINARY_LDFLAGS" + + eval `grep -i '^dovecot_[[a-z_]]*=' "$dovecotdir"/dovecot-config` + eval `grep '^LIBDOVECOT[[A-Z0-9_]]*=' "$dovecotdir"/dovecot-config` + + CFLAGS="$ORIG_CFLAGS" + LDFLAGS="$ORIG_LDFLAGS" + BINARY_CFLAGS="$ORIG_BINARY_CFLAGS" + BINARY_LDFLAGS="$ORIG_BINARY_LDFLAGS" + + dovecot_installed_moduledir="$dovecot_moduledir" + + AS_IF([test "$use_install_dirs" = "no"], [ + dnl the main purpose of these is to fix make distcheck for plugins + dnl other than that, they don't really make much sense + dovecot_pkgincludedir='$(pkgincludedir)' + dovecot_pkglibdir='$(pkglibdir)' + dovecot_pkglibexecdir='$(libexecdir)/dovecot' + dovecot_docdir='$(docdir)' + dovecot_moduledir='$(moduledir)' + dovecot_statedir='$(statedir)' + ]) + + CC_CLANG + DC_DOVECOT_CFLAGS + DC_DOVECOT_HARDENING + + AX_SUBST_L([DISTCHECK_CONFIGURE_FLAGS], [dovecotdir], [dovecot_moduledir], [dovecot_installed_moduledir], [dovecot_pkgincludedir], [dovecot_pkglibexecdir], [dovecot_pkglibdir], [dovecot_docdir], [dovecot_statedir]) + AX_SUBST_L([DOVECOT_INSTALLED], [DOVECOT_CFLAGS], [DOVECOT_LIBS], [DOVECOT_SSL_LIBS], [DOVECOT_SQL_LIBS], [DOVECOT_COMPRESS_LIBS], [DOVECOT_BINARY_CFLAGS], [DOVECOT_BINARY_LDFLAGS]) + AX_SUBST_L([LIBDOVECOT], [LIBDOVECOT_LOGIN], [LIBDOVECOT_SQL], [LIBDOVECOT_SSL], [LIBDOVECOT_COMPRESS], [LIBDOVECOT_LDA], [LIBDOVECOT_STORAGE], [LIBDOVECOT_DSYNC], [LIBDOVECOT_LIBFTS]) + AX_SUBST_L([LIBDOVECOT_DEPS], [LIBDOVECOT_LOGIN_DEPS], [LIBDOVECOT_SQL_DEPS], [LIBDOVECOT_SSL_DEPS], [LIBDOVECOT_COMPRESS_DEPS], [LIBDOVECOT_LDA_DEPS], [LIBDOVECOT_STORAGE_DEPS], [LIBDOVECOT_DSYNC_DEPS], [LIBDOVECOT_LIBFTS_DEPS]) + AX_SUBST_L([LIBDOVECOT_INCLUDE], [LIBDOVECOT_LDA_INCLUDE], [LIBDOVECOT_AUTH_INCLUDE], [LIBDOVECOT_DOVEADM_INCLUDE], [LIBDOVECOT_SERVICE_INCLUDE], [LIBDOVECOT_STORAGE_INCLUDE], [LIBDOVECOT_LOGIN_INCLUDE], [LIBDOVECOT_SQL_INCLUDE]) + AX_SUBST_L([LIBDOVECOT_IMAP_LOGIN_INCLUDE], [LIBDOVECOT_CONFIG_INCLUDE], [LIBDOVECOT_IMAP_INCLUDE], [LIBDOVECOT_POP3_INCLUDE], [LIBDOVECOT_SUBMISSION_INCLUDE], [LIBDOVECOT_LMTP_INCLUDE], [LIBDOVECOT_DSYNC_INCLUDE], [LIBDOVECOT_IMAPC_INCLUDE], [LIBDOVECOT_FTS_INCLUDE]) + AX_SUBST_L([LIBDOVECOT_NOTIFY_INCLUDE], [LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE], [LIBDOVECOT_ACL_INCLUDE], [LIBDOVECOT_LIBFTS_INCLUDE], [LIBDOVECOT_LUA_INCLUDE]) + AX_SUBST_L([DOVECOT_LUA_LIBS], [DOVECOT_LUA_CFLAGS], [LIBDOVECOT_LUA], [LIBDOVECOT_LUA_DEPS]) + + AM_CONDITIONAL(DOVECOT_INSTALLED, test "$DOVECOT_INSTALLED" = "yes") + + DC_PLUGIN_DEPS + DC_DOVECOT_TEST_WRAPPER +]) + +AC_DEFUN([DC_CC_WRAPPER],[ + AS_IF([test "$want_shared_libs" != "yes"], [ + dnl want_shared_libs=no is for internal use. the liblib.la check is for plugins + AS_IF([test "$want_shared_libs" = "no" || echo "$LIBDOVECOT" | grep "/liblib.la" > /dev/null], [ + AS_IF([test "$with_gnu_ld" = yes], [ + dnl libtool can't handle using whole-archive flags, so we need to do this + dnl with a CC wrapper.. shouldn't be much of a problem, since most people + dnl are building with shared libs. + cat > cc-wrapper.sh <<_DC_EOF +#!/bin/sh + +if echo "\$[*]" | grep -- -ldl > /dev/null; then + # the binary uses plugins. make sure we include everything from .a libs + exec $CC -Wl,--whole-archive \$[*] -Wl,--no-whole-archive +else + exec $CC \$[*] +fi +_DC_EOF + chmod +x cc-wrapper.sh + CC=`pwd`/cc-wrapper.sh + ]) + ]) + ]) +]) + +AC_DEFUN([DC_PANDOC], [ + AC_ARG_VAR(PANDOC, [Path to pandoc program]) + + dnl Optional tool for making documentation + AC_CHECK_PROGS(PANDOC, [pandoc], [true]) + + AS_IF([test "$PANDOC" = "true"], [ + AS_IF([test ! -e README], [ + AC_MSG_ERROR([Cannot produce documentation without pandoc - disable with PANDOC=false ./configure]) + ]) + ]) +]) +# warnings.m4 serial 11 +dnl Copyright (C) 2008-2015 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Simon Josefsson + +# gl_AS_VAR_APPEND(VAR, VALUE) +# ---------------------------- +# Provide the functionality of AS_VAR_APPEND if Autoconf does not have it. +m4_ifdef([AS_VAR_APPEND], +[m4_copy([AS_VAR_APPEND], [gl_AS_VAR_APPEND])], +[m4_define([gl_AS_VAR_APPEND], +[AS_VAR_SET([$1], [AS_VAR_GET([$1])$2])])]) + + +# gl_COMPILER_OPTION_IF(OPTION, [IF-SUPPORTED], [IF-NOT-SUPPORTED], +# [PROGRAM = AC_LANG_PROGRAM()]) +# ----------------------------------------------------------------- +# Check if the compiler supports OPTION when compiling PROGRAM. +# +# FIXME: gl_Warn must be used unquoted until we can assume Autoconf +# 2.64 or newer. +AC_DEFUN([gl_COMPILER_OPTION_IF], +[AS_VAR_PUSHDEF([gl_Warn], [gl_cv_warn_[]_AC_LANG_ABBREV[]_$1])dnl +AS_VAR_PUSHDEF([gl_Flags], [_AC_LANG_PREFIX[]FLAGS])dnl +AS_LITERAL_IF([$1], + [m4_pushdef([gl_Positive], m4_bpatsubst([$1], [^-Wno-], [-W]))], + [gl_positive="$1" +case $gl_positive in + -Wno-*) gl_positive=-W`expr "X$gl_positive" : 'X-Wno-\(.*\)'` ;; +esac +m4_pushdef([gl_Positive], [$gl_positive])])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler handles $1], m4_defn([gl_Warn]), [ + gl_save_compiler_FLAGS="$gl_Flags" + gl_AS_VAR_APPEND(m4_defn([gl_Flags]), + [" $gl_unknown_warnings_are_errors ]m4_defn([gl_Positive])["]) + AC_LINK_IFELSE([m4_default([$4], [AC_LANG_PROGRAM([])])], + [AS_VAR_SET(gl_Warn, [yes])], + [AS_VAR_SET(gl_Warn, [no])]) + gl_Flags="$gl_save_compiler_FLAGS" +]) +AS_VAR_IF(gl_Warn, [yes], [$2], [$3]) +m4_popdef([gl_Positive])dnl +AS_VAR_POPDEF([gl_Flags])dnl +AS_VAR_POPDEF([gl_Warn])dnl +]) + +# gl_UNKNOWN_WARNINGS_ARE_ERRORS +# ------------------------------ +# Clang doesn't complain about unknown warning options unless one also +# specifies -Wunknown-warning-option -Werror. Detect this. +AC_DEFUN([gl_UNKNOWN_WARNINGS_ARE_ERRORS], +[gl_COMPILER_OPTION_IF([-Werror -Wunknown-warning-option], + [gl_unknown_warnings_are_errors='-Wunknown-warning-option -Werror'], + [gl_unknown_warnings_are_errors=])]) + +# gl_WARN_ADD(OPTION, [VARIABLE = WARN_CFLAGS], +# [PROGRAM = AC_LANG_PROGRAM()]) +# --------------------------------------------- +# Adds parameter to WARN_CFLAGS if the compiler supports it when +# compiling PROGRAM. For example, gl_WARN_ADD([-Wparentheses]). +# +# If VARIABLE is a variable name, AC_SUBST it. +AC_DEFUN([gl_WARN_ADD], +[AC_REQUIRE([gl_UNKNOWN_WARNINGS_ARE_ERRORS]) +gl_COMPILER_OPTION_IF([$1], + [gl_AS_VAR_APPEND(m4_if([$2], [], [[WARN_CFLAGS]], [[$2]]), [" $1"])], + [], + [$3]) +m4_ifval([$2], + [AS_LITERAL_IF([$2], [AC_SUBST([$2])])], + [AC_SUBST([WARN_CFLAGS])])dnl +]) + +# Local Variables: +# mode: autoconf +# End: +dnl * clang check +AC_DEFUN([CC_CLANG],[ + AC_MSG_CHECKING([whether $CC is clang 3.3+]) + AS_IF([$CC -dM -E -x c /dev/null | grep __clang__ > /dev/null 2>&1], [ + AS_VAR_SET([have_clang], [yes]) + ], [ + AS_VAR_SET([have_clang], [no]) + ]) + AC_MSG_RESULT([$have_clang]) +]) + +AC_DEFUN([DOVECOT_WANT_UBSAN], [ + AC_ARG_ENABLE(ubsan, + AS_HELP_STRING([--enable-ubsan], [Enable undefined behaviour sanitizes (default=no)]), + [want_ubsan=yes], [want_ubsan=no]) + AC_MSG_CHECKING([whether we want undefined behaviour sanitizer]) + AC_MSG_RESULT([$want_ubsan]) + AS_IF([test x$want_ubsan = xyes], [ + san_flags="" + gl_COMPILER_OPTION_IF([-fsanitize=undefined], [ + san_flags="$san_flags -fsanitize=undefined" + AC_DEFINE([HAVE_FSANITIZE_UNDEFINED], [1], [Define if your compiler has -fsanitize=undefined]) + ]) + gl_COMPILER_OPTION_IF([-fno-sanitize=nonnull-attribute], [ + san_flags="$san_flags -fno-sanitize=nonnull-attribute" + AC_DEFINE([HAVE_FNO_SANITIZE_NONNULL_ATTRIBUTE], [1], [Define if your compiler has -fno-sanitize=nonnull-attribute]) + ]) + gl_COMPILER_OPTION_IF([-fsanitize=implicit-integer-truncation], [ + san_flags="$san_flags -fsanitize=implicit-integer-truncation" + AC_DEFINE([HAVE_FSANITIZE_IMPLICIT_INTEGER_TRUNCATION], [1], [Define if your compiler has -fsanitize=implicit-integer-truncation]) + ]) + gl_COMPILER_OPTION_IF([-fsanitize=local-bounds], [ + san_flags="$san_flags -fsanitize=local-bounds" + AC_DEFINE([HAVE_FSANITIZE_LOCAL_BOUNDS], [1], [Define if your compiler has -fsanitize=local-bounds]) + ]) + gl_COMPILER_OPTION_IF([-fsanitize=integer], [ + san_flags="$san_flags -fsanitize=integer" + AC_DEFINE([HAVE_FSANITIZE_INTEGER], [1], [Define if your compiler has -fsanitize=integer]) + ]) + gl_COMPILER_OPTION_IF([-fsanitize=nullability], [ + san_flags="$san_flags -fsanitize=nullability" + AC_DEFINE([HAVE_FSANITIZE_NULLABILITY], [1], [Define if your compiler has -fsanitize=nullability]) + ]) + AS_IF([test "$san_flags" != "" ], [ + EXTRA_CFLAGS="$EXTRA_CFLAGS $san_flags -U_FORTIFY_SOURCE -g -ggdb3 -O0 -fno-omit-frame-pointer" + AC_DEFINE([HAVE_UNDEFINED_SANITIZER], [1], [Define if your compiler supports undefined sanitizers]) + ], [ + AC_MSG_ERROR([No undefined sanitizer support in your compiler]) + ]) + san_flags="" + ]) +]) diff --git a/pigeonhole/m4/libtool.m4 b/pigeonhole/m4/libtool.m4 new file mode 100644 index 0000000..c4c0294 --- /dev/null +++ b/pigeonhole/m4/libtool.m4 @@ -0,0 +1,8394 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +]) + +# serial 58 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + +# _LT_CC_BASENAME(CC) +# ------------------- +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. +m4_defun([_LT_CC_BASENAME], +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from 'configure', and 'config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain=$ac_aux_dir/ltmain.sh +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the 'libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# <var>='`$ECHO "$<var>" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags='_LT_TAGS'dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# '#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test 0 = "$lt_write_fail" && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +'$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to <bug-libtool@gnu.org>." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test 0 != $[#] +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try '$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try '$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test yes = "$silent" && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +_LT_COPYING +_LT_LIBTOOL_TAGS + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS=$save_LDFLAGS + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cr libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cr libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[912]]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[[012]][[,.]]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*|11.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + m4_if([$1], [CXX], +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case $ECHO in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([$with_sysroot]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and where our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cr} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test yes = "[$]$2"; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS +]) + +if test yes = "[$]$2"; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n "$lt_cv_sys_max_cmd_len"; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes = "$cross_compiling"; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen=shl_load], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen=dlopen], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then + + # We can hardcode non-existent directories. + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib<name>.so + # instead of lib<name>.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program that can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac]) +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program that can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test no = "$withval" || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in + *GNU* | *'with BFD'*) + test no != "$with_gnu_ld" && break + ;; + *) + test yes != "$with_gnu_ld" && break + ;; + esac + fi + done + IFS=$lt_save_ifs +else + lt_cv_path_LD=$LD # Let the user override the test with a path. +fi]) +LD=$lt_cv_path_LD +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +_LT_PATH_LD_GNU +AC_SUBST([LD]) + +_LT_TAGDECL([], [LD], [1], [The linker used to build libraries]) +])# LT_PATH_LD + +# Old names: +AU_ALIAS([AM_PROG_LD], [LT_PATH_LD]) +AU_ALIAS([AC_PROG_LD], [LT_PATH_LD]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_LD], []) +dnl AC_DEFUN([AC_PROG_LD], []) + + +# _LT_PATH_LD_GNU +#- -------------- +m4_defun([_LT_PATH_LD_GNU], +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) + lt_cv_prog_gnu_ld=yes + ;; +*) + lt_cv_prog_gnu_ld=no + ;; +esac]) +with_gnu_ld=$lt_cv_prog_gnu_ld +])# _LT_PATH_LD_GNU + + +# _LT_CMD_RELOAD +# -------------- +# find reload flag for linker +# -- PORTME Some linkers may need a different reload flag. +m4_defun([_LT_CMD_RELOAD], +[AC_CACHE_CHECK([for $LD option to reload object files], + lt_cv_ld_reload_flag, + [lt_cv_ld_reload_flag='-r']) +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test yes != "$GCC"; then + reload_cmds=false + fi + ;; + darwin*) + if test yes = "$GCC"; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac +_LT_TAGDECL([], [reload_flag], [1], [How to create reloadable object files])dnl +_LT_TAGDECL([], [reload_cmds], [2])dnl +])# _LT_CMD_RELOAD + + +# _LT_PATH_DD +# ----------- +# find a working dd +m4_defun([_LT_PATH_DD], +[AC_CACHE_CHECK([for a working dd], [ac_cv_path_lt_DD], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + +# _LT_CHECK_MAGIC_METHOD +# ---------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_MAGIC_METHOD], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +AC_CACHE_CHECK([how to recognize dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[[4-9]]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[[45]]*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi]) +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM=-lm) + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD + if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test yes = "$GCC"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # flang / f18. f95 an alias for gfortran or flang on Debian + flang* | f18* | f95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + _LT_TAGVAR(link_all_deplibs, $1)=no + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + osf3*) + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting $shlibpath_var if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC=$CC +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report what library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC=$lt_save_CC +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)=$prev$p + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)=$p + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)=$p + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test no = "$F77"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_F77"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test no = "$FC"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_FC"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_FC" + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code=$lt_simple_compile_test_code + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f "$lt_ac_sed" && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test 10 -lt "$lt_ac_count" && break + lt_ac_count=`expr $lt_ac_count + 1` + if test "$lt_ac_count" -gt "$lt_ac_max"; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine what file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/pigeonhole/m4/ltoptions.m4 b/pigeonhole/m4/ltoptions.m4 new file mode 100644 index 0000000..94b0829 --- /dev/null +++ b/pigeonhole/m4/ltoptions.m4 @@ -0,0 +1,437 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 8 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option '$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' +# LT_INIT options. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [pic_mode=m4_default([$1], [default])]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/pigeonhole/m4/ltsugar.m4 b/pigeonhole/m4/ltsugar.m4 new file mode 100644 index 0000000..48bc934 --- /dev/null +++ b/pigeonhole/m4/ltsugar.m4 @@ -0,0 +1,124 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59, which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/pigeonhole/m4/ltversion.m4 b/pigeonhole/m4/ltversion.m4 new file mode 100644 index 0000000..fa04b52 --- /dev/null +++ b/pigeonhole/m4/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 4179 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.6]) +m4_define([LT_PACKAGE_REVISION], [2.4.6]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.6' +macro_revision='2.4.6' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/pigeonhole/m4/lt~obsolete.m4 b/pigeonhole/m4/lt~obsolete.m4 new file mode 100644 index 0000000..c6b26f8 --- /dev/null +++ b/pigeonhole/m4/lt~obsolete.m4 @@ -0,0 +1,99 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/pigeonhole/missing b/pigeonhole/missing new file mode 100755 index 0000000..8d0eaad --- /dev/null +++ b/pigeonhole/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2018-03-07.03; # UTC + +# Copyright (C) 1996-2020 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to <bug-automake@gnu.org>." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=https://www.perl.org/ +flex_URL=https://github.com/westes/flex +gnu_software_URL=https://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/pigeonhole/pigeonhole-config.h.in b/pigeonhole/pigeonhole-config.h.in new file mode 100644 index 0000000..60b0ff9 --- /dev/null +++ b/pigeonhole/pigeonhole-config.h.in @@ -0,0 +1,15 @@ + +/* Define to the full name of Pigeonhole for Dovecot. */ +#undef PIGEONHOLE_NAME + +/* Define to the version of Pigeonhole for Dovecot. */ +#undef PIGEONHOLE_VERSION + +/* Pigeonhole ABI version */ +#undef PIGEONHOLE_ABI_VERSION + +/* Define to build unfinished features/extensions. */ +#undef HAVE_SIEVE_UNFINISHED + +/* LDAP support is built in */ +#undef SIEVE_BUILTIN_LDAP diff --git a/pigeonhole/pigeonhole-version.h b/pigeonhole/pigeonhole-version.h new file mode 100644 index 0000000..8ef02ff --- /dev/null +++ b/pigeonhole/pigeonhole-version.h @@ -0,0 +1,6 @@ +#ifndef PIGEONHOLE_VERSION_H +#define PIGEONHOLE_VERSION_H + +#define PIGEONHOLE_VERSION_FULL PIGEONHOLE_VERSION" (f6cd4b8e)" + +#endif /* PIGEONHOLE_VERSION_H */ diff --git a/pigeonhole/src/Makefile.am b/pigeonhole/src/Makefile.am new file mode 100644 index 0000000..85c1e44 --- /dev/null +++ b/pigeonhole/src/Makefile.am @@ -0,0 +1,21 @@ + + +sieve_subdirs = \ + lib-sieve \ + plugins \ + lib-sieve-tool \ + sieve-tools \ + testsuite + +if BUILD_MANAGESIEVE +managesieve_subdirs = \ + lib-managesieve \ + managesieve \ + managesieve-login +else +managesieve_subdirs = +endif + +SUBDIRS = \ + $(sieve_subdirs) \ + $(managesieve_subdirs) diff --git a/pigeonhole/src/Makefile.in b/pigeonhole/src/Makefile.in new file mode 100644 index 0000000..4b09bcb --- /dev/null +++ b/pigeonhole/src/Makefile.in @@ -0,0 +1,709 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = lib-sieve plugins lib-sieve-tool sieve-tools testsuite \ + lib-managesieve managesieve managesieve-login +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +sieve_subdirs = \ + lib-sieve \ + plugins \ + lib-sieve-tool \ + sieve-tools \ + testsuite + +@BUILD_MANAGESIEVE_FALSE@managesieve_subdirs = +@BUILD_MANAGESIEVE_TRUE@managesieve_subdirs = \ +@BUILD_MANAGESIEVE_TRUE@ lib-managesieve \ +@BUILD_MANAGESIEVE_TRUE@ managesieve \ +@BUILD_MANAGESIEVE_TRUE@ managesieve-login + +SUBDIRS = \ + $(sieve_subdirs) \ + $(managesieve_subdirs) + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-managesieve/Makefile.am b/pigeonhole/src/lib-managesieve/Makefile.am new file mode 100644 index 0000000..b036680 --- /dev/null +++ b/pigeonhole/src/lib-managesieve/Makefile.am @@ -0,0 +1,15 @@ +noinst_LTLIBRARIES = libmanagesieve.la + +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + -I$(top_srcdir) + +libmanagesieve_la_SOURCES = \ + managesieve-arg.c \ + managesieve-quote.c \ + managesieve-parser.c + +noinst_HEADERS = \ + managesieve-arg.h \ + managesieve-quote.h \ + managesieve-parser.h diff --git a/pigeonhole/src/lib-managesieve/Makefile.in b/pigeonhole/src/lib-managesieve/Makefile.in new file mode 100644 index 0000000..c52cc11 --- /dev/null +++ b/pigeonhole/src/lib-managesieve/Makefile.in @@ -0,0 +1,691 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-managesieve +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libmanagesieve_la_LIBADD = +am_libmanagesieve_la_OBJECTS = managesieve-arg.lo managesieve-quote.lo \ + managesieve-parser.lo +libmanagesieve_la_OBJECTS = $(am_libmanagesieve_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/managesieve-arg.Plo \ + ./$(DEPDIR)/managesieve-parser.Plo \ + ./$(DEPDIR)/managesieve-quote.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libmanagesieve_la_SOURCES) +DIST_SOURCES = $(libmanagesieve_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libmanagesieve.la +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + -I$(top_srcdir) + +libmanagesieve_la_SOURCES = \ + managesieve-arg.c \ + managesieve-quote.c \ + managesieve-parser.c + +noinst_HEADERS = \ + managesieve-arg.h \ + managesieve-quote.h \ + managesieve-parser.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-managesieve/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-managesieve/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libmanagesieve.la: $(libmanagesieve_la_OBJECTS) $(libmanagesieve_la_DEPENDENCIES) $(EXTRA_libmanagesieve_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libmanagesieve_la_OBJECTS) $(libmanagesieve_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-arg.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-parser.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-quote.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/managesieve-arg.Plo + -rm -f ./$(DEPDIR)/managesieve-parser.Plo + -rm -f ./$(DEPDIR)/managesieve-quote.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/managesieve-arg.Plo + -rm -f ./$(DEPDIR)/managesieve-parser.Plo + -rm -f ./$(DEPDIR)/managesieve-quote.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-managesieve/managesieve-arg.c b/pigeonhole/src/lib-managesieve/managesieve-arg.c new file mode 100644 index 0000000..178bf45 --- /dev/null +++ b/pigeonhole/src/lib-managesieve/managesieve-arg.c @@ -0,0 +1,207 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "strescape.h" +#include "managesieve-arg.h" + +bool managesieve_arg_get_atom(const struct managesieve_arg *arg, + const char **str_r) +{ + if (arg->type != MANAGESIEVE_ARG_ATOM) + return FALSE; + + *str_r = arg->_data.str; + return TRUE; +} + +bool managesieve_arg_get_number(const struct managesieve_arg *arg, + uoff_t *number_r) +{ + const char *data; + uoff_t num = 0; + size_t i; + + if (arg->type != MANAGESIEVE_ARG_ATOM) + return FALSE; + + data = arg->_data.str; + for (i = 0; i < arg->str_len; i++) { + uoff_t newnum; + + if (data[i] < '0' || data[i] > '9') + return FALSE; + + newnum = num*10 + (data[i] -'0'); + if (newnum < num) + return FALSE; + + num = newnum; + } + + *number_r = num; + return TRUE; +} + +bool managesieve_arg_get_quoted(const struct managesieve_arg *arg, + const char **str_r) +{ + if (arg->type != MANAGESIEVE_ARG_STRING) + return FALSE; + + *str_r = arg->_data.str; + return TRUE; +} + +bool managesieve_arg_get_string(const struct managesieve_arg *arg, + const char **str_r) +{ + if (arg->type != MANAGESIEVE_ARG_STRING && + arg->type != MANAGESIEVE_ARG_LITERAL) + return FALSE; + + *str_r = arg->_data.str; + return TRUE; +} + +bool managesieve_arg_get_string_stream(const struct managesieve_arg *arg, + struct istream **stream_r) +{ + if (arg->type != MANAGESIEVE_ARG_STRING_STREAM) + return FALSE; + + *stream_r = arg->_data.str_stream; + return TRUE; +} + +bool managesieve_arg_get_list(const struct managesieve_arg *arg, + const struct managesieve_arg **list_r) +{ + unsigned int count; + + return managesieve_arg_get_list_full(arg, list_r, &count); +} + +bool managesieve_arg_get_list_full(const struct managesieve_arg *arg, + const struct managesieve_arg **list_r, + unsigned int *list_count_r) +{ + unsigned int count; + + if (arg->type != MANAGESIEVE_ARG_LIST) + return FALSE; + + *list_r = array_get(&arg->_data.list, &count); + + /* drop MANAGESIEVE_ARG_EOL from list size */ + i_assert(count > 0); + *list_count_r = count - 1; + return TRUE; +} + +const char *managesieve_arg_as_atom(const struct managesieve_arg *arg) +{ + const char *str; + + if (!managesieve_arg_get_atom(arg, &str)) + i_unreached(); + return str; +} + +const char *managesieve_arg_as_string(const struct managesieve_arg *arg) +{ + const char *str; + + if (!managesieve_arg_get_string(arg, &str)) + i_unreached(); + return str; +} + +struct istream * +managesieve_arg_as_string_stream(const struct managesieve_arg *arg) +{ + struct istream *stream; + + if (!managesieve_arg_get_string_stream(arg, &stream)) + i_unreached(); + return stream; +} + +const struct managesieve_arg * +managesieve_arg_as_list(const struct managesieve_arg *arg) +{ + const struct managesieve_arg *ret; + + if (!managesieve_arg_get_list(arg, &ret)) + i_unreached(); + return ret; +} + +bool managesieve_arg_atom_equals(const struct managesieve_arg *arg, + const char *str) +{ + const char *value; + + if (!managesieve_arg_get_atom(arg, &value)) + return FALSE; + return strcasecmp(value, str) == 0; +} + +void managesieve_write_arg(string_t *dest, const struct managesieve_arg *arg) +{ + const char *strval; + + switch (arg->type) { + case MANAGESIEVE_ARG_ATOM: + str_append(dest, managesieve_arg_as_atom(arg)); + break; + case MANAGESIEVE_ARG_STRING: + strval = managesieve_arg_as_string(arg); + str_append_c(dest, '"'); + str_append_escaped(dest, strval, strlen(strval)); + str_append_c(dest, '"'); + break; + case MANAGESIEVE_ARG_STRING_STREAM: + str_append(dest, "\"<too large>\""); + break; + case MANAGESIEVE_ARG_LITERAL: { + const char *strarg = managesieve_arg_as_string(arg); + str_printfa(dest, "{%zu}\r\n", + strlen(strarg)); + str_append(dest, strarg); + break; + } + case MANAGESIEVE_ARG_LIST: + str_append_c(dest, '('); + managesieve_write_args(dest, managesieve_arg_as_list(arg)); + str_append_c(dest, ')'); + break; + case MANAGESIEVE_ARG_NONE: + case MANAGESIEVE_ARG_EOL: + i_unreached(); + } +} + +void managesieve_write_args(string_t *dest, const struct managesieve_arg *args) +{ + bool first = TRUE; + + for (; !MANAGESIEVE_ARG_IS_EOL(args); args++) { + if (first) + first = FALSE; + else + str_append_c(dest, ' '); + managesieve_write_arg(dest, args); + } +} + +const char *managesieve_args_to_str(const struct managesieve_arg *args) +{ + string_t *str; + + str = t_str_new(128); + managesieve_write_args(str, args); + return str_c(str); +} + diff --git a/pigeonhole/src/lib-managesieve/managesieve-arg.h b/pigeonhole/src/lib-managesieve/managesieve-arg.h new file mode 100644 index 0000000..23f7c05 --- /dev/null +++ b/pigeonhole/src/lib-managesieve/managesieve-arg.h @@ -0,0 +1,117 @@ +#ifndef MANAGESIEVE_ARG_H +#define MANAGESIEVE_ARG_H + +#include "array.h" + +/* + * QUOTED-SPECIALS = <"> / "\" + */ +#define IS_QUOTED_SPECIAL(c) \ + ((c) == '"' || (c) == '\\') + +/* + * ATOM-SPECIALS = "(" / ")" / "{" / SP / CTL / QUOTED-SPECIALS + */ +#define IS_ATOM_SPECIAL(c) \ + ((c) == '(' || (c) == ')' || (c) == '{' || \ + (c) <= 32 || (c) == 0x7f || \ + IS_QUOTED_SPECIAL(c)) + +/* + * CHAR = %x01-7F + */ +#define IS_CHAR(c) \ + (((c) & 0x80) == 0) + +/* + * TEXT-CHAR = %x01-09 / %x0B-0C / %x0E-7F + * ;; any CHAR except CR and LF + */ +#define IS_TEXT_CHAR(c) \ + (IS_CHAR(c) && (c) != '\r' && (c) != '\n') + +/* + * SAFE-CHAR = %x01-09 / %x0B-0C / %x0E-21 / + * %x23-5B / %x5D-7F + * ;; any TEXT-CHAR except QUOTED-SPECIALS + */ +#define IS_SAFE_CHAR(c) \ + (IS_TEXT_CHAR(c) && !IS_QUOTED_SPECIAL(c)) + +enum managesieve_arg_type { + MANAGESIEVE_ARG_NONE = 0, + MANAGESIEVE_ARG_ATOM, + MANAGESIEVE_ARG_STRING, + MANAGESIEVE_ARG_STRING_STREAM, + + MANAGESIEVE_ARG_LIST, + + /* literals are returned as MANAGESIEVE_ARG_STRING by default */ + MANAGESIEVE_ARG_LITERAL, + + MANAGESIEVE_ARG_EOL /* end of argument list */ +}; + +ARRAY_DEFINE_TYPE(managesieve_arg_list, struct managesieve_arg); +struct managesieve_arg { + enum managesieve_arg_type type; + /* parent argument; always of type MANAGESIEVE_ARG_LIST */ + struct managesieve_arg *parent; + + /* Set when _data.str is set */ + size_t str_len; + + union { + const char *str; + struct istream *str_stream; + ARRAY_TYPE(managesieve_arg_list) list; + } _data; +}; + +#define MANAGESIEVE_ARG_IS_EOL(arg) \ + ((arg)->type == MANAGESIEVE_ARG_EOL) + +bool managesieve_arg_get_atom(const struct managesieve_arg *arg, + const char **str_r) ATTR_WARN_UNUSED_RESULT; +bool managesieve_arg_get_number(const struct managesieve_arg *arg, + uoff_t *number_r) ATTR_WARN_UNUSED_RESULT; +bool managesieve_arg_get_quoted(const struct managesieve_arg *arg, + const char **str_r) ATTR_WARN_UNUSED_RESULT; +bool managesieve_arg_get_string(const struct managesieve_arg *arg, + const char **str_r) ATTR_WARN_UNUSED_RESULT; + +bool managesieve_arg_get_string_stream(const struct managesieve_arg *arg, + struct istream **stream_r) + ATTR_WARN_UNUSED_RESULT; + +bool managesieve_arg_get_list(const struct managesieve_arg *arg, + const struct managesieve_arg **list_r) + ATTR_WARN_UNUSED_RESULT; +bool managesieve_arg_get_list_full(const struct managesieve_arg *arg, + const struct managesieve_arg **list_r, + unsigned int *list_count_r) + ATTR_WARN_UNUSED_RESULT; + +/* Similar to above, but assumes that arg is already of correct type. */ +const char *managesieve_arg_as_atom(const struct managesieve_arg *arg); +const char *managesieve_arg_as_string(const struct managesieve_arg *arg); +struct istream * +managesieve_arg_as_string_stream(const struct managesieve_arg *arg); +const struct managesieve_arg * +managesieve_arg_as_list(const struct managesieve_arg *arg); + +/* Returns TRUE if arg is atom and case-insensitively matches str */ +bool managesieve_arg_atom_equals(const struct managesieve_arg *arg, + const char *str); + +/* Write ManageSieve arg to the given string. Because + MANAGESIVE_ARG_LITERAL_SIZE* have no content, they're written as + "{size}\r\n<too large>". */ +void managesieve_write_arg(string_t *dest, const struct managesieve_arg *arg); +/* Same as managesieve_write_arg(), but write all the args until EOL. */ +void managesieve_write_args(string_t *dest, const struct managesieve_arg *args); +/* Like managesieve_write_args(), but return the string allocated from data + stack. */ +const char *managesieve_args_to_str(const struct managesieve_arg *args); + +#endif diff --git a/pigeonhole/src/lib-managesieve/managesieve-parser.c b/pigeonhole/src/lib-managesieve/managesieve-parser.c new file mode 100644 index 0000000..546e431 --- /dev/null +++ b/pigeonhole/src/lib-managesieve/managesieve-parser.c @@ -0,0 +1,757 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "unichar.h" +#include "istream-private.h" +#include "ostream.h" +#include "strescape.h" +#include "managesieve-parser.h" + +#define is_linebreak(c) \ + ((c) == '\r' || (c) == '\n') + +#define LIST_INIT_COUNT 7 + +enum arg_parse_type { + ARG_PARSE_NONE = 0, + ARG_PARSE_ATOM, + ARG_PARSE_STRING, + ARG_PARSE_LITERAL, + ARG_PARSE_LITERAL_DATA +}; + +struct managesieve_parser { + /* permanent */ + pool_t pool; + struct istream *input; + size_t max_line_size; + enum managesieve_parser_flags flags; + + /* reset by managesieve_parser_reset(): */ + size_t line_size; + ARRAY_TYPE(managesieve_arg_list) root_list; + ARRAY_TYPE(managesieve_arg_list) *cur_list; + struct managesieve_arg *list_arg; + + enum arg_parse_type cur_type; + size_t cur_pos; /* parser position in input buffer */ + + int str_first_escape; /* ARG_PARSE_STRING: index to first '\' */ + uoff_t literal_size; /* ARG_PARSE_LITERAL: string size */ + + struct istream *str_stream; + + const char *error; + + bool literal_skip_crlf:1; + bool literal_nonsync:1; + bool eol:1; + bool fatal_error:1; +}; + +static struct istream *quoted_string_istream_create + (struct managesieve_parser *parser); + +struct managesieve_parser * +managesieve_parser_create(struct istream *input, size_t max_line_size) +{ + struct managesieve_parser *parser; + + parser = i_new(struct managesieve_parser, 1); + parser->pool = pool_alloconly_create("MANAGESIEVE parser", 8192); + parser->input = input; + parser->max_line_size = max_line_size; + + p_array_init(&parser->root_list, parser->pool, LIST_INIT_COUNT); + parser->cur_list = &parser->root_list; + return parser; +} + +void managesieve_parser_destroy(struct managesieve_parser **parser) +{ + i_stream_unref(&(*parser)->str_stream); + + pool_unref(&(*parser)->pool); + i_free(*parser); + *parser = NULL; +} + +void managesieve_parser_reset(struct managesieve_parser *parser) +{ + p_clear(parser->pool); + + parser->line_size = 0; + + p_array_init(&parser->root_list, parser->pool, LIST_INIT_COUNT); + parser->cur_list = &parser->root_list; + parser->list_arg = NULL; + + parser->cur_type = ARG_PARSE_NONE; + parser->cur_pos = 0; + + parser->str_first_escape = 0; + parser->literal_size = 0; + + parser->error = NULL; + + parser->literal_skip_crlf = FALSE; + parser->eol = FALSE; + + i_stream_unref(&parser->str_stream); +} + +const char * +managesieve_parser_get_error(struct managesieve_parser *parser, bool *fatal) +{ + *fatal = parser->fatal_error; + return parser->error; +} + +/* Skip over everything parsed so far, plus the following whitespace */ +static bool +managesieve_parser_skip_to_next(struct managesieve_parser *parser, + const unsigned char **data, size_t *data_size) +{ + size_t i; + + for (i = parser->cur_pos; i < *data_size; i++) { + if ((*data)[i] != ' ') + break; + } + + parser->line_size += i; + i_stream_skip(parser->input, i); + parser->cur_pos = 0; + + *data += i; + *data_size -= i; + return *data_size > 0; +} + +static struct managesieve_arg * +managesieve_arg_create(struct managesieve_parser *parser) +{ + struct managesieve_arg *arg; + + arg = array_append_space(parser->cur_list); + arg->parent = parser->list_arg; + + return arg; +} + +static void +managesieve_parser_save_arg(struct managesieve_parser *parser, + const unsigned char *data, size_t size) +{ + struct managesieve_arg *arg; + char *str; + + arg = managesieve_arg_create(parser); + + switch (parser->cur_type) { + case ARG_PARSE_ATOM: + /* Simply save the string */ + arg->type = MANAGESIEVE_ARG_ATOM; + arg->_data.str = p_strndup(parser->pool, data, size); + arg->str_len = size; + break; + case ARG_PARSE_STRING: + /* Data is quoted and may contain escapes. */ + if ((parser->flags & + MANAGESIEVE_PARSE_FLAG_STRING_STREAM) != 0) { + arg->type = MANAGESIEVE_ARG_STRING_STREAM; + arg->_data.str_stream = parser->str_stream; + } else { + i_assert(size > 0); + + arg->type = MANAGESIEVE_ARG_STRING; + str = p_strndup(parser->pool, data+1, size-1); + + /* remove the escapes */ + if (parser->str_first_escape >= 0 && + (parser->flags & + MANAGESIEVE_PARSE_FLAG_NO_UNESCAPE) == 0) + (void)str_unescape(str); + + arg->_data.str = str; + arg->str_len = strlen(str); + } + break; + case ARG_PARSE_LITERAL_DATA: + if ((parser->flags & + MANAGESIEVE_PARSE_FLAG_STRING_STREAM) != 0) { + arg->type = MANAGESIEVE_ARG_STRING_STREAM; + arg->_data.str_stream = parser->str_stream; + } else if ((parser->flags & + MANAGESIEVE_PARSE_FLAG_LITERAL_TYPE) != 0) { + arg->type = MANAGESIEVE_ARG_LITERAL; + arg->_data.str = p_strndup(parser->pool, data, size); + arg->str_len = size; + } else { + arg->type = MANAGESIEVE_ARG_STRING; + arg->_data.str = p_strndup(parser->pool, data, size); + arg->str_len = size; + } + break; + default: + i_unreached(); + } + + parser->cur_type = ARG_PARSE_NONE; +} + +static bool is_valid_atom_char(struct managesieve_parser *parser, char chr) +{ + if (IS_ATOM_SPECIAL((unsigned char)chr)) { + parser->error = "Invalid characters in atom"; + return FALSE; + } else if ((((unsigned char)chr) & 0x80) != 0) { + parser->error = "8bit data in atom"; + return FALSE; + } + + return TRUE; +} + +static bool +managesieve_parser_read_atom(struct managesieve_parser *parser, + const unsigned char *data, size_t data_size) +{ + size_t i; + + /* Read until we've found space, CR or LF. */ + for (i = parser->cur_pos; i < data_size; i++) { + if (data[i] == ' ' || data[i] == ')' || + is_linebreak(data[i])) { + managesieve_parser_save_arg(parser, data, i); + break; + } else if (!is_valid_atom_char(parser, data[i])) + return FALSE; + } + + parser->cur_pos = i; + return (parser->cur_type == ARG_PARSE_NONE); +} + +static bool +managesieve_parser_read_string(struct managesieve_parser *parser, + const unsigned char *data, size_t data_size) +{ + size_t i; + + /* QUOTED-CHAR = SAFE-UTF8-CHAR / "\" QUOTED-SPECIALS + quoted = <"> *QUOTED-CHAR <"> + ;; limited to 1024 octets between the <">s + */ + + /* Read until we've found non-escaped ", CR or LF */ + for (i = parser->cur_pos; i < data_size; i++) { + if (data[i] == '"') { + if (!uni_utf8_data_is_valid(data+1, i-1)) { + parser->error = + "Invalid UTF-8 character in quoted-string."; + return FALSE; + } + + managesieve_parser_save_arg(parser, data, i); + i++; /* skip the trailing '"' too */ + break; + } + + if (data[i] == '\0') { + parser->error = "NULs not allowed in strings"; + return FALSE; + } + + if (data[i] == '\\') { + if (i+1 == data_size) { + /* Known data ends with '\' - leave it to next + time as well if it happens to be \" */ + break; + } + + /* Save the first escaped char */ + if (parser->str_first_escape < 0) + parser->str_first_escape = i; + + /* Skip the escaped char */ + i++; + + if (!IS_QUOTED_SPECIAL(data[i])) { + parser->error = + "Escaped quoted-string character is not a QUOTED-SPECIAL."; + return FALSE; + } + continue; + } + + if ((data[i] & 0x80) == 0 && !IS_SAFE_CHAR(data[i])) { + parser->error = "String contains invalid character."; + return FALSE; + } + } + + parser->cur_pos = i; + return (parser->cur_type == ARG_PARSE_NONE); +} + +static bool managesieve_parser_literal_end(struct managesieve_parser *parser) +{ + if ((parser->flags & MANAGESIEVE_PARSE_FLAG_STRING_STREAM) == 0) { + if (parser->line_size >= parser->max_line_size || + (parser->literal_size > + (parser->max_line_size - parser->line_size))) { + /* Too long string, abort. */ + parser->error = "Literal size too large"; + parser->fatal_error = TRUE; + return FALSE; + } + } + + parser->cur_type = ARG_PARSE_LITERAL_DATA; + parser->literal_skip_crlf = TRUE; + + parser->cur_pos = 0; + return TRUE; +} + +static bool +managesieve_parser_read_literal(struct managesieve_parser *parser, + const unsigned char *data, size_t data_size) +{ + size_t i; + + /* Expecting digits + "}" */ + for (i = parser->cur_pos; i < data_size; i++) { + if (data[i] == '}') { + parser->line_size += i+1; + i_stream_skip(parser->input, i+1); + + return managesieve_parser_literal_end(parser); + } + + if (parser->literal_nonsync) { + parser->error = "Expecting '}' after '+'"; + return FALSE; + } + + if (data[i] == '+') { + parser->literal_nonsync = TRUE; + continue; + } + + if (data[i] < '0' || data[i] > '9') { + parser->error = "Invalid literal size"; + return FALSE; + } + + if (parser->literal_size >= ((uoff_t)-1 / 10)) { + if (parser->literal_size > ((uoff_t)-1 / 10) || + (uoff_t)(data[i] - '0') > ((uoff_t)-1 % 10)) { + parser->error = "Literal size too large"; + return FALSE; + } + } + parser->literal_size = parser->literal_size * 10 + + (data[i] - '0'); + } + + parser->cur_pos = i; + return FALSE; +} + +static bool +managesieve_parser_read_literal_data(struct managesieve_parser *parser, + const unsigned char *data, + size_t data_size) +{ + if (parser->literal_skip_crlf) { + /* Skip \r\n or \n, anything else gives an error */ + if (data_size == 0) + return FALSE; + + if (*data == '\r') { + parser->line_size++; + data++; data_size--; + i_stream_skip(parser->input, 1); + + if (data_size == 0) + return FALSE; + } + + if (*data != '\n') { + parser->error = "Missing LF after literal size"; + return FALSE; + } + + parser->line_size++; + data++; data_size--; + i_stream_skip(parser->input, 1); + + parser->literal_skip_crlf = FALSE; + + i_assert(parser->cur_pos == 0); + } + + if ((parser->flags & MANAGESIEVE_PARSE_FLAG_STRING_STREAM) == 0) { + /* Now we just wait until we've read enough data */ + if (data_size < parser->literal_size) { + return FALSE; + } else { + if (!uni_utf8_data_is_valid( + data, (size_t)parser->literal_size)) { + parser->error = + "Invalid UTF-8 character in literal string."; + return FALSE; + } + + managesieve_parser_save_arg( + parser, data, (size_t)parser->literal_size); + parser->cur_pos = (size_t)parser->literal_size; + return TRUE; + } + } else { + /* We don't read the data; we just create a stream for the + literal */ + parser->eol = TRUE; + parser->str_stream = i_stream_create_limit( + parser->input, parser->literal_size); + managesieve_parser_save_arg(parser, NULL, 0); + return TRUE; + } +} + +/* Returns TRUE if argument was fully processed. Also returns TRUE if an + argument inside a list was processed. */ +static bool managesieve_parser_read_arg(struct managesieve_parser *parser) +{ + const unsigned char *data; + size_t data_size; + + data = i_stream_get_data(parser->input, &data_size); + if (data_size == 0) + return FALSE; + + while (parser->cur_type == ARG_PARSE_NONE) { + /* We haven't started parsing yet */ + if (!managesieve_parser_skip_to_next(parser, &data, &data_size)) + return FALSE; + i_assert(parser->cur_pos == 0); + + switch (data[0]) { + case '\r': + case '\n': + /* Unexpected end of line */ + parser->eol = TRUE; + return FALSE; + case '"': + parser->cur_type = ARG_PARSE_STRING; + parser->str_first_escape = -1; + break; + case '{': + parser->cur_type = ARG_PARSE_LITERAL; + parser->literal_size = 0; + parser->literal_nonsync = FALSE; + break; + default: + if (!is_valid_atom_char(parser, data[0])) + return FALSE; + parser->cur_type = ARG_PARSE_ATOM; + break; + } + parser->cur_pos++; + } + + i_assert(data_size > 0); + + switch (parser->cur_type) { + case ARG_PARSE_ATOM: + if (!managesieve_parser_read_atom(parser, data, data_size)) + return FALSE; + break; + case ARG_PARSE_STRING: + if ((parser->flags & + MANAGESIEVE_PARSE_FLAG_STRING_STREAM) != 0) { + parser->eol = TRUE; + parser->line_size += parser->cur_pos; + i_stream_skip(parser->input, parser->cur_pos); + parser->cur_pos = 0; + parser->str_stream = + quoted_string_istream_create(parser); + managesieve_parser_save_arg(parser, NULL, 0); + + } else if (!managesieve_parser_read_string(parser, + data, data_size)) { + return FALSE; + } + break; + case ARG_PARSE_LITERAL: + if (!managesieve_parser_read_literal(parser, data, data_size)) + return FALSE; + + /* Pass through to parsing data. since input->skip was + modified, we need to get the data start position again. */ + data = i_stream_get_data(parser->input, &data_size); + + /* fall through */ + case ARG_PARSE_LITERAL_DATA: + if (!managesieve_parser_read_literal_data(parser, + data, data_size)) + return FALSE; + break; + default: + i_unreached(); + } + + i_assert(parser->cur_type == ARG_PARSE_NONE); + return TRUE; +} + +/* ARG_PARSE_NONE checks that last argument isn't only partially parsed. */ +#define IS_UNFINISHED(parser) \ + ((parser)->cur_type != ARG_PARSE_NONE || \ + (parser)->cur_list != &parser->root_list) + +static int +finish_line(struct managesieve_parser *parser, unsigned int count, + const struct managesieve_arg **args_r) +{ + struct managesieve_arg *arg; + int ret = array_count(&parser->root_list); + + parser->line_size += parser->cur_pos; + i_stream_skip(parser->input, parser->cur_pos); + parser->cur_pos = 0; + + /* Fill the missing parameters with NILs */ + while (count > array_count(&parser->root_list)) { + arg = array_append_space(&parser->root_list); + arg->type = MANAGESIEVE_ARG_NONE; + } + arg = array_append_space(&parser->root_list); + arg->type = MANAGESIEVE_ARG_EOL; + + *args_r = array_get(&parser->root_list, &count); + return ret; +} + +int managesieve_parser_read_args(struct managesieve_parser *parser, + unsigned int count, + enum managesieve_parser_flags flags, + const struct managesieve_arg **args_r) +{ + parser->flags = flags; + + while (!parser->eol && (count == 0 || IS_UNFINISHED(parser) || + array_count(&parser->root_list) < count)) { + if (!managesieve_parser_read_arg(parser)) + break; + + if (parser->line_size > parser->max_line_size) { + parser->error = "MANAGESIEVE command line too large"; + break; + } + } + + if (parser->error != NULL) { + /* Error, abort */ + parser->line_size += parser->cur_pos; + i_stream_skip(parser->input, parser->cur_pos); + parser->cur_pos = 0; + *args_r = NULL; + return -1; + } else if ((!IS_UNFINISHED(parser) && count > 0 && + array_count(&parser->root_list) >= count) || parser->eol) { + /* All arguments read / end of line. */ + return finish_line(parser, count, args_r); + } else { + /* Need more data */ + *args_r = NULL; + return -2; + } +} + +int managesieve_parser_finish_line(struct managesieve_parser *parser, + unsigned int count, + enum managesieve_parser_flags flags, + const struct managesieve_arg **args_r) +{ + const unsigned char *data; + size_t data_size; + int ret; + + ret = managesieve_parser_read_args(parser, count, flags, args_r); + if (ret == -2) { + /* We should have noticed end of everything except atom */ + if (parser->cur_type == ARG_PARSE_ATOM) { + data = i_stream_get_data(parser->input, &data_size); + managesieve_parser_save_arg(parser, data, data_size); + } + } + return finish_line(parser, count, args_r); +} + +const char *managesieve_parser_read_word(struct managesieve_parser *parser) +{ + const unsigned char *data; + size_t i, data_size; + + data = i_stream_get_data(parser->input, &data_size); + + for (i = 0; i < data_size; i++) { + if (data[i] == ' ' || data[i] == '\r' || data[i] == '\n') + break; + } + + if (i < data_size) { + data_size = i + (data[i] == ' ' ? 1 : 0); + parser->line_size += data_size; + i_stream_skip(parser->input, data_size); + return p_strndup(parser->pool, data, i); + } else { + return NULL; + } +} + +/* + * Quoted string stream + */ + +struct quoted_string_istream { + struct istream_private istream; + + /* The end '"' was found */ + bool str_end:1; +}; + +static int +quoted_string_istream_read_parent(struct quoted_string_istream *qsstream, + unsigned int min_bytes) +{ + struct istream_private *stream = &qsstream->istream; + size_t size, avail; + ssize_t ret; + + size = i_stream_get_data_size(stream->parent); + while (size < min_bytes) { + ret = i_stream_read_memarea(stream->parent); + if (ret <= 0) { + if (ret == -2) { + /* Tiny parent buffer size - shouldn't happen */ + return -2; + } + stream->istream.stream_errno = + stream->parent->stream_errno; + stream->istream.eof = stream->parent->eof; + if (ret == -1 && stream->istream.stream_errno == 0) { + io_stream_set_error(&stream->iostream, + "Quoted string ends without closing quotes"); + stream->istream.stream_errno = EPIPE; + } + return ret; + } + size = i_stream_get_data_size(stream->parent); + } + + if (!i_stream_try_alloc(stream, size, &avail)) + return -2; + return 1; +} + +static ssize_t quoted_string_istream_read(struct istream_private *stream) +{ + struct quoted_string_istream *qsstream = + (struct quoted_string_istream *)stream; + const unsigned char *data; + unsigned int extra; + size_t i, dest, size; + ssize_t ret; + + if (qsstream->str_end) { + stream->istream.eof = TRUE; + return -1; + } + + ret = quoted_string_istream_read_parent(qsstream, 1); + if (ret <= 0) + return ret; + + /* @UNSAFE */ + dest = stream->pos; + extra = 0; + + data = i_stream_get_data(stream->parent, &size); + for (i = 0; i < size && dest < stream->buffer_size; ) { + if (data[i] == '"') { + i++; + qsstream->str_end = TRUE; + if (dest == stream->pos) { + i_stream_skip(stream->parent, i); + stream->istream.eof = TRUE; + return -1; + } + break; + } else if (data[i] == '\\') { + if (i+1 == size) { + /* Not enough input for \x */ + extra = 1; + break; + } + i++; + + if (!IS_QUOTED_SPECIAL(data[i])) { + /* Invalid string */ + io_stream_set_error(&stream->iostream, + "Escaped quoted-string character is not a QUOTED-SPECIAL"); + stream->istream.stream_errno = EINVAL; + return -1; + } + stream->w_buffer[dest++] = data[i]; + i++; + } else { + if (data[i] == '\r' || data[i] == '\n') { + io_stream_set_error(&stream->iostream, + "Quoted string contains an invalid character"); + stream->istream.stream_errno = EINVAL; + return -1; + } + + stream->w_buffer[dest++] = data[i]; + i++; + } + i_assert(dest <= stream->buffer_size); + } + i_stream_skip(stream->parent, i); + + ret = dest - stream->pos; + if (ret == 0) { + /* Not enough input */ + i_assert(i == 0); + i_assert(extra > 0); + ret = quoted_string_istream_read_parent(qsstream, extra+1); + if (ret <= 0) + return ret; + return quoted_string_istream_read(stream); + } + i_assert(ret > 0); + stream->pos = dest; + return ret; +} + +static struct +istream *quoted_string_istream_create(struct managesieve_parser *parser) +{ + struct quoted_string_istream *qsstream; + + qsstream = i_new(struct quoted_string_istream, 1); + qsstream->istream.max_buffer_size = + parser->input->real_stream->max_buffer_size; + qsstream->istream.read = quoted_string_istream_read; + + qsstream->istream.istream.readable_fd = FALSE; + qsstream->istream.istream.blocking = parser->input->blocking; + qsstream->istream.istream.seekable = FALSE; + return i_stream_create(&qsstream->istream, parser->input, + i_stream_get_fd(parser->input), 0); +} diff --git a/pigeonhole/src/lib-managesieve/managesieve-parser.h b/pigeonhole/src/lib-managesieve/managesieve-parser.h new file mode 100644 index 0000000..93e67ae --- /dev/null +++ b/pigeonhole/src/lib-managesieve/managesieve-parser.h @@ -0,0 +1,67 @@ +#ifndef MANAGESIEVE_PARSER_H +#define MANAGESIEVE_PARSER_H + +#include "managesieve-arg.h" + +enum managesieve_parser_flags { + /* Set this flag if you want to read a string argument as as stream. + Useful when you need to deal with large strings. The string must be + the last read argument. */ + MANAGESIEVE_PARSE_FLAG_STRING_STREAM = 0x01, + /* Don't remove '\' chars from string arguments */ + MANAGESIEVE_PARSE_FLAG_NO_UNESCAPE = 0x02, + /* Return literals as MANAGESIEVE_ARG_LITERAL instead of + MANAGESIEVE_ARG_STRING */ + MANAGESIEVE_PARSE_FLAG_LITERAL_TYPE = 0x04 +}; + +struct managesieve_parser; + +/* Create new MANAGESIEVE argument parser. + + max_line_size can be used to approximately limit the maximum amount of memory + that gets allocated when parsing a line. Input buffer size limits the maximum + size of each parsed token. + + Usually the largest lines are large only because they have a one huge message + set token, so you'll probably want to keep input buffer size the same as + max_line_size. That means the maximum memory usage is around + 2 * max_line_size. */ +struct managesieve_parser * +managesieve_parser_create(struct istream *input, size_t max_line_size); +void managesieve_parser_destroy(struct managesieve_parser **parser); + +/* Reset the parser to initial state. */ +void managesieve_parser_reset(struct managesieve_parser *parser); + +/* Return the last error in parser. fatal is set to TRUE if there's no way to + continue parsing, currently only if too large non-sync literal size was + given. */ +const char * +managesieve_parser_get_error(struct managesieve_parser *parser, bool *fatal); + +/* Read a number of arguments. This function doesn't call i_stream_read(), you + need to do that. Returns number of arguments read (may be less than count + in case of EOL), -2 if more data is needed or -1 if error occurred. + + count-sized array of arguments are stored into args when return value is 0 or + larger. If all arguments weren't read, they're set to NIL. count can be set + to 0 to read all arguments in the line. Last element in args is always of + type MANAGESIEVE_ARG_EOL. */ +int managesieve_parser_read_args(struct managesieve_parser *parser, + unsigned int count, + enum managesieve_parser_flags flags, + const struct managesieve_arg **args_r); + +/* Just like managesieve_parser_read_args(), but assume \n at end of data in + input stream. */ +int managesieve_parser_finish_line(struct managesieve_parser *parser, + unsigned int count, + enum managesieve_parser_flags flags, + const struct managesieve_arg **args_r); + +/* Read one word - used for reading command name. Returns NULL if more data is + needed. */ +const char *managesieve_parser_read_word(struct managesieve_parser *parser); + +#endif diff --git a/pigeonhole/src/lib-managesieve/managesieve-quote.c b/pigeonhole/src/lib-managesieve/managesieve-quote.c new file mode 100644 index 0000000..a86818c --- /dev/null +++ b/pigeonhole/src/lib-managesieve/managesieve-quote.c @@ -0,0 +1,121 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "unichar.h" +#include "managesieve-parser.h" +#include "managesieve-quote.h" + +/* Turn the value string into a valid MANAGESIEVE string or literal, no matter + * what. QUOTED-SPECIALS are escaped, but any invalid (UTF-8) character + * is simply removed. Linebreak characters are not considered invalid, but + * they do force the generation of a string literal. + */ +void managesieve_quote_append(string_t *str, const unsigned char *value, + size_t value_len, bool compress_lwsp) +{ + size_t i, extra = 0, escape = 0; + string_t *tmp; + bool + last_lwsp = TRUE, + literal = FALSE, + modify = FALSE; + + if (value == NULL) { + str_append(str, "\"\""); + return; + } + + if (value_len == (size_t)-1) + value_len = strlen((const char *) value); + + for (i = 0; i < value_len; i++) { + switch (value[i]) { + case ' ': + case '\t': + if (last_lwsp && compress_lwsp) { + modify = TRUE; + extra++; + } + last_lwsp = TRUE; + break; + case '"': + case '\\': + escape++; + last_lwsp = FALSE; + break; + case 13: + case 10: + literal = TRUE; + last_lwsp = TRUE; + break; + default: + last_lwsp = FALSE; + } + } + + if (!literal) { + /* no linebreak chars, return as (escaped) "string" */ + str_append_c(str, '"'); + } else { + /* return as literal */ + str_printfa(str, "{%zu}\r\n", value_len - extra); + } + + tmp = t_str_new(value_len+escape+4); + if (!modify && (literal || escape == 0)) + str_append_data(tmp, value, value_len); + else { + last_lwsp = TRUE; + for (i = 0; i < value_len; i++) { + switch (value[i]) { + case '"': + case '\\': + last_lwsp = FALSE; + if (!literal) + str_append_c(tmp, '\\'); + str_append_c(tmp, value[i]); + break; + case ' ': + case '\t': + if (!last_lwsp || !compress_lwsp) + str_append_c(tmp, ' '); + last_lwsp = TRUE; + break; + case 13: + case 10: + last_lwsp = TRUE; + str_append_c(tmp, value[i]); + break; + default: + last_lwsp = FALSE; + str_append_c(tmp, value[i]); + break; + } + } + } + + if ( uni_utf8_get_valid_data(str_data(tmp), str_len(tmp), str) ) + str_append_str(str, tmp); + + if (!literal) + str_append_c(str, '"'); +} + +char *managesieve_quote(pool_t pool, const unsigned char *value, size_t value_len) +{ + string_t *str; + char *ret; + + if (value == NULL) + return "\"\""; + + T_BEGIN { + str = t_str_new(value_len + MAX_INT_STRLEN + 5); + managesieve_quote_append(str, value, value_len, TRUE); + ret = p_strndup(pool, str_data(str), str_len(str)); + } T_END; + + return ret; +} diff --git a/pigeonhole/src/lib-managesieve/managesieve-quote.h b/pigeonhole/src/lib-managesieve/managesieve-quote.h new file mode 100644 index 0000000..cae5491 --- /dev/null +++ b/pigeonhole/src/lib-managesieve/managesieve-quote.h @@ -0,0 +1,17 @@ +#ifndef IMAP_QUOTE_H +#define IMAP_QUOTE_H + +/* Return value suitable for sending to client, either as quoted-string or + literal. Note that this also converts TABs into spaces, multiple spaces + into single space and NULs to #128. */ +char *managesieve_quote(pool_t pool, const unsigned char *value, size_t value_len); + +/* Append to existing string. */ +void managesieve_quote_append(string_t *str, const unsigned char *value, + size_t value_len, bool compress_lwsp); + +#define managesieve_quote_append_string(str, value, compress_lwsp) \ + managesieve_quote_append(str, (const unsigned char *)(value), \ + (size_t)-1, compress_lwsp) + +#endif diff --git a/pigeonhole/src/lib-sieve-tool/Makefile.am b/pigeonhole/src/lib-sieve-tool/Makefile.am new file mode 100644 index 0000000..3386824 --- /dev/null +++ b/pigeonhole/src/lib-sieve-tool/Makefile.am @@ -0,0 +1,13 @@ +noinst_LTLIBRARIES = libsieve-tool.la + +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + -I$(top_srcdir)/src/lib-sieve/util \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_SERVICE_INCLUDE) + +libsieve_tool_la_SOURCES = \ + sieve-tool.c + +noinst_HEADERS = \ + sieve-tool.h diff --git a/pigeonhole/src/lib-sieve-tool/Makefile.in b/pigeonhole/src/lib-sieve-tool/Makefile.in new file mode 100644 index 0000000..c56deeb --- /dev/null +++ b/pigeonhole/src/lib-sieve-tool/Makefile.in @@ -0,0 +1,680 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve-tool +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_tool_la_LIBADD = +am_libsieve_tool_la_OBJECTS = sieve-tool.lo +libsieve_tool_la_OBJECTS = $(am_libsieve_tool_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/sieve-tool.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_tool_la_SOURCES) +DIST_SOURCES = $(libsieve_tool_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve-tool.la +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + -I$(top_srcdir)/src/lib-sieve/util \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_SERVICE_INCLUDE) + +libsieve_tool_la_SOURCES = \ + sieve-tool.c + +noinst_HEADERS = \ + sieve-tool.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve-tool/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve-tool/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve-tool.la: $(libsieve_tool_la_OBJECTS) $(libsieve_tool_la_DEPENDENCIES) $(EXTRA_libsieve_tool_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_tool_la_OBJECTS) $(libsieve_tool_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-tool.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/sieve-tool.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/sieve-tool.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve-tool/sieve-tool.c b/pigeonhole/src/lib-sieve-tool/sieve-tool.c new file mode 100644 index 0000000..435f973 --- /dev/null +++ b/pigeonhole/src/lib-sieve-tool/sieve-tool.c @@ -0,0 +1,672 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "lib-signals.h" +#include "array.h" +#include "ioloop.h" +#include "ostream.h" +#include "hostpid.h" +#include "dict.h" +#include "mail-namespace.h" +#include "mail-storage.h" +#include "mail-user.h" +#include "message-address.h" +#include "smtp-params.h" +#include "master-service.h" +#include "master-service-settings.h" +#include "mail-storage-service.h" + +#include "sieve.h" +#include "sieve-plugins.h" +#include "sieve-extensions.h" + +#include "mail-raw.h" + +#include "sieve-tool.h" + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <pwd.h> +#include <sysexits.h> + +/* + * Global state + */ + +struct sieve_tool { + char *name; + + bool no_config; + + char *username; + char *homedir; + + char *sieve_extensions; + ARRAY_TYPE(const_string) sieve_plugins; + + sieve_tool_setting_callback_t setting_callback; + void *setting_callback_context; + + struct sieve_instance *svinst; + + struct mail_storage_service_ctx *storage_service; + struct mail_storage_service_user *service_user; + struct mail_user *mail_user_dovecot; + struct mail_user *mail_user; + + struct mail_user *mail_raw_user; + struct mail_raw *mail_raw; + + bool debug:1; +}; + +struct sieve_tool *sieve_tool; + +/* + * Settings management + */ + +static const char * +sieve_tool_sieve_get_setting(void *context, const char *identifier) +{ + struct sieve_tool *tool = (struct sieve_tool *) context; + + if (tool->setting_callback != NULL) { + return tool->setting_callback(tool->setting_callback_context, + identifier); + } + + if (tool->mail_user_dovecot == NULL) + return NULL; + + return mail_user_plugin_getenv(tool->mail_user_dovecot, identifier); +} + +static const char *sieve_tool_sieve_get_homedir(void *context) +{ + struct sieve_tool *tool = (struct sieve_tool *) context; + + return sieve_tool_get_homedir(tool); +} + +const struct sieve_callbacks sieve_tool_callbacks = { + sieve_tool_sieve_get_homedir, + sieve_tool_sieve_get_setting +}; + +/* + * Initialization + */ + +static void +sieve_tool_get_user_data(const char **username_r, const char **homedir_r) +{ + uid_t process_euid = geteuid(); + struct passwd *pw; + const char *user = NULL, *home = NULL; + + user = getenv("USER"); + home = getenv("HOME"); + + if (user == NULL || *user == '\0' || home == NULL || *home == '\0') { + if ((pw = getpwuid(process_euid)) != NULL) { + user = pw->pw_name; + home = pw->pw_dir; + } + } + + if (username_r != NULL) { + if (user == NULL || *user == '\0') { + i_fatal("couldn't lookup our username (uid=%s)", + dec2str(process_euid)); + } + + *username_r = t_strdup(user); + } + + if (homedir_r != NULL) + *homedir_r = t_strdup(home); +} + +struct sieve_tool * +sieve_tool_init(const char *name, int *argc, char **argv[], + const char *getopt_str, bool no_config) +{ + struct sieve_tool *tool; + enum master_service_flags service_flags = + MASTER_SERVICE_FLAG_STANDALONE | + MASTER_SERVICE_FLAG_DONT_SEND_STATS | + MASTER_SERVICE_FLAG_NO_INIT_DATASTACK_FRAME | + MASTER_SERVICE_FLAG_DISABLE_SSL_SET; + + if (no_config) + service_flags |= MASTER_SERVICE_FLAG_NO_CONFIG_SETTINGS; + + master_service = master_service_init(name, service_flags, + argc, argv, getopt_str); + + tool = i_new(struct sieve_tool, 1); + tool->name = i_strdup(name); + tool->no_config = no_config; + + i_array_init(&tool->sieve_plugins, 16); + + return tool; +} + +int sieve_tool_getopt(struct sieve_tool *tool) +{ + int c; + + while ((c = master_getopt(master_service)) > 0) { + switch (c) { + case 'x': + /* extensions */ + if (tool->sieve_extensions != NULL) { + i_fatal_status( + EX_USAGE, + "duplicate -x option specified, " + "but only one allowed."); + } + tool->sieve_extensions = i_strdup(optarg); + break; + case 'u': + if (tool->username == NULL) + tool->username = i_strdup(optarg); + break; + case 'P': + /* Plugin */ + { + const char *plugin; + + plugin = t_strdup(optarg); + array_append(&tool->sieve_plugins, &plugin, 1); + } + break; + case 'D': + tool->debug = TRUE; + break; + default: + return c; + } + } + + return c; +} + +static void sieve_tool_load_plugins(struct sieve_tool *tool) +{ + unsigned int i, count; + const char * const *plugins; + + plugins = array_get(&tool->sieve_plugins, &count); + for (i = 0; i < count; i++) { + const char *path, *file = strrchr(plugins[i], '/'); + + if (file != NULL) { + path = t_strdup_until(plugins[i], file); + file = file+1; + } else { + path = NULL; + file = plugins[i]; + } + + sieve_plugins_load(tool->svinst, path, file); + } +} + +struct sieve_instance * +sieve_tool_init_finish(struct sieve_tool *tool, bool init_mailstore, + bool preserve_root) +{ + enum mail_storage_service_flags storage_service_flags = + MAIL_STORAGE_SERVICE_FLAG_NO_CHDIR | + MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT | + MAIL_STORAGE_SERVICE_FLAG_USE_SYSEXITS; + struct mail_storage_service_input service_input; + struct sieve_environment svenv; + const char *username = tool->username; + const char *homedir = tool->homedir; + const char *errstr; + + master_service_init_finish(master_service); + + if (username == NULL) { + sieve_tool_get_user_data(&username, &homedir); + + username = tool->username = i_strdup(username); + + if (tool->homedir != NULL) + i_free(tool->homedir); + tool->homedir = i_strdup(homedir); + + if (preserve_root) { + storage_service_flags |= + MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS; + } + } else { + storage_service_flags |= + MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP; + } + + if (!init_mailstore) + storage_service_flags |= + MAIL_STORAGE_SERVICE_FLAG_NO_NAMESPACES; + + i_zero(&service_input); + service_input.module = "mail"; + service_input.service = tool->name; + service_input.username = username; + + tool->storage_service = mail_storage_service_init( + master_service, NULL, storage_service_flags); + if (mail_storage_service_lookup_next( + tool->storage_service, &service_input, &tool->service_user, + &tool->mail_user_dovecot, &errstr) <= 0) + i_fatal("%s", errstr); + + if (master_service_set(master_service, + "mail_full_filesystem_access=yes") < 0) + i_unreached(); + + memset((void *)&svenv, 0, sizeof(svenv)); + svenv.username = username; + (void)mail_user_get_home(tool->mail_user_dovecot, &svenv.home_dir); + svenv.hostname = my_hostdomain(); + svenv.base_dir = tool->mail_user_dovecot->set->base_dir; + svenv.temp_dir = tool->mail_user_dovecot->set->mail_temp_dir; + svenv.location = SIEVE_ENV_LOCATION_MS; + svenv.delivery_phase = SIEVE_DELIVERY_PHASE_POST; + + /* Initialize Sieve Engine */ + if ((tool->svinst = sieve_init(&svenv, &sieve_tool_callbacks, + tool, tool->debug)) == NULL) + i_fatal("failed to initialize sieve implementation"); + + /* Load Sieve plugins */ + if (array_count(&tool->sieve_plugins) > 0) + sieve_tool_load_plugins(tool); + + /* Set active Sieve extensions */ + if (tool->sieve_extensions != NULL) { + sieve_set_extensions(tool->svinst, tool->sieve_extensions); + } else if (tool->no_config) { + sieve_set_extensions(tool->svinst, NULL); + } + + return tool->svinst; +} + +void sieve_tool_deinit(struct sieve_tool **_tool) +{ + struct sieve_tool *tool = *_tool; + + *_tool = NULL; + + /* Deinitialize Sieve engine */ + sieve_deinit(&tool->svinst); + + /* Free options */ + + if (tool->username != NULL) + i_free(tool->username); + if (tool->homedir != NULL) + i_free(tool->homedir); + + if (tool->sieve_extensions != NULL) + i_free(tool->sieve_extensions); + array_free(&tool->sieve_plugins); + + /* Free raw mail */ + + if (tool->mail_raw != NULL) + mail_raw_close(&tool->mail_raw); + + if (tool->mail_raw_user != NULL) + mail_user_unref(&tool->mail_raw_user); + + /* Free mail service */ + + if (tool->mail_user != NULL) + mail_user_unref(&tool->mail_user); + if (tool->mail_user_dovecot != NULL) + mail_user_unref(&tool->mail_user_dovecot); + + mail_storage_service_user_unref(&tool->service_user); + mail_storage_service_deinit(&tool->storage_service); + + /* Free sieve tool object */ + + i_free(tool->name); + i_free(tool); + + /* Deinitialize service */ + master_service_deinit(&master_service); +} + +/* + * Mail environment + */ + +void sieve_tool_init_mail_user(struct sieve_tool *tool, + const char *mail_location) +{ + struct mail_user *mail_user_dovecot = tool->mail_user_dovecot; + const char *username = tool->username; + struct mail_namespace *ns = NULL; + const char *home = NULL, *errstr = NULL; + + tool->mail_user = mail_user_alloc(NULL, username, + mail_user_dovecot->set_info, + mail_user_dovecot->unexpanded_set); + + if ((home = sieve_tool_get_homedir(sieve_tool)) != NULL) + mail_user_set_home(tool->mail_user, home); + + if (mail_user_init(tool->mail_user, &errstr) < 0) + i_fatal("Test user initialization failed: %s", errstr); + + if (mail_namespaces_init_location(tool->mail_user, mail_location, + &errstr) < 0) + i_fatal("Test storage creation failed: %s", errstr); + + ns = tool->mail_user->namespaces; + ns->flags |= NAMESPACE_FLAG_NOQUOTA | NAMESPACE_FLAG_NOACL; +} + +static void sieve_tool_init_mail_raw_user(struct sieve_tool *tool) +{ + if (tool->mail_raw_user == NULL) { + tool->mail_raw_user = mail_raw_user_create( + master_service, tool->mail_user_dovecot); + } +} + +struct mail * +sieve_tool_open_file_as_mail(struct sieve_tool *tool, const char *path) +{ + sieve_tool_init_mail_raw_user(tool); + + if (tool->mail_raw != NULL) + mail_raw_close(&tool->mail_raw); + + tool->mail_raw = mail_raw_open_file(tool->mail_raw_user, path); + + return tool->mail_raw->mail; +} + +struct mail * +sieve_tool_open_data_as_mail(struct sieve_tool *tool, string_t *mail_data) +{ + sieve_tool_init_mail_raw_user(tool); + + if (tool->mail_raw != NULL) + mail_raw_close(&tool->mail_raw); + + tool->mail_raw = mail_raw_open_data(tool->mail_raw_user, mail_data); + + return tool->mail_raw->mail; +} + +/* + * Configuration + */ + +void sieve_tool_set_homedir(struct sieve_tool *tool, const char *homedir) +{ + if (tool->homedir != NULL) { + if (strcmp(homedir, tool->homedir) == 0) + return; + + i_free(tool->homedir); + } + + tool->homedir = i_strdup(homedir); + + if (tool->mail_user_dovecot != NULL) + mail_user_set_home(tool->mail_user_dovecot, tool->homedir); + if (tool->mail_user != NULL) + mail_user_set_home(tool->mail_user, tool->homedir); +} + +void sieve_tool_set_setting_callback(struct sieve_tool *tool, + sieve_tool_setting_callback_t callback, + void *context) +{ + tool->setting_callback = callback; + tool->setting_callback_context = context; +} + +/* + * Accessors + */ + +const char *sieve_tool_get_username(struct sieve_tool *tool) +{ + const char *username; + + if (tool->username == NULL) { + sieve_tool_get_user_data(&username, NULL); + return username; + } + + return tool->username; +} + +const char *sieve_tool_get_homedir(struct sieve_tool *tool) +{ + const char *homedir = NULL; + + if (tool->homedir != NULL) + return tool->homedir; + + if (tool->mail_user_dovecot != NULL && + mail_user_get_home(tool->mail_user_dovecot, &homedir) > 0) + return tool->homedir; + + sieve_tool_get_user_data(NULL, &homedir); + return homedir; +} + +struct mail_user *sieve_tool_get_mail_user(struct sieve_tool *tool) +{ + return (tool->mail_user == NULL ? + tool->mail_user_dovecot : tool->mail_user); +} + +struct mail_user *sieve_tool_get_mail_raw_user(struct sieve_tool *tool) +{ + sieve_tool_init_mail_raw_user(tool); + return tool->mail_raw_user; +} + +/* + * Commonly needed functionality + */ + +static const struct smtp_address * +sieve_tool_get_address(struct mail *mail, const char *header) +{ + struct message_address *addr; + struct smtp_address *smtp_addr; + const char *str; + + if (mail_get_first_header(mail, header, &str) <= 0) + return NULL; + addr = message_address_parse(pool_datastack_create(), + (const unsigned char *)str, + strlen(str), 1, 0); + if (addr == NULL || addr->mailbox == NULL || + addr->domain == NULL || *addr->mailbox == '\0' || + *addr->domain == '\0') + return NULL; + if (smtp_address_create_from_msg_temp(addr, &smtp_addr) < 0) + return NULL; + return smtp_addr; +} + +void sieve_tool_get_envelope_data(struct sieve_message_data *msgdata, + struct mail *mail, + const struct smtp_address *sender, + const struct smtp_address *rcpt_orig, + const struct smtp_address *rcpt_final) +{ + struct smtp_params_rcpt *rcpt_params; + + /* Get sender address */ + if (sender == NULL) + sender = sieve_tool_get_address(mail, "Return-path"); + if (sender == NULL) + sender = sieve_tool_get_address(mail, "Sender"); + if (sender == NULL) + sender = sieve_tool_get_address(mail, "From"); + if (sender == NULL) + sender = smtp_address_create_temp("sender", "example.com"); + + /* Get recipient address */ + if (rcpt_final == NULL) + rcpt_final = sieve_tool_get_address(mail, "Envelope-To"); + if (rcpt_final == NULL) + rcpt_final = sieve_tool_get_address(mail, "To"); + if (rcpt_final == NULL) { + rcpt_final = smtp_address_create_temp("recipient", + "example.com"); + } + if (rcpt_orig == NULL) + rcpt_orig = rcpt_final; + + msgdata->envelope.mail_from = sender; + msgdata->envelope.rcpt_to = rcpt_final; + + rcpt_params = t_new(struct smtp_params_rcpt, 1); + rcpt_params->orcpt.addr = rcpt_orig; + + msgdata->envelope.rcpt_params = rcpt_params; +} + +/* + * File I/O + */ + +struct ostream *sieve_tool_open_output_stream(const char *filename) +{ + struct ostream *outstream; + int fd; + + if (strcmp(filename, "-") == 0) + outstream = o_stream_create_fd(1, 0); + else { + if ((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, + 0600)) < 0) + i_fatal("failed to open file for writing: %m"); + + outstream = o_stream_create_fd_autoclose(&fd, 0); + } + + return outstream; +} + +/* + * Sieve script handling + */ + +struct sieve_binary * +sieve_tool_script_compile(struct sieve_instance *svinst, + const char *filename, const char *name) +{ + struct sieve_error_handler *ehandler; + struct sieve_binary *sbin; + + ehandler = sieve_stderr_ehandler_create(svinst, 0); + sieve_error_handler_accept_infolog(ehandler, TRUE); + sieve_error_handler_accept_debuglog(ehandler, svinst->debug); + + if ((sbin = sieve_compile(svinst, filename, name, ehandler, + 0, NULL)) == NULL) + i_fatal("failed to compile sieve script '%s'", filename); + + sieve_error_handler_unref(&ehandler); + return sbin; +} + +struct sieve_binary * +sieve_tool_script_open(struct sieve_instance *svinst, const char *filename) +{ + struct sieve_error_handler *ehandler; + struct sieve_binary *sbin; + + ehandler = sieve_stderr_ehandler_create(svinst, 0); + sieve_error_handler_accept_infolog(ehandler, TRUE); + sieve_error_handler_accept_debuglog(ehandler, svinst->debug); + + if ((sbin = sieve_open(svinst, filename, NULL, ehandler, + 0, NULL)) == NULL) { + sieve_error_handler_unref(&ehandler); + i_fatal("failed to compile sieve script"); + } + + sieve_error_handler_unref(&ehandler); + + sieve_save(sbin, FALSE, NULL); + return sbin; +} + +void sieve_tool_dump_binary_to(struct sieve_binary *sbin, + const char *filename, bool hexdump) +{ + struct ostream *dumpstream; + + if (filename == NULL) + return; + + dumpstream = sieve_tool_open_output_stream(filename); + if (dumpstream != NULL) { + if (hexdump) + (void)sieve_hexdump(sbin, dumpstream); + else + (void)sieve_dump(sbin, dumpstream, FALSE); + if (o_stream_finish(dumpstream) < 0) { + i_fatal("write(%s) failed: %s", filename, + o_stream_get_error(dumpstream)); + } + o_stream_destroy(&dumpstream); + } else { + i_fatal("Failed to create stream for sieve code dump."); + } +} + +/* + * Commandline option parsing + */ + +void sieve_tool_parse_trace_option(struct sieve_trace_config *tr_config, + const char *tr_option) +{ + if (str_begins(tr_option, "level=")) { + const char *lvl = &tr_option[6]; + + if (strcmp(lvl, "none") == 0) { + tr_config->level = SIEVE_TRLVL_NONE; + } else if (strcmp(lvl, "actions") == 0) { + tr_config->level = SIEVE_TRLVL_ACTIONS; + } else if (strcmp(lvl, "commands") == 0) { + tr_config->level = SIEVE_TRLVL_COMMANDS; + } else if (strcmp(lvl, "tests") == 0) { + tr_config->level = SIEVE_TRLVL_TESTS; + } else if (strcmp(lvl, "matching") == 0) { + tr_config->level = SIEVE_TRLVL_MATCHING; + } else { + i_fatal_status(EX_USAGE, + "Unknown -tlevel= trace level: %s", lvl); + } + } else if (strcmp(tr_option, "debug") == 0) { + tr_config->flags |= SIEVE_TRFLG_DEBUG; + } else if (strcmp(tr_option, "addresses") == 0) { + tr_config->flags |= SIEVE_TRFLG_ADDRESSES; + } else { + i_fatal_status(EX_USAGE, "Unknown -t trace option value: %s", + tr_option); + } +} diff --git a/pigeonhole/src/lib-sieve-tool/sieve-tool.h b/pigeonhole/src/lib-sieve-tool/sieve-tool.h new file mode 100644 index 0000000..02f4198 --- /dev/null +++ b/pigeonhole/src/lib-sieve-tool/sieve-tool.h @@ -0,0 +1,100 @@ +#ifndef SIEVE_TOOL_H +#define SIEVE_TOOL_H + +#include "sieve-common.h" + +/* + * Types + */ + +typedef const char * +(*sieve_tool_setting_callback_t)(void *context, const char *identifier); + +/* + * Global variables + */ + +extern struct sieve_tool *sieve_tool; + +/* + * Initialization + */ + +struct sieve_tool * +sieve_tool_init(const char *name, int *argc, char **argv[], + const char *getopt_str, bool no_config); + +int sieve_tool_getopt(struct sieve_tool *tool); + +struct sieve_instance * +sieve_tool_init_finish(struct sieve_tool *tool, bool init_mailstore, + bool preserve_root); + +void sieve_tool_deinit(struct sieve_tool **_tool); + +/* + * Mail environment + */ + +void sieve_tool_init_mail_user(struct sieve_tool *tool, + const char *mail_location); + +struct mail * +sieve_tool_open_file_as_mail(struct sieve_tool *tool, const char *path); +struct mail * +sieve_tool_open_data_as_mail(struct sieve_tool *tool, string_t *mail_data); + +/* + * Accessors + */ + +const char *sieve_tool_get_username(struct sieve_tool *tool); +const char *sieve_tool_get_homedir(struct sieve_tool *tool); +struct mail_user *sieve_tool_get_mail_user(struct sieve_tool *tool); +struct mail_user *sieve_tool_get_mail_raw_user(struct sieve_tool *tool); + +/* + * Configuration + */ + +void sieve_tool_set_homedir(struct sieve_tool *tool, const char *homedir); +void sieve_tool_set_setting_callback(struct sieve_tool *tool, + sieve_tool_setting_callback_t callback, + void *context); + +/* + * Commonly needed functionality + */ + +void sieve_tool_get_envelope_data(struct sieve_message_data *msgdata, + struct mail *mail, + const struct smtp_address *sender, + const struct smtp_address *rcpt_orig, + const struct smtp_address *rcpt_final); + +/* + * File I/O + */ + +struct ostream *sieve_tool_open_output_stream(const char *filename); + +/* + * Sieve script handling + */ + +struct sieve_binary * +sieve_tool_script_compile(struct sieve_instance *svinst, + const char *filename, const char *name); +struct sieve_binary * +sieve_tool_script_open(struct sieve_instance *svinst, const char *filename); +void sieve_tool_dump_binary_to(struct sieve_binary *sbin, + const char *filename, bool hexdump); + +/* + * Command line option parsing + */ + +void sieve_tool_parse_trace_option(struct sieve_trace_config *tr_config, + const char *tr_option); + +#endif diff --git a/pigeonhole/src/lib-sieve/Makefile.am b/pigeonhole/src/lib-sieve/Makefile.am new file mode 100644 index 0000000..2e80871 --- /dev/null +++ b/pigeonhole/src/lib-sieve/Makefile.am @@ -0,0 +1,188 @@ +SUBDIRS = util storage plugins + +dovecot_pkglib_LTLIBRARIES = libdovecot-sieve.la + +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_SERVICE_INCLUDE) \ + -I$(top_srcdir)/src/lib-sieve/util \ + -DMODULEDIR=\""$(dovecot_moduledir)"\" + +tests = \ + tst-truefalse.c \ + tst-not.c \ + tst-anyof.c \ + tst-allof.c \ + tst-address.c \ + tst-header.c \ + tst-exists.c \ + tst-size.c + +commands = \ + cmd-require.c \ + cmd-stop.c \ + cmd-if.c \ + cmd-keep.c \ + cmd-redirect.c \ + cmd-discard.c + +extensions = \ + ext-fileinto.c \ + ext-reject.c \ + ext-envelope.c \ + ext-encoded-character.c + +match_types = \ + mcht-is.c \ + mcht-contains.c \ + mcht-matches.c + +comparators = \ + cmp-i-octet.c \ + cmp-i-ascii-casemap.c + +if BUILD_UNFINISHED +unfinished_storages = +unfinished_plugins = +endif + +strgdir = $(top_builddir)/src/lib-sieve/storage +storages = \ + $(strgdir)/data/libsieve_storage_data.la \ + $(strgdir)/file/libsieve_storage_file.la \ + $(strgdir)/dict/libsieve_storage_dict.la \ + $(strgdir)/ldap/libsieve_storage_ldap.la \ + $(unfinished_storages) + +extdir = $(top_builddir)/src/lib-sieve/plugins +plugins = \ + $(extdir)/vacation/libsieve_ext_vacation.la \ + $(extdir)/subaddress/libsieve_ext_subaddress.la \ + $(extdir)/comparator-i-ascii-numeric/libsieve_ext_comparator-i-ascii-numeric.la \ + $(extdir)/relational/libsieve_ext_relational.la \ + $(extdir)/regex/libsieve_ext_regex.la \ + $(extdir)/copy/libsieve_ext_copy.la \ + $(extdir)/imap4flags/libsieve_ext_imap4flags.la \ + $(extdir)/include/libsieve_ext_include.la \ + $(extdir)/body/libsieve_ext_body.la \ + $(extdir)/variables/libsieve_ext_variables.la \ + $(extdir)/enotify/libsieve_ext_enotify.la \ + $(extdir)/notify/libsieve_ext_notify.la \ + $(extdir)/environment/libsieve_ext_environment.la \ + $(extdir)/mailbox/libsieve_ext_mailbox.la \ + $(extdir)/date/libsieve_ext_date.la \ + $(extdir)/spamvirustest/libsieve_ext_spamvirustest.la \ + $(extdir)/ihave/libsieve_ext_ihave.la \ + $(extdir)/editheader/libsieve_ext_editheader.la \ + $(extdir)/duplicate/libsieve_ext_duplicate.la \ + $(extdir)/index/libsieve_ext_index.la \ + $(extdir)/metadata/libsieve_ext_metadata.la \ + $(extdir)/mime/libsieve_ext_mime.la \ + $(extdir)/special-use/libsieve_ext_special_use.la \ + $(extdir)/vnd.dovecot/debug/libsieve_ext_debug.la \ + $(extdir)/vnd.dovecot/environment/libsieve_ext_vnd_environment.la \ + $(extdir)/vnd.dovecot/report/libsieve_ext_vnd_report.la \ + $(unfinished_plugins) + +libdovecot_sieve_la_DEPENDENCIES = \ + $(storages) \ + $(plugins) \ + $(top_builddir)/src/lib-sieve/util/libsieve_util.la \ + $(LIBDOVECOT_STORAGE_DEPS) \ + $(LIBDOVECOT_DEPS) +libdovecot_sieve_la_LIBADD = \ + $(storages) \ + $(plugins) \ + $(top_builddir)/src/lib-sieve/util/libsieve_util.la \ + $(LIBDOVECOT_STORAGE) \ + $(LIBDOVECOT) + +libdovecot_sieve_la_SOURCES = \ + sieve-settings.c \ + sieve-message.c \ + sieve-smtp.c \ + sieve-lexer.c \ + sieve-script.c \ + sieve-storage.c \ + sieve-storage-sync.c \ + sieve-ast.c \ + sieve-binary.c \ + sieve-binary-file.c \ + sieve-binary-code.c \ + sieve-binary-debug.c \ + sieve-parser.c \ + sieve-address.c \ + sieve-validator.c \ + sieve-generator.c \ + sieve-execute.c \ + sieve-interpreter.c \ + sieve-runtime-trace.c \ + sieve-code-dumper.c \ + sieve-binary-dumper.c \ + sieve-result.c \ + sieve-error.c \ + sieve-objects.c \ + sieve-stringlist.c \ + sieve-comparators.c \ + sieve-match-types.c \ + sieve-address-parts.c \ + sieve-address-source.c \ + sieve-match.c \ + sieve-commands.c \ + sieve-code.c \ + sieve-actions.c \ + sieve-extensions.c \ + sieve-plugins.c \ + $(comparators) \ + $(match_types) \ + $(tests) \ + $(commands) \ + $(extensions) \ + sieve.c + +headers = \ + sieve-config.h \ + sieve-types.h \ + sieve-common.h \ + sieve-limits.h \ + sieve-settings.h \ + sieve-message.h \ + sieve-smtp.h \ + sieve-lexer.h \ + sieve-script.h \ + sieve-script-private.h \ + sieve-storage.h \ + sieve-storage-private.h \ + sieve-ast.h \ + sieve-binary.h \ + sieve-binary-private.h \ + sieve-parser.h \ + sieve-address.h \ + sieve-validator.h \ + sieve-generator.h \ + sieve-execute.h \ + sieve-interpreter.h \ + sieve-runtime-trace.h \ + sieve-runtime.h \ + sieve-code-dumper.h \ + sieve-binary-dumper.h \ + sieve-dump.h \ + sieve-result.h \ + sieve-error.h \ + sieve-error-private.h \ + sieve-objects.h \ + sieve-stringlist.h \ + sieve-match.h \ + sieve-comparators.h \ + sieve-match-types.h \ + sieve-address-parts.h \ + sieve-address-source.h \ + sieve-commands.h \ + sieve-code.h \ + sieve-actions.h \ + sieve-extensions.h \ + sieve-plugins.h \ + sieve.h + +pkginc_libdir=$(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(headers) diff --git a/pigeonhole/src/lib-sieve/Makefile.in b/pigeonhole/src/lib-sieve/Makefile.in new file mode 100644 index 0000000..104d4df --- /dev/null +++ b/pigeonhole/src/lib-sieve/Makefile.in @@ -0,0 +1,1311 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(pkginc_lib_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(dovecot_pkglibdir)" \ + "$(DESTDIR)$(pkginc_libdir)" +LTLIBRARIES = $(dovecot_pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +am__DEPENDENCIES_2 = $(strgdir)/data/libsieve_storage_data.la \ + $(strgdir)/file/libsieve_storage_file.la \ + $(strgdir)/dict/libsieve_storage_dict.la \ + $(strgdir)/ldap/libsieve_storage_ldap.la $(am__DEPENDENCIES_1) +am__DEPENDENCIES_3 = $(extdir)/vacation/libsieve_ext_vacation.la \ + $(extdir)/subaddress/libsieve_ext_subaddress.la \ + $(extdir)/comparator-i-ascii-numeric/libsieve_ext_comparator-i-ascii-numeric.la \ + $(extdir)/relational/libsieve_ext_relational.la \ + $(extdir)/regex/libsieve_ext_regex.la \ + $(extdir)/copy/libsieve_ext_copy.la \ + $(extdir)/imap4flags/libsieve_ext_imap4flags.la \ + $(extdir)/include/libsieve_ext_include.la \ + $(extdir)/body/libsieve_ext_body.la \ + $(extdir)/variables/libsieve_ext_variables.la \ + $(extdir)/enotify/libsieve_ext_enotify.la \ + $(extdir)/notify/libsieve_ext_notify.la \ + $(extdir)/environment/libsieve_ext_environment.la \ + $(extdir)/mailbox/libsieve_ext_mailbox.la \ + $(extdir)/date/libsieve_ext_date.la \ + $(extdir)/spamvirustest/libsieve_ext_spamvirustest.la \ + $(extdir)/ihave/libsieve_ext_ihave.la \ + $(extdir)/editheader/libsieve_ext_editheader.la \ + $(extdir)/duplicate/libsieve_ext_duplicate.la \ + $(extdir)/index/libsieve_ext_index.la \ + $(extdir)/metadata/libsieve_ext_metadata.la \ + $(extdir)/mime/libsieve_ext_mime.la \ + $(extdir)/special-use/libsieve_ext_special_use.la \ + $(extdir)/vnd.dovecot/debug/libsieve_ext_debug.la \ + $(extdir)/vnd.dovecot/environment/libsieve_ext_vnd_environment.la \ + $(extdir)/vnd.dovecot/report/libsieve_ext_vnd_report.la \ + $(am__DEPENDENCIES_1) +am__objects_1 = cmp-i-octet.lo cmp-i-ascii-casemap.lo +am__objects_2 = mcht-is.lo mcht-contains.lo mcht-matches.lo +am__objects_3 = tst-truefalse.lo tst-not.lo tst-anyof.lo tst-allof.lo \ + tst-address.lo tst-header.lo tst-exists.lo tst-size.lo +am__objects_4 = cmd-require.lo cmd-stop.lo cmd-if.lo cmd-keep.lo \ + cmd-redirect.lo cmd-discard.lo +am__objects_5 = ext-fileinto.lo ext-reject.lo ext-envelope.lo \ + ext-encoded-character.lo +am_libdovecot_sieve_la_OBJECTS = sieve-settings.lo sieve-message.lo \ + sieve-smtp.lo sieve-lexer.lo sieve-script.lo sieve-storage.lo \ + sieve-storage-sync.lo sieve-ast.lo sieve-binary.lo \ + sieve-binary-file.lo sieve-binary-code.lo \ + sieve-binary-debug.lo sieve-parser.lo sieve-address.lo \ + sieve-validator.lo sieve-generator.lo sieve-execute.lo \ + sieve-interpreter.lo sieve-runtime-trace.lo \ + sieve-code-dumper.lo sieve-binary-dumper.lo sieve-result.lo \ + sieve-error.lo sieve-objects.lo sieve-stringlist.lo \ + sieve-comparators.lo sieve-match-types.lo \ + sieve-address-parts.lo sieve-address-source.lo sieve-match.lo \ + sieve-commands.lo sieve-code.lo sieve-actions.lo \ + sieve-extensions.lo sieve-plugins.lo $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) $(am__objects_4) \ + $(am__objects_5) sieve.lo +libdovecot_sieve_la_OBJECTS = $(am_libdovecot_sieve_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/cmd-discard.Plo \ + ./$(DEPDIR)/cmd-if.Plo ./$(DEPDIR)/cmd-keep.Plo \ + ./$(DEPDIR)/cmd-redirect.Plo ./$(DEPDIR)/cmd-require.Plo \ + ./$(DEPDIR)/cmd-stop.Plo ./$(DEPDIR)/cmp-i-ascii-casemap.Plo \ + ./$(DEPDIR)/cmp-i-octet.Plo \ + ./$(DEPDIR)/ext-encoded-character.Plo \ + ./$(DEPDIR)/ext-envelope.Plo ./$(DEPDIR)/ext-fileinto.Plo \ + ./$(DEPDIR)/ext-reject.Plo ./$(DEPDIR)/mcht-contains.Plo \ + ./$(DEPDIR)/mcht-is.Plo ./$(DEPDIR)/mcht-matches.Plo \ + ./$(DEPDIR)/sieve-actions.Plo \ + ./$(DEPDIR)/sieve-address-parts.Plo \ + ./$(DEPDIR)/sieve-address-source.Plo \ + ./$(DEPDIR)/sieve-address.Plo ./$(DEPDIR)/sieve-ast.Plo \ + ./$(DEPDIR)/sieve-binary-code.Plo \ + ./$(DEPDIR)/sieve-binary-debug.Plo \ + ./$(DEPDIR)/sieve-binary-dumper.Plo \ + ./$(DEPDIR)/sieve-binary-file.Plo ./$(DEPDIR)/sieve-binary.Plo \ + ./$(DEPDIR)/sieve-code-dumper.Plo ./$(DEPDIR)/sieve-code.Plo \ + ./$(DEPDIR)/sieve-commands.Plo \ + ./$(DEPDIR)/sieve-comparators.Plo ./$(DEPDIR)/sieve-error.Plo \ + ./$(DEPDIR)/sieve-execute.Plo ./$(DEPDIR)/sieve-extensions.Plo \ + ./$(DEPDIR)/sieve-generator.Plo \ + ./$(DEPDIR)/sieve-interpreter.Plo ./$(DEPDIR)/sieve-lexer.Plo \ + ./$(DEPDIR)/sieve-match-types.Plo ./$(DEPDIR)/sieve-match.Plo \ + ./$(DEPDIR)/sieve-message.Plo ./$(DEPDIR)/sieve-objects.Plo \ + ./$(DEPDIR)/sieve-parser.Plo ./$(DEPDIR)/sieve-plugins.Plo \ + ./$(DEPDIR)/sieve-result.Plo \ + ./$(DEPDIR)/sieve-runtime-trace.Plo \ + ./$(DEPDIR)/sieve-script.Plo ./$(DEPDIR)/sieve-settings.Plo \ + ./$(DEPDIR)/sieve-smtp.Plo ./$(DEPDIR)/sieve-storage-sync.Plo \ + ./$(DEPDIR)/sieve-storage.Plo ./$(DEPDIR)/sieve-stringlist.Plo \ + ./$(DEPDIR)/sieve-validator.Plo ./$(DEPDIR)/sieve.Plo \ + ./$(DEPDIR)/tst-address.Plo ./$(DEPDIR)/tst-allof.Plo \ + ./$(DEPDIR)/tst-anyof.Plo ./$(DEPDIR)/tst-exists.Plo \ + ./$(DEPDIR)/tst-header.Plo ./$(DEPDIR)/tst-not.Plo \ + ./$(DEPDIR)/tst-size.Plo ./$(DEPDIR)/tst-truefalse.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libdovecot_sieve_la_SOURCES) +DIST_SOURCES = $(libdovecot_sieve_la_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(pkginc_lib_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = util storage plugins +dovecot_pkglib_LTLIBRARIES = libdovecot-sieve.la +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_SERVICE_INCLUDE) \ + -I$(top_srcdir)/src/lib-sieve/util \ + -DMODULEDIR=\""$(dovecot_moduledir)"\" + +tests = \ + tst-truefalse.c \ + tst-not.c \ + tst-anyof.c \ + tst-allof.c \ + tst-address.c \ + tst-header.c \ + tst-exists.c \ + tst-size.c + +commands = \ + cmd-require.c \ + cmd-stop.c \ + cmd-if.c \ + cmd-keep.c \ + cmd-redirect.c \ + cmd-discard.c + +extensions = \ + ext-fileinto.c \ + ext-reject.c \ + ext-envelope.c \ + ext-encoded-character.c + +match_types = \ + mcht-is.c \ + mcht-contains.c \ + mcht-matches.c + +comparators = \ + cmp-i-octet.c \ + cmp-i-ascii-casemap.c + +@BUILD_UNFINISHED_TRUE@unfinished_storages = +@BUILD_UNFINISHED_TRUE@unfinished_plugins = +strgdir = $(top_builddir)/src/lib-sieve/storage +storages = \ + $(strgdir)/data/libsieve_storage_data.la \ + $(strgdir)/file/libsieve_storage_file.la \ + $(strgdir)/dict/libsieve_storage_dict.la \ + $(strgdir)/ldap/libsieve_storage_ldap.la \ + $(unfinished_storages) + +extdir = $(top_builddir)/src/lib-sieve/plugins +plugins = \ + $(extdir)/vacation/libsieve_ext_vacation.la \ + $(extdir)/subaddress/libsieve_ext_subaddress.la \ + $(extdir)/comparator-i-ascii-numeric/libsieve_ext_comparator-i-ascii-numeric.la \ + $(extdir)/relational/libsieve_ext_relational.la \ + $(extdir)/regex/libsieve_ext_regex.la \ + $(extdir)/copy/libsieve_ext_copy.la \ + $(extdir)/imap4flags/libsieve_ext_imap4flags.la \ + $(extdir)/include/libsieve_ext_include.la \ + $(extdir)/body/libsieve_ext_body.la \ + $(extdir)/variables/libsieve_ext_variables.la \ + $(extdir)/enotify/libsieve_ext_enotify.la \ + $(extdir)/notify/libsieve_ext_notify.la \ + $(extdir)/environment/libsieve_ext_environment.la \ + $(extdir)/mailbox/libsieve_ext_mailbox.la \ + $(extdir)/date/libsieve_ext_date.la \ + $(extdir)/spamvirustest/libsieve_ext_spamvirustest.la \ + $(extdir)/ihave/libsieve_ext_ihave.la \ + $(extdir)/editheader/libsieve_ext_editheader.la \ + $(extdir)/duplicate/libsieve_ext_duplicate.la \ + $(extdir)/index/libsieve_ext_index.la \ + $(extdir)/metadata/libsieve_ext_metadata.la \ + $(extdir)/mime/libsieve_ext_mime.la \ + $(extdir)/special-use/libsieve_ext_special_use.la \ + $(extdir)/vnd.dovecot/debug/libsieve_ext_debug.la \ + $(extdir)/vnd.dovecot/environment/libsieve_ext_vnd_environment.la \ + $(extdir)/vnd.dovecot/report/libsieve_ext_vnd_report.la \ + $(unfinished_plugins) + +libdovecot_sieve_la_DEPENDENCIES = \ + $(storages) \ + $(plugins) \ + $(top_builddir)/src/lib-sieve/util/libsieve_util.la \ + $(LIBDOVECOT_STORAGE_DEPS) \ + $(LIBDOVECOT_DEPS) + +libdovecot_sieve_la_LIBADD = \ + $(storages) \ + $(plugins) \ + $(top_builddir)/src/lib-sieve/util/libsieve_util.la \ + $(LIBDOVECOT_STORAGE) \ + $(LIBDOVECOT) + +libdovecot_sieve_la_SOURCES = \ + sieve-settings.c \ + sieve-message.c \ + sieve-smtp.c \ + sieve-lexer.c \ + sieve-script.c \ + sieve-storage.c \ + sieve-storage-sync.c \ + sieve-ast.c \ + sieve-binary.c \ + sieve-binary-file.c \ + sieve-binary-code.c \ + sieve-binary-debug.c \ + sieve-parser.c \ + sieve-address.c \ + sieve-validator.c \ + sieve-generator.c \ + sieve-execute.c \ + sieve-interpreter.c \ + sieve-runtime-trace.c \ + sieve-code-dumper.c \ + sieve-binary-dumper.c \ + sieve-result.c \ + sieve-error.c \ + sieve-objects.c \ + sieve-stringlist.c \ + sieve-comparators.c \ + sieve-match-types.c \ + sieve-address-parts.c \ + sieve-address-source.c \ + sieve-match.c \ + sieve-commands.c \ + sieve-code.c \ + sieve-actions.c \ + sieve-extensions.c \ + sieve-plugins.c \ + $(comparators) \ + $(match_types) \ + $(tests) \ + $(commands) \ + $(extensions) \ + sieve.c + +headers = \ + sieve-config.h \ + sieve-types.h \ + sieve-common.h \ + sieve-limits.h \ + sieve-settings.h \ + sieve-message.h \ + sieve-smtp.h \ + sieve-lexer.h \ + sieve-script.h \ + sieve-script-private.h \ + sieve-storage.h \ + sieve-storage-private.h \ + sieve-ast.h \ + sieve-binary.h \ + sieve-binary-private.h \ + sieve-parser.h \ + sieve-address.h \ + sieve-validator.h \ + sieve-generator.h \ + sieve-execute.h \ + sieve-interpreter.h \ + sieve-runtime-trace.h \ + sieve-runtime.h \ + sieve-code-dumper.h \ + sieve-binary-dumper.h \ + sieve-dump.h \ + sieve-result.h \ + sieve-error.h \ + sieve-error-private.h \ + sieve-objects.h \ + sieve-stringlist.h \ + sieve-match.h \ + sieve-comparators.h \ + sieve-match-types.h \ + sieve-address-parts.h \ + sieve-address-source.h \ + sieve-commands.h \ + sieve-code.h \ + sieve-actions.h \ + sieve-extensions.h \ + sieve-plugins.h \ + sieve.h + +pkginc_libdir = $(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(headers) +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-dovecot_pkglibLTLIBRARIES: $(dovecot_pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(dovecot_pkglib_LTLIBRARIES)'; test -n "$(dovecot_pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(dovecot_pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(dovecot_pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(dovecot_pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(dovecot_pkglibdir)"; \ + } + +uninstall-dovecot_pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(dovecot_pkglib_LTLIBRARIES)'; test -n "$(dovecot_pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(dovecot_pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(dovecot_pkglibdir)/$$f"; \ + done + +clean-dovecot_pkglibLTLIBRARIES: + -test -z "$(dovecot_pkglib_LTLIBRARIES)" || rm -f $(dovecot_pkglib_LTLIBRARIES) + @list='$(dovecot_pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libdovecot-sieve.la: $(libdovecot_sieve_la_OBJECTS) $(libdovecot_sieve_la_DEPENDENCIES) $(EXTRA_libdovecot_sieve_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) -rpath $(dovecot_pkglibdir) $(libdovecot_sieve_la_OBJECTS) $(libdovecot_sieve_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-discard.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-if.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-keep.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-redirect.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-require.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-stop.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmp-i-ascii-casemap.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmp-i-octet.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-encoded-character.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-envelope.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-fileinto.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-reject.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcht-contains.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcht-is.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcht-matches.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-actions.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-address-parts.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-address-source.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-address.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-ast.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-binary-code.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-binary-debug.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-binary-dumper.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-binary-file.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-binary.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-code-dumper.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-code.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-commands.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-comparators.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-error.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-execute.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-extensions.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-generator.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-interpreter.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-lexer.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-match-types.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-match.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-message.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-objects.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-parser.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-plugins.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-result.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-runtime-trace.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-script.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-settings.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-smtp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-storage-sync.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-storage.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-stringlist.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-validator.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-address.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-allof.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-anyof.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-exists.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-header.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-not.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-size.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-truefalse.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkginc_libHEADERS: $(pkginc_lib_HEADERS) + @$(NORMAL_INSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkginc_libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkginc_libdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkginc_libdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkginc_libdir)" || exit $$?; \ + done + +uninstall-pkginc_libHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkginc_libdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(dovecot_pkglibdir)" "$(DESTDIR)$(pkginc_libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-dovecot_pkglibLTLIBRARIES clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-recursive + -rm -f ./$(DEPDIR)/cmd-discard.Plo + -rm -f ./$(DEPDIR)/cmd-if.Plo + -rm -f ./$(DEPDIR)/cmd-keep.Plo + -rm -f ./$(DEPDIR)/cmd-redirect.Plo + -rm -f ./$(DEPDIR)/cmd-require.Plo + -rm -f ./$(DEPDIR)/cmd-stop.Plo + -rm -f ./$(DEPDIR)/cmp-i-ascii-casemap.Plo + -rm -f ./$(DEPDIR)/cmp-i-octet.Plo + -rm -f ./$(DEPDIR)/ext-encoded-character.Plo + -rm -f ./$(DEPDIR)/ext-envelope.Plo + -rm -f ./$(DEPDIR)/ext-fileinto.Plo + -rm -f ./$(DEPDIR)/ext-reject.Plo + -rm -f ./$(DEPDIR)/mcht-contains.Plo + -rm -f ./$(DEPDIR)/mcht-is.Plo + -rm -f ./$(DEPDIR)/mcht-matches.Plo + -rm -f ./$(DEPDIR)/sieve-actions.Plo + -rm -f ./$(DEPDIR)/sieve-address-parts.Plo + -rm -f ./$(DEPDIR)/sieve-address-source.Plo + -rm -f ./$(DEPDIR)/sieve-address.Plo + -rm -f ./$(DEPDIR)/sieve-ast.Plo + -rm -f ./$(DEPDIR)/sieve-binary-code.Plo + -rm -f ./$(DEPDIR)/sieve-binary-debug.Plo + -rm -f ./$(DEPDIR)/sieve-binary-dumper.Plo + -rm -f ./$(DEPDIR)/sieve-binary-file.Plo + -rm -f ./$(DEPDIR)/sieve-binary.Plo + -rm -f ./$(DEPDIR)/sieve-code-dumper.Plo + -rm -f ./$(DEPDIR)/sieve-code.Plo + -rm -f ./$(DEPDIR)/sieve-commands.Plo + -rm -f ./$(DEPDIR)/sieve-comparators.Plo + -rm -f ./$(DEPDIR)/sieve-error.Plo + -rm -f ./$(DEPDIR)/sieve-execute.Plo + -rm -f ./$(DEPDIR)/sieve-extensions.Plo + -rm -f ./$(DEPDIR)/sieve-generator.Plo + -rm -f ./$(DEPDIR)/sieve-interpreter.Plo + -rm -f ./$(DEPDIR)/sieve-lexer.Plo + -rm -f ./$(DEPDIR)/sieve-match-types.Plo + -rm -f ./$(DEPDIR)/sieve-match.Plo + -rm -f ./$(DEPDIR)/sieve-message.Plo + -rm -f ./$(DEPDIR)/sieve-objects.Plo + -rm -f ./$(DEPDIR)/sieve-parser.Plo + -rm -f ./$(DEPDIR)/sieve-plugins.Plo + -rm -f ./$(DEPDIR)/sieve-result.Plo + -rm -f ./$(DEPDIR)/sieve-runtime-trace.Plo + -rm -f ./$(DEPDIR)/sieve-script.Plo + -rm -f ./$(DEPDIR)/sieve-settings.Plo + -rm -f ./$(DEPDIR)/sieve-smtp.Plo + -rm -f ./$(DEPDIR)/sieve-storage-sync.Plo + -rm -f ./$(DEPDIR)/sieve-storage.Plo + -rm -f ./$(DEPDIR)/sieve-stringlist.Plo + -rm -f ./$(DEPDIR)/sieve-validator.Plo + -rm -f ./$(DEPDIR)/sieve.Plo + -rm -f ./$(DEPDIR)/tst-address.Plo + -rm -f ./$(DEPDIR)/tst-allof.Plo + -rm -f ./$(DEPDIR)/tst-anyof.Plo + -rm -f ./$(DEPDIR)/tst-exists.Plo + -rm -f ./$(DEPDIR)/tst-header.Plo + -rm -f ./$(DEPDIR)/tst-not.Plo + -rm -f ./$(DEPDIR)/tst-size.Plo + -rm -f ./$(DEPDIR)/tst-truefalse.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-dovecot_pkglibLTLIBRARIES \ + install-pkginc_libHEADERS + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f ./$(DEPDIR)/cmd-discard.Plo + -rm -f ./$(DEPDIR)/cmd-if.Plo + -rm -f ./$(DEPDIR)/cmd-keep.Plo + -rm -f ./$(DEPDIR)/cmd-redirect.Plo + -rm -f ./$(DEPDIR)/cmd-require.Plo + -rm -f ./$(DEPDIR)/cmd-stop.Plo + -rm -f ./$(DEPDIR)/cmp-i-ascii-casemap.Plo + -rm -f ./$(DEPDIR)/cmp-i-octet.Plo + -rm -f ./$(DEPDIR)/ext-encoded-character.Plo + -rm -f ./$(DEPDIR)/ext-envelope.Plo + -rm -f ./$(DEPDIR)/ext-fileinto.Plo + -rm -f ./$(DEPDIR)/ext-reject.Plo + -rm -f ./$(DEPDIR)/mcht-contains.Plo + -rm -f ./$(DEPDIR)/mcht-is.Plo + -rm -f ./$(DEPDIR)/mcht-matches.Plo + -rm -f ./$(DEPDIR)/sieve-actions.Plo + -rm -f ./$(DEPDIR)/sieve-address-parts.Plo + -rm -f ./$(DEPDIR)/sieve-address-source.Plo + -rm -f ./$(DEPDIR)/sieve-address.Plo + -rm -f ./$(DEPDIR)/sieve-ast.Plo + -rm -f ./$(DEPDIR)/sieve-binary-code.Plo + -rm -f ./$(DEPDIR)/sieve-binary-debug.Plo + -rm -f ./$(DEPDIR)/sieve-binary-dumper.Plo + -rm -f ./$(DEPDIR)/sieve-binary-file.Plo + -rm -f ./$(DEPDIR)/sieve-binary.Plo + -rm -f ./$(DEPDIR)/sieve-code-dumper.Plo + -rm -f ./$(DEPDIR)/sieve-code.Plo + -rm -f ./$(DEPDIR)/sieve-commands.Plo + -rm -f ./$(DEPDIR)/sieve-comparators.Plo + -rm -f ./$(DEPDIR)/sieve-error.Plo + -rm -f ./$(DEPDIR)/sieve-execute.Plo + -rm -f ./$(DEPDIR)/sieve-extensions.Plo + -rm -f ./$(DEPDIR)/sieve-generator.Plo + -rm -f ./$(DEPDIR)/sieve-interpreter.Plo + -rm -f ./$(DEPDIR)/sieve-lexer.Plo + -rm -f ./$(DEPDIR)/sieve-match-types.Plo + -rm -f ./$(DEPDIR)/sieve-match.Plo + -rm -f ./$(DEPDIR)/sieve-message.Plo + -rm -f ./$(DEPDIR)/sieve-objects.Plo + -rm -f ./$(DEPDIR)/sieve-parser.Plo + -rm -f ./$(DEPDIR)/sieve-plugins.Plo + -rm -f ./$(DEPDIR)/sieve-result.Plo + -rm -f ./$(DEPDIR)/sieve-runtime-trace.Plo + -rm -f ./$(DEPDIR)/sieve-script.Plo + -rm -f ./$(DEPDIR)/sieve-settings.Plo + -rm -f ./$(DEPDIR)/sieve-smtp.Plo + -rm -f ./$(DEPDIR)/sieve-storage-sync.Plo + -rm -f ./$(DEPDIR)/sieve-storage.Plo + -rm -f ./$(DEPDIR)/sieve-stringlist.Plo + -rm -f ./$(DEPDIR)/sieve-validator.Plo + -rm -f ./$(DEPDIR)/sieve.Plo + -rm -f ./$(DEPDIR)/tst-address.Plo + -rm -f ./$(DEPDIR)/tst-allof.Plo + -rm -f ./$(DEPDIR)/tst-anyof.Plo + -rm -f ./$(DEPDIR)/tst-exists.Plo + -rm -f ./$(DEPDIR)/tst-header.Plo + -rm -f ./$(DEPDIR)/tst-not.Plo + -rm -f ./$(DEPDIR)/tst-size.Plo + -rm -f ./$(DEPDIR)/tst-truefalse.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-dovecot_pkglibLTLIBRARIES \ + uninstall-pkginc_libHEADERS + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--depfiles check check-am clean \ + clean-dovecot_pkglibLTLIBRARIES clean-generic clean-libtool \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dovecot_pkglibLTLIBRARIES \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am \ + install-pkginc_libHEADERS install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-dovecot_pkglibLTLIBRARIES \ + uninstall-pkginc_libHEADERS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/cmd-discard.c b/pigeonhole/src/lib-sieve/cmd-discard.c new file mode 100644 index 0000000..de460ae --- /dev/null +++ b/pigeonhole/src/lib-sieve/cmd-discard.c @@ -0,0 +1,173 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-dump.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +/* + * Discard command + * + * Syntax + * discard + */ + +static bool +cmd_discard_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx ATTR_UNUSED); + +const struct sieve_command_def cmd_discard = { + .identifier = "discard", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .generate = cmd_discard_generate +}; + +/* + * Discard operation + */ + +static bool +cmd_discard_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_discard_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def cmd_discard_operation = { + .mnemonic = "DISCARD", + .code = SIEVE_OPERATION_DISCARD, + .dump = cmd_discard_operation_dump, + .execute = cmd_discard_operation_execute +}; + +/* + * Discard actions + */ + +static bool +act_discard_equals(const struct sieve_script_env *senv, + const struct sieve_action *act1, + const struct sieve_action *act2); +static int +act_discard_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other); +static void +act_discard_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep); +static int +act_discard_execute(const struct sieve_action_exec_env *aenv, void *tr_context, + bool *keep); + +const struct sieve_action_def act_discard = { + .name = "discard", + .equals = act_discard_equals, + .check_duplicate = act_discard_check_duplicate, + .print = act_discard_print, + .execute = act_discard_execute, +}; + +/* + * Code generation + */ + +static bool +cmd_discard_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd ATTR_UNUSED) +{ + sieve_operation_emit(cgenv->sblock, NULL, &cmd_discard_operation); + + return TRUE; +} + +/* + * Code dump + */ + +static bool +cmd_discard_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_code_dumpf(denv, "DISCARD"); + sieve_code_descend(denv); + + return (sieve_action_opr_optional_dump(denv, address, NULL) == 0); +} + +/* + * Interpretation + */ + +static int +cmd_discard_operation_execute(const struct sieve_runtime_env *renv ATTR_UNUSED, + sieve_size_t *address ATTR_UNUSED) +{ + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, + "discard action; cancel implicit keep"); + + if (sieve_result_add_action(renv, NULL, "discard", &act_discard, + NULL, NULL, 0, FALSE) < 0) + return SIEVE_EXEC_FAILURE; + return SIEVE_EXEC_OK; +} + +/* + * Action implementation + */ + +static bool +act_discard_equals(const struct sieve_script_env *senv ATTR_UNUSED, + const struct sieve_action *act1 ATTR_UNUSED, + const struct sieve_action *act2 ATTR_UNUSED) +{ + return TRUE; +} + +static int +act_discard_check_duplicate(const struct sieve_runtime_env *renv ATTR_UNUSED, + const struct sieve_action *act ATTR_UNUSED, + const struct sieve_action *act_other ATTR_UNUSED) +{ + return 1; +} + +static void +act_discard_print(const struct sieve_action *action ATTR_UNUSED, + const struct sieve_result_print_env *rpenv, bool *keep) +{ + sieve_result_action_printf(rpenv, "discard"); + + *keep = FALSE; +} + +static int +act_discard_execute(const struct sieve_action_exec_env *aenv, + void *tr_context ATTR_UNUSED, bool *keep) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + + eenv->exec_status->significant_action_executed = TRUE; + + struct event_passthrough *e = sieve_action_create_finish_event(aenv); + + sieve_result_event_log(aenv, e->event(), + "Marked message to be discarded if not explicitly delivered " + "(discard action)"); + *keep = FALSE; + + return SIEVE_EXEC_OK; +} + diff --git a/pigeonhole/src/lib-sieve/cmd-if.c b/pigeonhole/src/lib-sieve/cmd-if.c new file mode 100644 index 0000000..2ae186e --- /dev/null +++ b/pigeonhole/src/lib-sieve/cmd-if.c @@ -0,0 +1,277 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-code.h" +#include "sieve-binary.h" + +/* + * Commands + */ + +static bool cmd_if_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_elsif_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_if_validate_const + (struct sieve_validator *valdtr, struct sieve_command *cmd, + int *const_current, int const_next); +static bool cmd_if_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); +static bool cmd_else_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + +/* If command + * + * Syntax: + * if <test1: test> <block1: block> + */ + +const struct sieve_command_def cmd_if = { + .identifier = "if", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 1, + .block_allowed = TRUE, + .block_required = TRUE, + .validate = cmd_if_validate, + .validate_const = cmd_if_validate_const, + .generate = cmd_if_generate +}; + +/* ElsIf command + * + * Santax: + * elsif <test2: test> <block2: block> + */ + +const struct sieve_command_def cmd_elsif = { + .identifier = "elsif", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 1, + .block_allowed = TRUE, + .block_required = TRUE, + .validate = cmd_elsif_validate, + .validate_const = cmd_if_validate_const, + .generate = cmd_if_generate +}; + +/* Else command + * + * Syntax: + * else <block> + */ + +const struct sieve_command_def cmd_else = { + .identifier = "else", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = TRUE, + .block_required = TRUE, + .validate = cmd_elsif_validate, + .validate_const = cmd_if_validate_const, + .generate = cmd_else_generate +}; + +/* + * Context management + */ + +struct cmd_if_context_data { + struct cmd_if_context_data *previous; + struct cmd_if_context_data *next; + + int const_condition; + + bool jump_generated; + sieve_size_t exit_jump; +}; + +static void cmd_if_initialize_context_data +(struct sieve_command *cmd, struct cmd_if_context_data *previous) +{ + struct cmd_if_context_data *cmd_data; + + /* Assign context */ + cmd_data = p_new(sieve_command_pool(cmd), struct cmd_if_context_data, 1); + cmd_data->exit_jump = 0; + cmd_data->jump_generated = FALSE; + + /* Update linked list of contexts */ + cmd_data->previous = previous; + cmd_data->next = NULL; + if ( previous != NULL ) + previous->next = cmd_data; + + /* Check const status */ + cmd_data->const_condition = -1; + while ( previous != NULL ) { + if ( previous->const_condition > 0 ) { + cmd_data->const_condition = 0; + break; + } + previous = previous->previous; + } + + /* Assign to command context */ + cmd->data = cmd_data; +} + +/* + * Validation + */ + +static bool cmd_if_validate +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command *cmd) +{ + /* Start if-command structure */ + cmd_if_initialize_context_data(cmd, NULL); + + return TRUE; +} + +static bool cmd_elsif_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_command *prev; + + i_assert(cmd != NULL); + prev = sieve_command_prev(cmd); + + /* Check valid command placement */ + if ( prev == NULL || + ( !sieve_command_is(prev, cmd_if) && !sieve_command_is(prev, cmd_elsif) ) ) + { + sieve_command_validate_error(valdtr, cmd, + "the %s command must follow an if or elseif command", + sieve_command_identifier(cmd)); + return FALSE; + } + + /* Previous command in this block is 'if' or 'elsif', so we can safely refer + * to its context data + */ + cmd_if_initialize_context_data(cmd, prev->data); + + return TRUE; +} + +static bool cmd_if_validate_const +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command *cmd, + int *const_current, int const_next) +{ + struct cmd_if_context_data *cmd_data = + (struct cmd_if_context_data *) cmd->data; + + if ( cmd_data != NULL ) { + if ( cmd_data->const_condition == 0 ) { + *const_current = cmd_data->const_condition; + return FALSE; + } + + cmd_data->const_condition = const_next; + } + + *const_current = const_next; + + return ( const_next < 0 ); +} + +/* + * Code generation + */ + +/* The if command does not generate specific IF-ELSIF-ELSE opcodes, but only uses + * JMP instructions. This is why the implementation of the if command does not + * include an opcode implementation. + */ + +static void cmd_if_resolve_exit_jumps +(struct sieve_binary_block *sblock, struct cmd_if_context_data *cmd_data) +{ + struct cmd_if_context_data *if_ctx = cmd_data->previous; + + /* Iterate backwards through all if-command contexts and resolve the + * exit jumps to the current code position. + */ + while ( if_ctx != NULL ) { + if ( if_ctx->jump_generated ) + sieve_binary_resolve_offset(sblock, if_ctx->exit_jump); + if_ctx = if_ctx->previous; + } +} + +static bool cmd_if_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + struct sieve_binary_block *sblock = cgenv->sblock; + struct cmd_if_context_data *cmd_data = + (struct cmd_if_context_data *) cmd->data; + struct sieve_ast_node *test; + struct sieve_jumplist jmplist; + + /* Generate test condition */ + if ( cmd_data->const_condition < 0 ) { + /* Prepare jumplist */ + sieve_jumplist_init_temp(&jmplist, sblock); + + test = sieve_ast_test_first(cmd->ast_node); + if ( !sieve_generate_test(cgenv, test, &jmplist, FALSE) ) + return FALSE; + } + + /* Case true { */ + if ( cmd_data->const_condition != 0 ) { + if ( !sieve_generate_block(cgenv, cmd->ast_node) ) + return FALSE; + } + + /* Are we the final command in this if-elsif-else structure? */ + if ( cmd_data->next == NULL || cmd_data->const_condition == 1 ) { + /* Yes, Resolve previous exit jumps to this point */ + cmd_if_resolve_exit_jumps(sblock, cmd_data); + + } else if ( cmd_data->const_condition < 0 ) { + /* No, generate jump to end of if-elsif-else structure (resolved later) + * This of course is not necessary if the {} block contains a command + * like stop at top level that unconditionally exits the block already + * anyway. + */ + if ( !sieve_command_block_exits_unconditionally(cmd) ) { + sieve_operation_emit(sblock, NULL, &sieve_jmp_operation); + cmd_data->exit_jump = sieve_binary_emit_offset(sblock, 0); + cmd_data->jump_generated = TRUE; + } + } + + if ( cmd_data->const_condition < 0 ) { + /* Case false ... (subsequent elsif/else commands might generate more) */ + sieve_jumplist_resolve(&jmplist); + } + + return TRUE; +} + +static bool cmd_else_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + struct cmd_if_context_data *cmd_data = + (struct cmd_if_context_data *) cmd->data; + + /* Else { */ + if ( cmd_data->const_condition != 0 ) { + if ( !sieve_generate_block(cgenv, cmd->ast_node) ) + return FALSE; + + /* } End: resolve all exit blocks */ + cmd_if_resolve_exit_jumps(cgenv->sblock, cmd_data); + } + + return TRUE; +} + diff --git a/pigeonhole/src/lib-sieve/cmd-keep.c b/pigeonhole/src/lib-sieve/cmd-keep.c new file mode 100644 index 0000000..b619a80 --- /dev/null +++ b/pigeonhole/src/lib-sieve/cmd-keep.c @@ -0,0 +1,113 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-dump.h" +#include "sieve-message.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +/* + * Keep command + * + * Syntax: + * keep + */ + +static bool cmd_keep_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + +const struct sieve_command_def cmd_keep = { + .identifier = "keep", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .generate = cmd_keep_generate +}; + +/* + * Keep operation + */ + +static bool cmd_keep_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_keep_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def cmd_keep_operation = { + .mnemonic = "KEEP", + .code = SIEVE_OPERATION_KEEP, + .dump = cmd_keep_operation_dump, + .execute = cmd_keep_operation_execute +}; + +/* + * Code generation + */ + +static bool cmd_keep_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + /* Emit opcode */ + sieve_operation_emit(cgenv->sblock, NULL, &cmd_keep_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool cmd_keep_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "KEEP"); + sieve_code_descend(denv); + + return ( sieve_action_opr_optional_dump(denv, address, NULL) == 0 ); +} + +/* + * Interpretation + */ + +static int cmd_keep_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_side_effects_list *slist = NULL; + int ret = 0; + + /* + * Read data + */ + + /* Optional operands (side effects only) */ + if ( sieve_action_opr_optional_read(renv, address, NULL, &ret, &slist) != 0 ) + return ret; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, + "keep action; store message in default mailbox"); + + /* Add keep action to result. + */ + if ( sieve_result_add_keep(renv, slist) < 0 ) + return SIEVE_EXEC_FAILURE; + + return SIEVE_EXEC_OK; +} + + diff --git a/pigeonhole/src/lib-sieve/cmd-redirect.c b/pigeonhole/src/lib-sieve/cmd-redirect.c new file mode 100644 index 0000000..6a3b0a4 --- /dev/null +++ b/pigeonhole/src/lib-sieve/cmd-redirect.c @@ -0,0 +1,677 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "ioloop.h" +#include "str-sanitize.h" +#include "strfuncs.h" +#include "istream.h" +#include "istream-header-filter.h" +#include "ostream.h" +#include "mail-storage.h" + +#include "rfc2822.h" + +#include "sieve-common.h" +#include "sieve-limits.h" +#include "sieve-address.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-code-dumper.h" +#include "sieve-result.h" +#include "sieve-smtp.h" +#include "sieve-message.h" + +#include <stdio.h> + +/* + * Redirect command + * + * Syntax + * redirect <address: string> + */ + +static bool +cmd_redirect_validate(struct sieve_validator *validator, + struct sieve_command *cmd); +static bool +cmd_redirect_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd); + +const struct sieve_command_def cmd_redirect = { + .identifier = "redirect", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_redirect_validate, + .generate = cmd_redirect_generate +}; + +/* + * Redirect operation + */ + +static bool +cmd_redirect_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_redirect_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def cmd_redirect_operation = { + .mnemonic = "REDIRECT", + .code = SIEVE_OPERATION_REDIRECT, + .dump = cmd_redirect_operation_dump, + .execute = cmd_redirect_operation_execute +}; + +/* + * Redirect action + */ + +static bool +act_redirect_equals(const struct sieve_script_env *senv, + const struct sieve_action *act1, + const struct sieve_action *act2); +static int +act_redirect_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other); +static void +act_redirect_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep); + +static int +act_redirect_start(const struct sieve_action_exec_env *aenv, void **tr_context); +static int +act_redirect_execute(const struct sieve_action_exec_env *aenv, void *tr_context, + bool *keep); +static int +act_redirect_commit(const struct sieve_action_exec_env *aenv, void *tr_context); + +const struct sieve_action_def act_redirect = { + .name = "redirect", + .flags = SIEVE_ACTFLAG_TRIES_DELIVER, + .equals = act_redirect_equals, + .check_duplicate = act_redirect_check_duplicate, + .print = act_redirect_print, + .start = act_redirect_start, + .execute = act_redirect_execute, + .commit = act_redirect_commit, +}; + +/* + * Validation + */ + +static bool +cmd_redirect_validate(struct sieve_validator *validator, + struct sieve_command *cmd) +{ + struct sieve_instance *svinst = sieve_validator_svinst(validator); + struct sieve_ast_argument *arg = cmd->first_positional; + + /* Check and activate address argument */ + + if (!sieve_validate_positional_argument(validator, cmd, arg, "address", + 1, SAAT_STRING)) + return FALSE; + + if (!sieve_validator_argument_activate(validator, cmd, arg, FALSE)) + return FALSE; + + /* We can only assess the validity of the outgoing address when it is + * a string literal. For runtime-generated strings this needs to be + * done at runtime. + */ + if (sieve_argument_is_string_literal(arg)) { + string_t *raw_address = sieve_ast_argument_str(arg); + const char *error; + bool result; + + T_BEGIN { + /* Parse the address */ + result = sieve_address_validate_str(raw_address, &error); + if (!result) { + sieve_argument_validate_error( + validator, arg, + "specified redirect address '%s' is invalid: %s", + str_sanitize(str_c(raw_address),128), + error); + } + } T_END; + + return result; + } + + if (svinst->max_redirects == 0) { + sieve_command_validate_error(validator, cmd, + "local policy prohibits the use of a redirect action"); + return FALSE; + } + return TRUE; +} + +/* + * Code generation + */ + +static bool +cmd_redirect_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, NULL, &cmd_redirect_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool +cmd_redirect_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_code_dumpf(denv, "REDIRECT"); + sieve_code_descend(denv); + + if (sieve_action_opr_optional_dump(denv, address, NULL) != 0) + return FALSE; + + return sieve_opr_string_dump(denv, address, "address"); +} + +/* + * Code execution + */ + +static int +cmd_redirect_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct sieve_instance *svinst = eenv->svinst; + struct sieve_side_effects_list *slist = NULL; + string_t *redirect; + const struct smtp_address *to_address; + const char *error; + int ret; + + /* + * Read data + */ + + /* Optional operands (side effects only) */ + if (sieve_action_opr_optional_read(renv, address, NULL, + &ret, &slist) != 0) + return ret; + + /* Read the address */ + if ((ret = sieve_opr_string_read(renv, address, "address", + &redirect)) <= 0) + return ret; + + /* + * Perform operation + */ + + /* Parse the address */ + to_address = sieve_address_parse_str(redirect, &error); + if (to_address == NULL) { + sieve_runtime_error(renv, NULL, + "specified redirect address '%s' is invalid: %s", + str_sanitize(str_c(redirect),128), error); + return SIEVE_EXEC_FAILURE; + } + + if (svinst->max_redirects == 0) { + sieve_runtime_error(renv, NULL, + "local policy prohibits the use of a redirect action"); + return SIEVE_EXEC_FAILURE; + } + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_ACTIONS)) { + sieve_runtime_trace(renv, 0, "redirect action"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace(renv, 0, "forward message to address %s", + smtp_address_encode_path(to_address)); + } + + /* Add redirect action to the result */ + + return sieve_act_redirect_add_to_result(renv, "redirect", slist, + to_address); +} + +/* + * Action implementation + */ + +struct act_redirect_transaction { + const char *msg_id, *new_msg_id; + const char *dupeid; + + bool skip_redirect:1; +}; + +static bool +act_redirect_equals(const struct sieve_script_env *senv ATTR_UNUSED, + const struct sieve_action *act1, + const struct sieve_action *act2) +{ + struct act_redirect_context *rd_ctx1 = + (struct act_redirect_context *)act1->context; + struct act_redirect_context *rd_ctx2 = + (struct act_redirect_context *)act2->context; + + /* Address is already normalized */ + return (smtp_address_equals(rd_ctx1->to_address, rd_ctx2->to_address)); +} + +static int +act_redirect_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + return (act_redirect_equals(eenv->scriptenv, act, act_other) ? 1 : 0); +} + +static void +act_redirect_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep) +{ + struct act_redirect_context *ctx = + (struct act_redirect_context *)action->context; + + sieve_result_action_printf(rpenv, "redirect message to: %s", + smtp_address_encode_path(ctx->to_address)); + *keep = FALSE; +} + +static int +act_redirect_send(const struct sieve_action_exec_env *aenv, struct mail *mail, + struct act_redirect_context *ctx, const char *new_msg_id) + ATTR_NULL(4) +{ + static const char *hide_headers[] = { "Return-Path" }; + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_instance *svinst = eenv->svinst; + struct sieve_message_context *msgctx = aenv->msgctx; + const struct sieve_script_env *senv = eenv->scriptenv; + struct sieve_address_source env_from = svinst->redirect_from; + struct istream *input; + struct ostream *output; + const struct smtp_address *sender; + const char *error; + struct sieve_smtp_context *sctx; + int ret; + + /* Just to be sure */ + if (!sieve_smtp_available(senv)) { + sieve_result_global_warning(aenv, "no means to send mail"); + return SIEVE_EXEC_FAILURE; + } + + if (mail_get_stream(mail, NULL, NULL, &input) < 0) { + return sieve_result_mail_error(aenv, mail, + "failed to read input message"); + } + + /* Determine which sender to use + + From RFC 5228, Section 4.2: + + The envelope sender address on the outgoing message is chosen by the + sieve implementation. It MAY be copied from the message being + processed. However, if the message being processed has an empty + envelope sender address the outgoing message MUST also have an empty + envelope sender address. This last requirement is imposed to prevent + loops in the case where a message is redirected to an invalid address + when then returns a delivery status notification that also ends up + being redirected to the same invalid address. + */ + if ((eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0) { + /* Envelope available */ + sender = sieve_message_get_sender(msgctx); + if (sender != NULL && + sieve_address_source_get_address(&env_from, svinst, senv, + msgctx, eenv->flags, + &sender) < 0) + sender = NULL; + } else { + /* No envelope available */ + ret = sieve_address_source_get_address(&env_from, svinst, senv, + msgctx, eenv->flags, + &sender); + if (ret < 0) + sender = NULL; + else if (ret == 0) + sender = svinst->user_email; + } + + /* Open SMTP transport */ + sctx = sieve_smtp_start_single(senv, ctx->to_address, sender, &output); + + /* Remove unwanted headers */ + input = i_stream_create_header_filter( + input, HEADER_FILTER_EXCLUDE | HEADER_FILTER_NO_CR, + hide_headers, N_ELEMENTS(hide_headers), + *null_header_filter_callback, (void *)NULL); + + T_BEGIN { + string_t *hdr = t_str_new(256); + const struct smtp_address *user_email; + + /* Prepend sieve headers (should not affect signatures) */ + rfc2822_header_append(hdr, "X-Sieve", SIEVE_IMPLEMENTATION, + FALSE, NULL); + if (svinst->user_email == NULL && + (eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0) + user_email = sieve_message_get_final_recipient(msgctx); + else + user_email = sieve_get_user_email(svinst); + if (user_email != NULL) { + rfc2822_header_append(hdr, "X-Sieve-Redirected-From", + smtp_address_encode(user_email), + FALSE, NULL); + } + + /* Add new Message-ID if message doesn't have one */ + if (new_msg_id != NULL) + rfc2822_header_write(hdr, "Message-ID", new_msg_id); + + o_stream_nsend(output, str_data(hdr), str_len(hdr)); + } T_END; + + o_stream_nsend_istream(output, input); + + if (input->stream_errno != 0) { + sieve_result_critical(aenv, "failed to read input message", + "read(%s) failed: %s", + i_stream_get_name(input), + i_stream_get_error(input)); + i_stream_unref(&input); + sieve_smtp_abort(sctx); + return SIEVE_EXEC_TEMP_FAILURE; + } + i_stream_unref(&input); + + /* Close SMTP transport */ + if ((ret = sieve_smtp_finish(sctx, &error)) <= 0) { + if (ret < 0) { + sieve_result_global_error( + aenv, "failed to redirect message to <%s>: %s " + "(temporary failure)", + smtp_address_encode(ctx->to_address), + str_sanitize(error, 512)); + return SIEVE_EXEC_TEMP_FAILURE; + } + + sieve_result_global_log_error( + aenv, "failed to redirect message to <%s>: %s " + "(permanent failure)", + smtp_address_encode(ctx->to_address), + str_sanitize(error, 512)); + return SIEVE_EXEC_FAILURE; + } + + return SIEVE_EXEC_OK; +} + +static int +act_redirect_get_duplicate_id(struct act_redirect_context *ctx, + const struct sieve_action_exec_env *aenv, + const char *msg_id, const char **dupeid_r) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_message_context *msgctx = aenv->msgctx; + const struct sieve_message_data *msgdata = eenv->msgdata; + struct mail *mail = msgdata->mail; + const struct smtp_address *recipient; + const char *resent_id = NULL, *list_id = NULL; + + /* Read identifying headers */ + if (mail_get_first_header(mail, "resent-message-id", &resent_id) < 0) { + return sieve_result_mail_error( + aenv, mail, + "failed to read header field `resent-message-id'"); + } + if (resent_id == NULL && + mail_get_first_header(mail, "resent-from", &resent_id) < 0) { + return sieve_result_mail_error( + aenv, mail, + "failed to read header field `resent-from'"); + } + if (mail_get_first_header(mail, "list-id", &list_id) < 0) { + return sieve_result_mail_error( + aenv, mail, + "failed to read header field `list-id'"); + } + + if ((eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0) + recipient = sieve_message_get_orig_recipient(msgctx); + else + recipient = sieve_get_user_email(eenv->svinst); + + pool_t pool = sieve_result_pool(aenv->result); + + /* Base the duplicate ID on: + - the message id + - the recipient running this Sieve script + - redirect target address + - if this message is resent: the message-id or from-address of + the original message + - if the message came through a mailing list: the mailinglist ID + */ + *dupeid_r = p_strdup_printf( + pool, "%s-%s-%s-%s-%s", msg_id, + (recipient != NULL ? smtp_address_encode(recipient) : ""), + smtp_address_encode(ctx->to_address), + (resent_id != NULL ? resent_id : ""), + (list_id != NULL ? list_id : "")); + return SIEVE_EXEC_OK; +} + +static int +act_redirect_check_loop_header(const struct sieve_action_exec_env *aenv, + struct mail *mail, bool *loop_detected_r) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_message_context *msgctx = aenv->msgctx; + const char *const *headers; + const char *recipient, *user_email; + const struct smtp_address *addr; + int ret; + + *loop_detected_r = FALSE; + + ret = mail_get_headers(mail, "x-sieve-redirected-from", &headers); + if (ret < 0) { + return sieve_result_mail_error( + aenv, mail, "failed to read header field " + "`x-sieve-redirected-from'"); + } + + if (ret == 0) + return SIEVE_EXEC_OK; + + recipient = user_email = NULL; + if ((eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0) { + addr = sieve_message_get_final_recipient(msgctx); + if (addr != NULL) + recipient = smtp_address_encode(addr); + } + addr = sieve_get_user_email(eenv->svinst); + if (addr != NULL) + user_email = smtp_address_encode(addr); + + while (*headers != NULL) { + const char *header = t_str_trim(*headers, " \t\r\n"); + if (recipient != NULL && strcmp(header, recipient) == 0) { + *loop_detected_r = TRUE; + break; + } + if (user_email != NULL && strcmp(header, user_email) == 0) { + *loop_detected_r = TRUE; + break; + } + headers++; + } + + return SIEVE_EXEC_OK; +} + +static int +act_redirect_start(const struct sieve_action_exec_env *aenv, void **tr_context) +{ + struct act_redirect_transaction *trans; + pool_t pool = sieve_result_pool(aenv->result); + + /* Create transaction context */ + trans = p_new(pool, struct act_redirect_transaction, 1); + *tr_context = trans; + + return SIEVE_EXEC_OK; +} + +static int +act_redirect_execute(const struct sieve_action_exec_env *aenv, + void *tr_context, bool *keep) +{ + const struct sieve_action *action = aenv->action; + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_instance *svinst = eenv->svinst; + struct act_redirect_context *ctx = + (struct act_redirect_context *)action->context; + struct act_redirect_transaction *trans = tr_context; + struct sieve_message_context *msgctx = aenv->msgctx; + struct mail *mail = (action->mail != NULL ? + action->mail : sieve_message_get_mail(msgctx)); + const struct sieve_message_data *msgdata = eenv->msgdata; + bool duplicate, loop_detected = FALSE; + int ret; + + /* + * Prevent mail loops + */ + + /* Create Message-ID for the message if it has none */ + trans->msg_id = msgdata->id; + if (trans->msg_id == NULL) { + pool_t pool = sieve_result_pool(aenv->result); + const char *msg_id; + if (mail_get_message_id_no_validation(msgdata->mail, &msg_id) > 0) + trans->msg_id = p_strdup(pool, msg_id); + else { + msg_id = sieve_message_get_new_id(svinst); + trans->msg_id = trans->new_msg_id = p_strdup(pool, msg_id); + } + } + + /* Create ID for duplicate database lookup */ + ret = act_redirect_get_duplicate_id(ctx, aenv, trans->msg_id, + &trans->dupeid); + if (ret != SIEVE_EXEC_OK) + return ret; + i_assert(trans->dupeid != NULL); + + /* Check whether we've seen this message before */ + ret = sieve_action_duplicate_check(aenv, trans->dupeid, + strlen(trans->dupeid), + &duplicate); + if (ret < SIEVE_EXEC_OK) { + sieve_result_critical( + aenv, "failed to check for duplicate forward", + "failed to check for duplicate forward to <%s>%s", + smtp_address_encode(ctx->to_address), + (ret == SIEVE_EXEC_TEMP_FAILURE ? + " (temporaty failure)" : "")); + return ret; + } + if (duplicate) { + sieve_result_global_log( + aenv, "discarded duplicate forward to <%s>", + smtp_address_encode(ctx->to_address)); + trans->skip_redirect = TRUE; + return SIEVE_EXEC_OK; + } + + /* Check whether we've seen this message before based on added headers + */ + ret = act_redirect_check_loop_header(aenv, mail, &loop_detected); + if (ret != SIEVE_EXEC_OK) + return ret; + if (loop_detected) { + sieve_result_global_log( + aenv, "not forwarding message to <%s>: " + "the `x-sieve-redirected-from' header indicates a mail loop", + smtp_address_encode(ctx->to_address)); + trans->skip_redirect = TRUE; + return SIEVE_EXEC_OK; + } + + /* Cancel implicit keep */ + *keep = FALSE; + + return SIEVE_EXEC_OK; +} + +static int +act_redirect_commit(const struct sieve_action_exec_env *aenv, void *tr_context) +{ + const struct sieve_action *action = aenv->action; + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_instance *svinst = eenv->svinst; + struct act_redirect_context *ctx = + (struct act_redirect_context *)action->context; + struct sieve_message_context *msgctx = aenv->msgctx; + struct mail *mail = (action->mail != NULL ? + action->mail : sieve_message_get_mail(msgctx)); + struct act_redirect_transaction *trans = tr_context; + int ret; + + if (trans->skip_redirect) + return SIEVE_EXEC_OK; + + /* + * Try to forward the message + */ + + ret = act_redirect_send(aenv, mail, ctx, trans->new_msg_id); + if (ret == SIEVE_EXEC_OK) { + /* Mark this message id as forwarded to the specified + destination */ + sieve_action_duplicate_mark( + aenv, trans->dupeid, strlen(trans->dupeid), + ioloop_time + svinst->redirect_duplicate_period); + + eenv->exec_status->significant_action_executed = TRUE; + + struct event_passthrough *e = + sieve_action_create_finish_event(aenv)-> + add_str("redirect_target", + smtp_address_encode(ctx->to_address)); + + sieve_result_event_log(aenv, e->event(), + "forwarded to <%s>", + smtp_address_encode(ctx->to_address)); + + /* Indicate that message was successfully forwarded */ + eenv->exec_status->message_forwarded = TRUE; + + return SIEVE_EXEC_OK; + } + + return ret; +} diff --git a/pigeonhole/src/lib-sieve/cmd-require.c b/pigeonhole/src/lib-sieve/cmd-require.c new file mode 100644 index 0000000..93a2a26 --- /dev/null +++ b/pigeonhole/src/lib-sieve/cmd-require.c @@ -0,0 +1,86 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-extensions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" + +/* + * Require command + * + * Syntax + * Syntax: require <capabilities: string-list> + */ + +static bool cmd_require_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); + +const struct sieve_command_def cmd_require = { + .identifier = "require", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_require_validate +}; + +/* + * Validation + */ + +static bool cmd_require_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + bool result = TRUE; + struct sieve_ast_argument *arg; + struct sieve_command *prev = sieve_command_prev(cmd); + + /* Check valid command placement */ + if ( !sieve_command_is_toplevel(cmd) || + ( !sieve_command_is_first(cmd) && prev != NULL && + !sieve_command_is(prev, cmd_require) ) ) + { + sieve_command_validate_error(valdtr, cmd, + "require commands can only be placed at top level " + "at the beginning of the file"); + return FALSE; + } + + /* Check argument and load specified extension(s) */ + + arg = cmd->first_positional; + if ( sieve_ast_argument_type(arg) == SAAT_STRING ) { + /* Single string */ + const struct sieve_extension *ext = sieve_validator_extension_load_by_name + (valdtr, cmd, arg, sieve_ast_argument_strc(arg)); + + if ( ext == NULL ) result = FALSE; + + } else if ( sieve_ast_argument_type(arg) == SAAT_STRING_LIST ) { + /* String list */ + struct sieve_ast_argument *stritem = sieve_ast_strlist_first(arg); + + while ( stritem != NULL ) { + const struct sieve_extension *ext = sieve_validator_extension_load_by_name + (valdtr, cmd, stritem, sieve_ast_strlist_strc(stritem)); + + if ( ext == NULL ) result = FALSE; + + stritem = sieve_ast_strlist_next(stritem); + } + } else { + /* Something else */ + sieve_argument_validate_error(valdtr, arg, + "the require command accepts a single string or string list argument, " + "but %s was found", + sieve_ast_argument_name(arg)); + return FALSE; + } + + return result; +} diff --git a/pigeonhole/src/lib-sieve/cmd-stop.c b/pigeonhole/src/lib-sieve/cmd-stop.c new file mode 100644 index 0000000..23acadb --- /dev/null +++ b/pigeonhole/src/lib-sieve/cmd-stop.c @@ -0,0 +1,86 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +/* + * Stop command + * + * Syntax + * stop + */ + +static bool cmd_stop_generate + (const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx ATTR_UNUSED); +static bool cmd_stop_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); + +const struct sieve_command_def cmd_stop = { + .identifier = "stop", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_stop_validate, + .generate = cmd_stop_generate +}; + +/* + * Stop operation + */ + +static int opc_stop_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def cmd_stop_operation = { + .mnemonic = "STOP", + .code = SIEVE_OPERATION_STOP, + .execute = opc_stop_execute +}; + +/* + * Command validation + */ + +static bool cmd_stop_validate +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command *cmd) +{ + sieve_command_exit_block_unconditionally(cmd); + + return TRUE; +} + +/* + * Code generation + */ + +static bool cmd_stop_generate +(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd ATTR_UNUSED) +{ + sieve_operation_emit(cgenv->sblock, NULL, &cmd_stop_operation); + + return TRUE; +} + +/* + * Code execution + */ + +static int opc_stop_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED) +{ + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "stop command; end all script execution"); + + sieve_interpreter_interrupt(renv->interp); + + return SIEVE_EXEC_OK; +} + diff --git a/pigeonhole/src/lib-sieve/cmp-i-ascii-casemap.c b/pigeonhole/src/lib-sieve/cmp-i-ascii-casemap.c new file mode 100644 index 0000000..4f0dab4 --- /dev/null +++ b/pigeonhole/src/lib-sieve/cmp-i-ascii-casemap.c @@ -0,0 +1,99 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Comparator 'i;ascii-casemap': + * + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-comparators.h" + +#include <string.h> +#include <stdio.h> +#include <ctype.h> + +/* + * Forward declarations + */ + +static int cmp_i_ascii_casemap_compare + (const struct sieve_comparator *cmp, + const char *val1, size_t val1_size, const char *val2, size_t val2_size); +static bool cmp_i_ascii_casemap_char_match + (const struct sieve_comparator *cmp, const char **val1, const char *val1_end, + const char **val2, const char *val2_end); + +/* + * Comparator object + */ + +const struct sieve_comparator_def i_ascii_casemap_comparator = { + SIEVE_OBJECT("i;ascii-casemap", + &comparator_operand, SIEVE_COMPARATOR_I_ASCII_CASEMAP), + .flags = + SIEVE_COMPARATOR_FLAG_ORDERING | + SIEVE_COMPARATOR_FLAG_EQUALITY | + SIEVE_COMPARATOR_FLAG_SUBSTRING_MATCH | + SIEVE_COMPARATOR_FLAG_PREFIX_MATCH, + .compare = cmp_i_ascii_casemap_compare, + .char_match = cmp_i_ascii_casemap_char_match, + .char_skip = sieve_comparator_octet_skip +}; + +/* + * Comparator implementation + */ + +static int cmp_i_ascii_casemap_compare( + const struct sieve_comparator *cmp ATTR_UNUSED, + const char *val1, size_t val1_size, const char *val2, size_t val2_size) +{ + int result; + + if ( val1_size == val2_size ) { + return strncasecmp(val1, val2, val1_size); + } + + if ( val1_size > val2_size ) { + result = strncasecmp(val1, val2, val2_size); + + if ( result == 0 ) return 1; + + return result; + } + + result = strncasecmp(val1, val2, val1_size); + + if ( result == 0 ) return -1; + + return result; +} + +static bool cmp_i_ascii_casemap_char_match + (const struct sieve_comparator *cmp ATTR_UNUSED, + const char **val, const char *val_end, + const char **key, const char *key_end) +{ + const char *val_begin = *val; + const char *key_begin = *key; + + while ( i_tolower(**val) == i_tolower(**key) && + *val < val_end && *key < key_end ) { + (*val)++; + (*key)++; + } + + if ( *key < key_end ) { + /* Reset */ + *val = val_begin; + *key = key_begin; + + return FALSE; + } + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/cmp-i-octet.c b/pigeonhole/src/lib-sieve/cmp-i-octet.c new file mode 100644 index 0000000..caa46fa --- /dev/null +++ b/pigeonhole/src/lib-sieve/cmp-i-octet.c @@ -0,0 +1,97 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Comparator 'i;octet': + * + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-comparators.h" + +#include <string.h> +#include <stdio.h> + +/* + * Forward declarations + */ + +static int cmp_i_octet_compare + (const struct sieve_comparator *cmp, + const char *val1, size_t val1_size, const char *val2, size_t val2_size); +static bool cmp_i_octet_char_match + (const struct sieve_comparator *cmp, const char **val1, const char *val1_end, + const char **val2, const char *val2_end); + +/* + * Comparator object + */ + +const struct sieve_comparator_def i_octet_comparator = { + SIEVE_OBJECT("i;octet", + &comparator_operand, SIEVE_COMPARATOR_I_OCTET), + .flags = + SIEVE_COMPARATOR_FLAG_ORDERING | + SIEVE_COMPARATOR_FLAG_EQUALITY | + SIEVE_COMPARATOR_FLAG_SUBSTRING_MATCH | + SIEVE_COMPARATOR_FLAG_PREFIX_MATCH, + .compare = cmp_i_octet_compare, + .char_match = cmp_i_octet_char_match, + .char_skip = sieve_comparator_octet_skip +}; + +/* + * Comparator implementation + */ + +static int cmp_i_octet_compare( + const struct sieve_comparator *cmp ATTR_UNUSED, + const char *val1, size_t val1_size, const char *val2, size_t val2_size) +{ + int result; + + if ( val1_size == val2_size ) { + return memcmp((void *) val1, (void *) val2, val1_size); + } + + if ( val1_size > val2_size ) { + result = memcmp((void *) val1, (void *) val2, val2_size); + + if ( result == 0 ) return 1; + + return result; + } + + result = memcmp((void *) val1, (void *) val2, val1_size); + + if ( result == 0 ) return -1; + + return result; +} + +static bool cmp_i_octet_char_match + (const struct sieve_comparator *cmp ATTR_UNUSED, + const char **val, const char *val_end, + const char **key, const char *key_end) +{ + const char *val_begin = *val; + const char *key_begin = *key; + + while ( **val == **key && *val < val_end && *key < key_end ) { + (*val)++; + (*key)++; + } + + if ( *key < key_end ) { + /* Reset */ + *val = val_begin; + *key = key_begin; + + return FALSE; + } + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/ext-encoded-character.c b/pigeonhole/src/lib-sieve/ext-encoded-character.c new file mode 100644 index 0000000..d9e2b18 --- /dev/null +++ b/pigeonhole/src/lib-sieve/ext-encoded-character.c @@ -0,0 +1,271 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension encoded-character + * --------------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5228 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "unichar.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" + +#include <ctype.h> + +/* + * Extension + */ + +static bool ext_encoded_character_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def encoded_character_extension = { + .name = "encoded-character", + .validator_load = ext_encoded_character_validator_load, +}; + +/* + * Encoded string argument + */ + +bool arg_encoded_string_validate + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *context); + +const struct sieve_argument_def encoded_string_argument = { + .identifier = "@encoded-string", + .validate = arg_encoded_string_validate +}; + +/* Parsing */ + +static bool _skip_whitespace + (const char **in, const char *inend) +{ + while ( *in < inend ) { + if ( **in == '\r' ) { + (*in)++; + if ( **in != '\n' ) + return FALSE; + continue; + } + + /* (Loose LF is non-standard) */ + if ( **in != ' ' && **in != '\n' && **in != '\t' ) + break; + + (*in)++; + } + + return TRUE; +} + +static bool _parse_hexint +(const char **in, const char *inend, int max_digits, unsigned int *result) +{ + int digit = 0; + *result = 0; + + while ( *in < inend && (max_digits == 0 || digit < max_digits) ) { + + if ( (**in) >= '0' && (**in) <= '9' ) + *result = ((*result) << 4) + (**in) - ((unsigned int) '0'); + else if ( (**in) >= 'a' && (**in) <= 'f' ) + *result = ((*result) << 4) + (**in) - ((unsigned int) 'a') + 0x0a; + else if ( (**in) >= 'A' && (**in) <= 'F' ) + *result = ((*result) << 4) + (**in) - ((unsigned int) 'A') + 0x0a; + else + return ( digit > 0 ); + + (*in)++; + digit++; + } + + if ( digit == max_digits ) { + /* Hex digit _MUST_ end here */ + if ( (**in >= '0' && **in <= '9') || (**in >= 'a' && **in <= 'f') || + (**in >= 'A' && **in <= 'F') ) + return FALSE; + + return TRUE; + } + + return ( digit > 0 ); +} + +static bool _decode_hex +(const char **in, const char *inend, string_t *result) +{ + int values = 0; + + while ( *in < inend ) { + unsigned int hexpair; + + if ( !_skip_whitespace(in, inend) ) return FALSE; + + if ( !_parse_hexint(in, inend, 2, &hexpair) ) break; + + str_append_c(result, (unsigned char) hexpair); + values++; + } + + return ( values > 0 ); +} + +static bool _decode_unicode +(const char **in, const char *inend, string_t *result, + unsigned int *error_hex) +{ + int values = 0; + bool valid = TRUE; + + while ( *in < inend ) { + unsigned int unicode_hex; + + if ( !_skip_whitespace(in, inend) ) return FALSE; + + if ( !_parse_hexint(in, inend, 0, &unicode_hex) ) break; + + if ( uni_is_valid_ucs4((unichar_t) unicode_hex) ) + uni_ucs4_to_utf8_c((unichar_t) unicode_hex, result); + else { + if ( valid ) *error_hex = unicode_hex; + valid = FALSE; + } + values++; + } + + return ( values > 0 ); +} + +bool arg_encoded_string_validate +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + bool result = TRUE; + enum { ST_NONE, ST_OPEN, ST_TYPE, ST_CLOSE } + state = ST_NONE; + string_t *str = sieve_ast_argument_str(*arg); + string_t *tmpstr, *newstr = NULL; + const char *p, *mark, *strstart, *substart = NULL; + const char *strval = (const char *) str_data(str); + const char *strend = strval + str_len(str); + unsigned int error_hex = 0; + + T_BEGIN { + tmpstr = t_str_new(32); + + p = strval; + strstart = p; + while ( result && p < strend ) { + switch ( state ) { + /* Normal string */ + case ST_NONE: + if ( *p == '$' ) { + substart = p; + state = ST_OPEN; + } + p++; + break; + /* Parsed '$' */ + case ST_OPEN: + if ( *p == '{' ) { + state = ST_TYPE; + p++; + } else + state = ST_NONE; + break; + /* Parsed '${' */ + case ST_TYPE: + mark = p; + /* Scan for 'hex' or 'unicode' */ + while ( p < strend && i_isalpha(*p) ) p++; + + if ( *p != ':' ) { + state = ST_NONE; + break; + } + + state = ST_CLOSE; + + str_truncate(tmpstr, 0); + if ( strncasecmp(mark, "hex", p - mark) == 0 ) { + /* Hexadecimal */ + p++; + if ( !_decode_hex(&p, strend, tmpstr) ) + state = ST_NONE; + } else if ( strncasecmp(mark, "unicode", p - mark) == 0 ) { + /* Unicode */ + p++; + if ( !_decode_unicode(&p, strend, tmpstr, &error_hex) ) + state = ST_NONE; + } else { + /* Invalid encoding */ + p++; + state = ST_NONE; + } + break; + case ST_CLOSE: + if ( *p == '}' ) { + /* We now know that the substitution is valid */ + + if ( error_hex != 0 ) { + sieve_argument_validate_error(valdtr, *arg, + "invalid unicode character 0x%08x in encoded character substitution", + error_hex); + result = FALSE; + break; + } + + if ( newstr == NULL ) { + newstr = str_new(sieve_ast_pool((*arg)->ast), str_len(str)*2); + } + + str_append_data(newstr, strstart, substart-strstart); + str_append_str(newstr, tmpstr); + + strstart = p + 1; + substart = strstart; + + p++; + } + state = ST_NONE; + } + } + } T_END; + + if ( !result ) return FALSE; + + if ( newstr != NULL ) { + if ( strstart != strend ) + str_append_data(newstr, strstart, strend-strstart); + + sieve_ast_argument_string_set(*arg, newstr); + } + + /* Pass the processed string to a (possible) next layer of processing */ + return sieve_validator_argument_activate_super + (valdtr, cmd, *arg, TRUE); +} + +/* + * Extension implementation + */ + +static bool ext_encoded_character_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Override the constant string argument with our own */ + sieve_validator_argument_override + (valdtr, SAT_CONST_STRING, ext, &encoded_string_argument); + + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/ext-envelope.c b/pigeonhole/src/lib-sieve/ext-envelope.c new file mode 100644 index 0000000..e889cff --- /dev/null +++ b/pigeonhole/src/lib-sieve/ext-envelope.c @@ -0,0 +1,732 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension envelope + * ------------------ + * + * Authors: Stephan Bosch + * Specification: RFC 5228 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "str-sanitize.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-address.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" +#include "sieve-message.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +/* + * Forward declarations + */ + +static const struct sieve_command_def envelope_test; +const struct sieve_operation_def envelope_operation; +const struct sieve_extension_def envelope_extension; + +/* + * Extension + */ + +static bool +ext_envelope_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr); +static bool +ext_envelope_interpreter_load(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + sieve_size_t *address); + +static bool +ext_envelope_validator_validate(const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + bool required); +static int +ext_envelope_interpreter_run(const struct sieve_extension *this_ext, + const struct sieve_runtime_env *renv, + void *context, bool deferred); + +const struct sieve_extension_def envelope_extension = { + .name = "envelope", + .interpreter_load = ext_envelope_interpreter_load, + .validator_load = ext_envelope_validator_load, + SIEVE_EXT_DEFINE_OPERATION(envelope_operation) +}; +const struct sieve_validator_extension +envelope_validator_extension = { + .ext = &envelope_extension, + .validate = ext_envelope_validator_validate +}; +const struct sieve_interpreter_extension +envelope_interpreter_extension = { + .ext_def = &envelope_extension, + .run = ext_envelope_interpreter_run +}; + +static bool +ext_envelope_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr) +{ + /* Register new test */ + sieve_validator_register_command(valdtr, ext, &envelope_test); + + sieve_validator_extension_register(valdtr, ext, + &envelope_validator_extension, NULL); + return TRUE; +} + +static bool +ext_envelope_interpreter_load(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + sieve_interpreter_extension_register(renv->interp, ext, + &envelope_interpreter_extension, + NULL); + return TRUE; +} + +static bool +ext_envelope_validator_validate(const struct sieve_extension *ext, + struct sieve_validator *valdtr, + void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg, + bool required) +{ + if (required) { + enum sieve_compile_flags flags = + sieve_validator_compile_flags(valdtr); + + if ((flags & SIEVE_COMPILE_FLAG_NO_ENVELOPE) != 0) { + sieve_argument_validate_error( + valdtr, require_arg, + "the %s extension cannot be used in this context " + "(needs access to message envelope)", + sieve_extension_name(ext)); + return FALSE; + } + } + return TRUE; +} + +static int +ext_envelope_interpreter_run(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + void *context ATTR_UNUSED, bool deferred) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + if ((eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) != 0) { + if (!deferred) { + sieve_runtime_error( + renv, NULL, + "the %s extension cannot be used in this context " + "(needs access to message envelope)", + sieve_extension_name(ext)); + } + return SIEVE_EXEC_FAILURE; + } + return SIEVE_EXEC_OK; +} + +/* + * Envelope test + * + * Syntax + * envelope [COMPARATOR] [ADDRESS-PART] [MATCH-TYPE] + * <envelope-part: string-list> <key-list: string-list> + */ + +static bool +tst_envelope_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool +tst_envelope_validate(struct sieve_validator *valdtr, + struct sieve_command *tst); +static bool +tst_envelope_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +static const struct sieve_command_def envelope_test = { + .identifier = "envelope", + .type = SCT_TEST, + .positional_args= 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_envelope_registered, + .validate = tst_envelope_validate, + .generate = tst_envelope_generate +}; + +/* + * Envelope operation + */ + +static bool +ext_envelope_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +ext_envelope_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def envelope_operation = { + .mnemonic = "ENVELOPE", + .ext_def = &envelope_extension, + .dump = ext_envelope_operation_dump, + .execute = ext_envelope_operation_execute +}; + +/* + * Envelope parts + * + * FIXME: not available to extensions + */ + +struct sieve_envelope_part { + const char *identifier; + + const struct smtp_address *const *(*get_addresses) + (const struct sieve_runtime_env *renv); + const char * const *(*get_values) + (const struct sieve_runtime_env *renv); +}; + +static const struct smtp_address *const * +_from_part_get_addresses(const struct sieve_runtime_env *renv); +static const char *const * +_from_part_get_values(const struct sieve_runtime_env *renv); +static const struct smtp_address *const * +_to_part_get_addresses(const struct sieve_runtime_env *renv); +static const char *const * +_to_part_get_values(const struct sieve_runtime_env *renv); +static const char *const * +_auth_part_get_values(const struct sieve_runtime_env *renv); + +static const struct sieve_envelope_part _from_part = { + "from", + _from_part_get_addresses, + _from_part_get_values, +}; + +static const struct sieve_envelope_part _to_part = { + "to", + _to_part_get_addresses, + _to_part_get_values, +}; + +static const struct sieve_envelope_part _auth_part = { + "auth", + NULL, + _auth_part_get_values, +}; + +static const struct sieve_envelope_part *_envelope_parts[] = { + /* Required */ + &_from_part, &_to_part, + + /* Non-standard */ + &_auth_part +}; + +static unsigned int _envelope_part_count = N_ELEMENTS(_envelope_parts); + +static const struct sieve_envelope_part * +_envelope_part_find(const char *identifier) +{ + unsigned int i; + + for (i = 0; i < _envelope_part_count; i++) { + if (strcasecmp(_envelope_parts[i]->identifier, + identifier) == 0) + return _envelope_parts[i]; + } + + return NULL; +} + +/* Envelope parts implementation */ + +static const struct smtp_address *const * +_from_part_get_addresses(const struct sieve_runtime_env *renv) +{ + ARRAY(const struct smtp_address *) envelope_values; + const struct smtp_address *address = + sieve_message_get_sender(renv->msgctx); + + t_array_init(&envelope_values, 2); + + if (address == NULL) + address = smtp_address_create_temp(NULL, NULL); + array_append(&envelope_values, &address, 1); + + (void)array_append_space(&envelope_values); + return array_idx(&envelope_values, 0); +} + +static const char *const * +_from_part_get_values(const struct sieve_runtime_env *renv) +{ + ARRAY(const char *)envelope_values; + const struct smtp_address *address = + sieve_message_get_sender(renv->msgctx); + const char *value; + + t_array_init(&envelope_values, 2); + + value = ""; + if (!smtp_address_isnull(address)) + value = smtp_address_encode(address); + array_append(&envelope_values, &value, 1); + + (void)array_append_space(&envelope_values); + + return array_idx(&envelope_values, 0); +} + +static const struct smtp_address *const * +_to_part_get_addresses(const struct sieve_runtime_env *renv) +{ + ARRAY(const struct smtp_address *) envelope_values; + const struct smtp_address *address = + sieve_message_get_orig_recipient(renv->msgctx); + + if (address != NULL && address->localpart != NULL) { + t_array_init(&envelope_values, 2); + + array_append(&envelope_values, &address, 1); + + (void)array_append_space(&envelope_values); + return array_idx(&envelope_values, 0); + } + return NULL; +} + +static const char *const * +_to_part_get_values(const struct sieve_runtime_env *renv) +{ + ARRAY(const char *) envelope_values; + const struct smtp_address *address = + sieve_message_get_orig_recipient(renv->msgctx); + + t_array_init(&envelope_values, 2); + + if (address != NULL && address->localpart != NULL) { + const char *value = smtp_address_encode(address); + array_append(&envelope_values, &value, 1); + } + + (void)array_append_space(&envelope_values); + + return array_idx(&envelope_values, 0); +} + +static const char *const * +_auth_part_get_values(const struct sieve_runtime_env *renv) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + ARRAY(const char *) envelope_values; + + t_array_init(&envelope_values, 2); + + if (eenv->msgdata->auth_user != NULL) + array_append(&envelope_values, &eenv->msgdata->auth_user, 1); + + (void)array_append_space(&envelope_values); + + return array_idx(&envelope_values, 0); +} + +/* + * Envelope address list + */ + +/* Forward declarations */ + +static int +sieve_envelope_address_list_next_string_item(struct sieve_stringlist *_strlist, + string_t **str_r); +static int +sieve_envelope_address_list_next_item(struct sieve_address_list *_addrlist, + struct smtp_address *addr_r, + string_t **unparsed_r); +static void +sieve_envelope_address_list_reset(struct sieve_stringlist *_strlist); + +/* Stringlist object */ + +struct sieve_envelope_address_list { + struct sieve_address_list addrlist; + + struct sieve_stringlist *env_parts; + + const struct smtp_address *const *cur_addresses; + const char * const *cur_values; + + int value_index; +}; + +static struct sieve_address_list * +sieve_envelope_address_list_create(const struct sieve_runtime_env *renv, + struct sieve_stringlist *env_parts) +{ + struct sieve_envelope_address_list *addrlist; + + addrlist = t_new(struct sieve_envelope_address_list, 1); + addrlist->addrlist.strlist.runenv = renv; + addrlist->addrlist.strlist.exec_status = SIEVE_EXEC_OK; + addrlist->addrlist.strlist.next_item = + sieve_envelope_address_list_next_string_item; + addrlist->addrlist.strlist.reset = sieve_envelope_address_list_reset; + addrlist->addrlist.next_item = sieve_envelope_address_list_next_item; + addrlist->env_parts = env_parts; + + return &addrlist->addrlist; +} + +static int +sieve_envelope_address_list_next_item(struct sieve_address_list *_addrlist, + struct smtp_address *addr_r, + string_t **unparsed_r) +{ + struct sieve_envelope_address_list *addrlist = + (struct sieve_envelope_address_list *)_addrlist; + const struct sieve_runtime_env *renv = _addrlist->strlist.runenv; + + if (addr_r != NULL) + smtp_address_init(addr_r, NULL, NULL); + if (unparsed_r != NULL) *unparsed_r = NULL; + + while (addrlist->cur_addresses == NULL && + addrlist->cur_values == NULL) { + const struct sieve_envelope_part *epart; + string_t *envp_item = NULL; + int ret; + + /* Read next header value from source list */ + if ((ret = sieve_stringlist_next_item(addrlist->env_parts, + &envp_item)) <= 0) + return ret; + + if (_addrlist->strlist.trace) { + sieve_runtime_trace( + _addrlist->strlist.runenv, 0, + "getting `%s' part from message envelope", + str_sanitize(str_c(envp_item), 80)); + } + + if ((epart=_envelope_part_find(str_c(envp_item))) != NULL) { + addrlist->value_index = 0; + + if (epart->get_addresses != NULL) { + /* Field contains addresses */ + addrlist->cur_addresses = + epart->get_addresses(renv); + + /* Drop empty list */ + if (addrlist->cur_addresses != NULL && + addrlist->cur_addresses[0] == NULL) + addrlist->cur_addresses = NULL; + } + + if (addrlist->cur_addresses == NULL && + epart->get_values != NULL) { + /* Field contains something else */ + addrlist->cur_values = epart->get_values(renv); + + /* Drop empty list */ + if (addrlist->cur_values != NULL && + addrlist->cur_values[0] == NULL) + addrlist->cur_values = NULL; + } + } + } + + /* Return next item */ + if (addrlist->cur_addresses != NULL) { + const struct smtp_address *addr = + addrlist->cur_addresses[addrlist->value_index]; + + if (addr->localpart == NULL) { + /* Null path <> */ + if (unparsed_r != NULL) + *unparsed_r = t_str_new_const("", 0); + } else { + if (addr_r != NULL) + *addr_r = *addr; + } + + /* Advance to next value */ + addrlist->value_index++; + if (addrlist->cur_addresses[addrlist->value_index] == NULL) { + addrlist->cur_addresses = NULL; + addrlist->value_index = 0; + } + } else { + if (unparsed_r != NULL) { + const char *value = + addrlist->cur_values[addrlist->value_index]; + + *unparsed_r = t_str_new_const(value, strlen(value)); + } + + /* Advance to next value */ + addrlist->value_index++; + if (addrlist->cur_values[addrlist->value_index] == NULL) { + addrlist->cur_values = NULL; + addrlist->value_index = 0; + } + } + + return 1; +} + +static int +sieve_envelope_address_list_next_string_item(struct sieve_stringlist *_strlist, + string_t **str_r) +{ + struct sieve_address_list *addrlist = + (struct sieve_address_list *)_strlist; + struct smtp_address addr; + int ret; + + if ((ret=sieve_envelope_address_list_next_item(addrlist, &addr, + str_r)) <= 0) + return ret; + + if (addr.localpart != NULL) { + const char *addr_str = smtp_address_encode(&addr); + if (str_r != NULL) + *str_r = t_str_new_const(addr_str, strlen(addr_str)); + } + return 1; +} + +static void +sieve_envelope_address_list_reset(struct sieve_stringlist *_strlist) +{ + struct sieve_envelope_address_list *addrlist = + (struct sieve_envelope_address_list *)_strlist; + + sieve_stringlist_reset(addrlist->env_parts); + addrlist->cur_addresses = NULL; + addrlist->cur_values = NULL; + addrlist->value_index = 0; +} + +/* + * Command Registration + */ + +static bool +tst_envelope_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + sieve_address_parts_link_tags(valdtr, cmd_reg, SIEVE_AM_OPT_ADDRESS_PART); + return TRUE; +} + +/* + * Validation + */ + +static int +_envelope_part_is_supported(void *context, struct sieve_ast_argument *arg) +{ + const struct sieve_envelope_part **not_address = + (const struct sieve_envelope_part **) context; + + if (sieve_argument_is_string_literal(arg)) { + const struct sieve_envelope_part *epart; + + if ((epart=_envelope_part_find( + sieve_ast_strlist_strc(arg))) != NULL) { + if (epart->get_addresses == NULL) { + if (*not_address == NULL) + *not_address = epart; + } + return 1; + } + return 0; + } + return 1; /* Can't check at compile time */ +} + +static bool +tst_envelope_validate(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + struct sieve_ast_argument *epart; + struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_envelope_part *not_address = NULL; + + if (!sieve_validate_positional_argument(valdtr, tst, arg, + "envelope part", 1, + SAAT_STRING_LIST)) { + return FALSE; + } + + if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) + return FALSE; + + /* Check whether supplied envelope parts are supported + * FIXME: verify dynamic envelope parts at runtime + */ + epart = arg; + if (sieve_ast_stringlist_map(&epart, (void *) ¬_address, + _envelope_part_is_supported) <= 0) { + i_assert(epart != NULL); + sieve_argument_validate_error( + valdtr, epart, + "specified envelope part '%s' is not supported by the envelope test", + str_sanitize(sieve_ast_strlist_strc(epart), 64)); + return FALSE; + } + + if (not_address != NULL) { + struct sieve_ast_argument *addrp_arg = + sieve_command_find_argument(tst, &address_part_tag); + + if (addrp_arg != NULL) { + sieve_argument_validate_error( + valdtr, addrp_arg, + "address part ':%s' specified while non-address envelope part '%s' " + "is tested with the envelope test", + sieve_ast_argument_tag(addrp_arg), + not_address->identifier); + return FALSE; + } + } + + arg = sieve_ast_argument_next(arg); + + if (!sieve_validate_positional_argument(valdtr, tst, arg, "key list", 2, + SAAT_STRING_LIST)) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate(valdtr, tst, arg, + &mcht_default, &cmp_default); +} + +/* + * Code generation + */ + +static bool +tst_envelope_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + (void)sieve_operation_emit(cgenv->sblock, cmd->ext, + &envelope_operation); + + /* Generate arguments */ + if (!sieve_generate_arguments(cgenv, cmd, NULL)) + return FALSE; + return TRUE; +} + +/* + * Code dump + */ + +static bool +ext_envelope_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_code_dumpf(denv, "ENVELOPE"); + sieve_code_descend(denv); + + /* Handle any optional arguments */ + if (sieve_addrmatch_opr_optional_dump(denv, address, NULL) != 0) + return FALSE; + + return (sieve_opr_stringlist_dump(denv, address, "envelope part") && + sieve_opr_stringlist_dump(denv, address, "key list")); +} + +/* + * Interpretation + */ + +static int +ext_envelope_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + struct sieve_address_part addrp = + SIEVE_ADDRESS_PART_DEFAULT(all_address_part); + struct sieve_stringlist *env_part_list, *value_list, *key_list; + struct sieve_address_list *addr_list; + int match, ret; + + /* + * Read operands + */ + + /* Read optional operands */ + if (sieve_addrmatch_opr_optional_read(renv, address, NULL, &ret, + &addrp, &mcht, &cmp) < 0) + return ret; + + /* Read envelope-part */ + if ((ret = sieve_opr_stringlist_read(renv, address, "envelope-part", + &env_part_list)) <= 0) + return ret; + + /* Read key-list */ + if ((ret = sieve_opr_stringlist_read(renv, address, "key-list", + &key_list)) <= 0) + return ret; + + /* + * Perform test + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "envelope test"); + + /* Create value stringlist */ + addr_list = sieve_envelope_address_list_create(renv, env_part_list); + value_list = sieve_address_part_stringlist_create(renv, &addrp, + addr_list); + + /* Perform match */ + if ((match = sieve_match(renv, &mcht, &cmp, + value_list, key_list, &ret)) < 0) + return ret; + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} + diff --git a/pigeonhole/src/lib-sieve/ext-fileinto.c b/pigeonhole/src/lib-sieve/ext-fileinto.c new file mode 100644 index 0000000..fb65758 --- /dev/null +++ b/pigeonhole/src/lib-sieve/ext-fileinto.c @@ -0,0 +1,225 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension fileinto + * ------------------ + * + * Authors: Stephan Bosch + * Specification: RFC 5228 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "str-sanitize.h" +#include "unichar.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-binary.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-result.h" + +/* + * Forward declarations + */ + +static const struct sieve_command_def fileinto_command; +const struct sieve_operation_def fileinto_operation; +const struct sieve_extension_def fileinto_extension; + +/* + * Extension + */ + +static bool +ext_fileinto_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr); + +const struct sieve_extension_def fileinto_extension = { + .name = "fileinto", + .validator_load = ext_fileinto_validator_load, + SIEVE_EXT_DEFINE_OPERATION(fileinto_operation), +}; + +static bool +ext_fileinto_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr) +{ + /* Register new command */ + sieve_validator_register_command(valdtr, ext, &fileinto_command); + + return TRUE; +} + +/* + * Fileinto command + * + * Syntax: + * fileinto <folder: string> + */ + +static bool +cmd_fileinto_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd); +static bool +cmd_fileinto_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +static const struct sieve_command_def fileinto_command = { + .identifier = "fileinto", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_fileinto_validate, + .generate = cmd_fileinto_generate, +}; + +/* + * Fileinto operation + */ + +static bool +ext_fileinto_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +ext_fileinto_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def fileinto_operation = { + .mnemonic = "FILEINTO", + .ext_def = &fileinto_extension, + .dump = ext_fileinto_operation_dump, + .execute = ext_fileinto_operation_execute, +}; + +/* + * Validation + */ + +static bool +cmd_fileinto_validate(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "folder", + 1, SAAT_STRING)) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE)) + return FALSE; + + /* Check name validity when folder argument is not a variable */ + if (sieve_argument_is_string_literal(arg)) { + const char *folder = sieve_ast_argument_strc(arg), *error; + + if (!sieve_mailbox_check_name(folder, &error)) { + sieve_command_validate_error( + valdtr, cmd, "fileinto command: " + "invalid folder name `%s' specified: %s", + str_sanitize(folder, 256), error); + return FALSE; + } + } + return TRUE; +} + +/* + * Code generation + */ + +static bool +cmd_fileinto_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &fileinto_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool +ext_fileinto_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_code_dumpf(denv, "FILEINTO"); + sieve_code_descend(denv); + + if (sieve_action_opr_optional_dump(denv, address, NULL) != 0) + return FALSE; + + return sieve_opr_string_dump(denv, address, "folder"); +} + +/* + * Execution + */ + +static int +ext_fileinto_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + struct sieve_side_effects_list *slist = NULL; + string_t *folder; + const char *error; + bool trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_ACTIONS); + int ret = 0; + + /* + * Read operands + */ + + /* Optional operands (side effects only) */ + if (sieve_action_opr_optional_read(renv, address, NULL, + &ret, &slist) != 0) + return ret; + + /* Folder operand */ + ret = sieve_opr_string_read(renv, address, "folder", &folder); + if (ret <= 0) + return ret; + + /* + * Perform operation + */ + + if (trace) { + sieve_runtime_trace(renv, 0, "fileinto action"); + sieve_runtime_trace_descend(renv); + } + + if (!sieve_mailbox_check_name(str_c(folder), &error)) { + sieve_runtime_error( + renv, NULL, "fileinto command: " + "invalid folder name `%s' specified: %s", + str_c(folder), error); + return SIEVE_EXEC_FAILURE; + } + + if (trace) { + sieve_runtime_trace(renv, 0, "store message in mailbox `%s'", + str_sanitize(str_c(folder), 80)); + } + + /* Add action to result */ + if (sieve_act_store_add_to_result(renv, "fileinto", slist, + str_c(folder)) < 0) + return SIEVE_EXEC_FAILURE; + + sieve_message_snapshot(renv->msgctx); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/ext-reject.c b/pigeonhole/src/lib-sieve/ext-reject.c new file mode 100644 index 0000000..649c1f2 --- /dev/null +++ b/pigeonhole/src/lib-sieve/ext-reject.c @@ -0,0 +1,606 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension reject + * ---------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5429 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "ioloop.h" +#include "hostpid.h" +#include "str-sanitize.h" +#include "message-date.h" +#include "message-size.h" +#include "istream.h" +#include "istream-header-filter.h" + +#include "rfc2822.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-result.h" +#include "sieve-message.h" +#include "sieve-smtp.h" + +/* + * Forward declarations + */ + +static const struct sieve_command_def reject_command; +static const struct sieve_operation_def reject_operation; + +static const struct sieve_command_def ereject_command; +static const struct sieve_operation_def ereject_operation; + +/* + * Extensions + */ + +static bool +ext_reject_validator_validate(const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + bool required); +static int +ext_reject_interpreter_run(const struct sieve_extension *this_ext, + const struct sieve_runtime_env *renv, + void *context, bool deferred); + +/* Reject */ + +static bool +ext_reject_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr); +static bool +ext_reject_interpreter_load(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_extension_def reject_extension = { + .name = "reject", + .validator_load = ext_reject_validator_load, + .interpreter_load = ext_reject_interpreter_load, + SIEVE_EXT_DEFINE_OPERATION(reject_operation) +}; +const struct sieve_validator_extension +reject_validator_extension = { + .ext = &reject_extension, + .validate = ext_reject_validator_validate +}; +const struct sieve_interpreter_extension +reject_interpreter_extension = { + .ext_def = &reject_extension, + .run = ext_reject_interpreter_run +}; + +static bool +ext_reject_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr) +{ + /* Register new command */ + sieve_validator_register_command(valdtr, ext, &reject_command); + + sieve_validator_extension_register(valdtr, ext, + &reject_validator_extension, NULL); + return TRUE; +} + +static bool +ext_reject_interpreter_load(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + sieve_interpreter_extension_register(renv->interp, ext, + &reject_interpreter_extension, + NULL); + return TRUE; +} + +/* EReject */ + +static bool +ext_ereject_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr); +static bool +ext_ereject_interpreter_load(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_extension_def ereject_extension = { + .name = "ereject", + .validator_load = ext_ereject_validator_load, + .interpreter_load = ext_ereject_interpreter_load, + SIEVE_EXT_DEFINE_OPERATION(ereject_operation) +}; +const struct sieve_validator_extension +ereject_validator_extension = { + .ext = &ereject_extension, + .validate = ext_reject_validator_validate +}; +const struct sieve_interpreter_extension +ereject_interpreter_extension = { + .ext_def = &ereject_extension, + .run = ext_reject_interpreter_run +}; + +static bool +ext_ereject_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr) +{ + /* Register new command */ + sieve_validator_register_command(valdtr, ext, &ereject_command); + + sieve_validator_extension_register(valdtr, ext, + &ereject_validator_extension, NULL); + return TRUE; +} + +static bool +ext_ereject_interpreter_load(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + sieve_interpreter_extension_register(renv->interp, ext, + &ereject_interpreter_extension, + NULL); + return TRUE; +} + +/* Environment checking */ + +static bool +ext_reject_validator_validate(const struct sieve_extension *ext, + struct sieve_validator *valdtr, + void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg, + bool required) +{ + if (required) { + enum sieve_compile_flags flags = + sieve_validator_compile_flags(valdtr); + + if ((flags & SIEVE_COMPILE_FLAG_NO_ENVELOPE) != 0) { + sieve_argument_validate_error( + valdtr, require_arg, + "the %s extension cannot be used in this context " + "(needs access to message envelope)", + sieve_extension_name(ext)); + return FALSE; + } + } + return TRUE; +} + +static int +ext_reject_interpreter_run(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + void *context ATTR_UNUSED, bool deferred) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + if ((eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) != 0) { + if (!deferred) { + sieve_runtime_error( + renv, NULL, + "the %s extension cannot be used in this context " + "(needs access to message envelope)", + sieve_extension_name(ext)); + } + return SIEVE_EXEC_FAILURE; + } + return SIEVE_EXEC_OK; +} + +/* + * Commands + */ + +/* Forward declarations */ + +static bool +cmd_reject_validate(struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool +cmd_reject_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd); + +/* Reject command + * + * Syntax: + * reject <reason: string> + */ + +static const struct sieve_command_def reject_command = { + .identifier = "reject", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_reject_validate, + .generate = cmd_reject_generate +}; + +/* EReject command + * + * Syntax: + * ereject <reason: string> + */ + +static const struct sieve_command_def ereject_command = { + .identifier = "ereject", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_reject_validate, + .generate = cmd_reject_generate, +}; + +/* + * Operations + */ + +/* Forward declarations */ + +static bool +ext_reject_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +ext_reject_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +/* Reject operation */ + +static const struct sieve_operation_def reject_operation = { + .mnemonic = "REJECT", + .ext_def = &reject_extension, + .dump = ext_reject_operation_dump, + .execute = ext_reject_operation_execute +}; + +/* EReject operation */ + +static const struct sieve_operation_def ereject_operation = { + .mnemonic = "EREJECT", + .ext_def = &ereject_extension, + .dump = ext_reject_operation_dump, + .execute = ext_reject_operation_execute +}; + +/* + * Reject action + */ + +static int +act_reject_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other); +int act_reject_check_conflict(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other); +static void +act_reject_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep); +static int +act_reject_start(const struct sieve_action_exec_env *aenv, void **tr_context); +static int +act_reject_execute(const struct sieve_action_exec_env *aenv, void *tr_context, + bool *keep); +static int +act_reject_commit(const struct sieve_action_exec_env *aenv, void *tr_context); + +const struct sieve_action_def act_reject = { + .name = "reject", + .flags = SIEVE_ACTFLAG_SENDS_RESPONSE, + .check_duplicate = act_reject_check_duplicate, + .check_conflict = act_reject_check_conflict, + .print = act_reject_print, + .start = act_reject_start, + .execute = act_reject_execute, + .commit = act_reject_commit, +}; + +struct act_reject_context { + const char *reason; + bool ereject; +}; + +/* + * Validation + */ + +static bool +cmd_reject_validate(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "reason", + 1, SAAT_STRING)) + return FALSE; + + return sieve_validator_argument_activate(valdtr, cmd, arg, FALSE); +} + +/* + * Code generation + */ + +static bool +cmd_reject_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + if (sieve_command_is(cmd, reject_command)) { + sieve_operation_emit(cgenv->sblock, cmd->ext, + &reject_operation); + } else { + sieve_operation_emit(cgenv->sblock, cmd->ext, + &ereject_operation); + } + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool +ext_reject_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(denv->oprtn)); + sieve_code_descend(denv); + + if (sieve_action_opr_optional_dump(denv, address, NULL) != 0) + return FALSE; + + return sieve_opr_string_dump(denv, address, "reason"); +} + +/* + * Interpretation + */ + +static int +ext_reject_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_operation *oprtn = renv->oprtn; + const struct sieve_extension *this_ext = oprtn->ext; + struct sieve_side_effects_list *slist = NULL; + struct act_reject_context *act; + string_t *reason; + pool_t pool; + int ret; + + /* + * Read data + */ + + /* Optional operands (side effects only) */ + if (sieve_action_opr_optional_read(renv, address, NULL, + &ret, &slist) != 0) + return ret; + + /* Read rejection reason */ + if ((ret = sieve_opr_string_read(renv, address, "reason", + &reason)) <= 0) + return ret; + + /* + * Perform operation + */ + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_ACTIONS)) { + if (sieve_operation_is(oprtn, ereject_operation)) + sieve_runtime_trace(renv, 0, "ereject action"); + else + sieve_runtime_trace(renv, 0, "reject action"); + + sieve_runtime_trace_descend(renv); + sieve_runtime_trace(renv, 0, "reject message with reason `%s'", + str_sanitize(str_c(reason), 64)); + } + + /* Add reject action to the result */ + pool = sieve_result_pool(renv->result); + act = p_new(pool, struct act_reject_context, 1); + act->reason = p_strdup(pool, str_c(reason)); + act->ereject = sieve_operation_is(oprtn, ereject_operation); + + if (sieve_result_add_action(renv, this_ext, + (act->ereject ? "ereject" : "reject"), + &act_reject, slist, (void *)act, + 0, FALSE) < 0) + return SIEVE_EXEC_FAILURE; + return SIEVE_EXEC_OK; +} + +/* + * Action implementation + */ + +struct act_reject_transaction { + bool ignore_reject:1; +}; + +static int +act_reject_check_duplicate(const struct sieve_runtime_env *renv ATTR_UNUSED, + const struct sieve_action *act, + const struct sieve_action *act_other) +{ + if (!sieve_action_is_executed(act_other, renv->result)) { + sieve_runtime_error( + renv, act->location, + "duplicate reject/ereject action not allowed " + "(previously triggered one was here: %s)", + act_other->location); + return -1; + } + + return 1; +} + +int act_reject_check_conflict(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other) +{ + if ((act_other->def->flags & SIEVE_ACTFLAG_TRIES_DELIVER) > 0) { + if (!sieve_action_is_executed(act_other, renv->result)) { + sieve_runtime_error( + renv, act->location, + "reject/ereject action conflicts with other action: " + "the %s action (%s) tries to deliver the message", + act_other->def->name, act_other->location); + return -1; + } + } + + if ((act_other->def->flags & SIEVE_ACTFLAG_SENDS_RESPONSE) > 0) { + struct act_reject_context *rj_ctx; + + if (!sieve_action_is_executed(act_other, renv->result)) { + sieve_runtime_error( + renv, act->location, + "reject/ereject action conflicts with other action: " + "the %s action (%s) also sends a response to the sender", + act_other->def->name, act_other->location); + return -1; + } + + /* Conflicting action was already executed, transform reject + * into discard equivalent. + */ + rj_ctx = (struct act_reject_context *)act->context; + rj_ctx->reason = NULL; + } + + return 0; +} + +static void +act_reject_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep) +{ + struct act_reject_context *rj_ctx = + (struct act_reject_context *)action->context; + + if (rj_ctx->reason != NULL) { + sieve_result_action_printf( + rpenv, "reject message with reason: %s", + str_sanitize(rj_ctx->reason, 128)); + } else { + sieve_result_action_printf( + rpenv, + "reject message without sending a response (discard)"); + } + + *keep = FALSE; +} + +static int +act_reject_start(const struct sieve_action_exec_env *aenv, void **tr_context) +{ + struct act_reject_transaction *trans; + pool_t pool = sieve_result_pool(aenv->result); + + /* Create transaction context */ + trans = p_new(pool, struct act_reject_transaction, 1); + *tr_context = trans; + + return SIEVE_EXEC_OK; +} + +static int +act_reject_execute(const struct sieve_action_exec_env *aenv, + void *tr_context, bool *keep) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct act_reject_context *rj_ctx = + (struct act_reject_context *)aenv->action->context; + struct act_reject_transaction *trans = tr_context; + const struct smtp_address *sender, *recipient; + + sender = sieve_message_get_sender(aenv->msgctx); + recipient = sieve_message_get_orig_recipient(aenv->msgctx); + + if ((eenv->flags & SIEVE_EXECUTE_FLAG_SKIP_RESPONSES) != 0) { + sieve_result_global_log( + aenv, "not sending reject message (skipped)"); + trans->ignore_reject = TRUE; + return SIEVE_EXEC_OK; + } + if (smtp_address_isnull(recipient)) { + sieve_result_global_warning( + aenv, "reject action aborted: envelope recipient is <>"); + trans->ignore_reject = TRUE; + return SIEVE_EXEC_OK; + } + if (rj_ctx->reason == NULL) { + sieve_result_global_log( + aenv, "not sending reject message " + "(would cause second response to sender)"); + trans->ignore_reject = TRUE; + *keep = FALSE; + return SIEVE_EXEC_OK; + } + if (smtp_address_isnull(sender)) { + sieve_result_global_log( + aenv, "not sending reject message to <>"); + trans->ignore_reject = TRUE; + *keep = FALSE; + return SIEVE_EXEC_OK; + } + + *keep = FALSE; + return SIEVE_EXEC_OK; +} + +static int +act_reject_commit(const struct sieve_action_exec_env *aenv, + void *tr_context ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct act_reject_context *rj_ctx = + (struct act_reject_context *)aenv->action->context; + struct act_reject_transaction *trans = tr_context; + const struct smtp_address *sender, *recipient; + int ret; + + sender = sieve_message_get_sender(aenv->msgctx); + recipient = sieve_message_get_orig_recipient(aenv->msgctx); + + if (trans->ignore_reject) + return SIEVE_EXEC_OK; + + if ((ret = sieve_action_reject_mail(aenv, recipient, + rj_ctx->reason)) <= 0) + return ret; + + eenv->exec_status->significant_action_executed = TRUE; + + struct event_passthrough *e = sieve_action_create_finish_event(aenv); + + sieve_result_event_log(aenv, e->event(), + "rejected message from <%s> (%s)", + smtp_address_encode(sender), + (rj_ctx->ereject ? "ereject" : "reject")); + + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/mcht-contains.c b/pigeonhole/src/lib-sieve/mcht-contains.c new file mode 100644 index 0000000..a9b3190 --- /dev/null +++ b/pigeonhole/src/lib-sieve/mcht-contains.c @@ -0,0 +1,66 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Match-type ':contains' + */ + +#include "lib.h" + +#include "sieve-match-types.h" +#include "sieve-comparators.h" +#include "sieve-match.h" + +#include <string.h> +#include <stdio.h> + +/* + * Forward declarations + */ + +static int mcht_contains_match_key + (struct sieve_match_context *mctx, const char *val, size_t val_size, + const char *key, size_t key_size); + +/* + * Match-type object + */ + +const struct sieve_match_type_def contains_match_type = { + SIEVE_OBJECT("contains", + &match_type_operand, SIEVE_MATCH_TYPE_CONTAINS), + .validate_context = sieve_match_substring_validate_context, + .match_key = mcht_contains_match_key +}; + +/* + * Match-type implementation + */ + +/* FIXME: Naive substring match implementation. Should switch to more + * efficient algorithm if large values need to be searched (e.g. message body). + */ +static int mcht_contains_match_key +(struct sieve_match_context *mctx, const char *val, size_t val_size, + const char *key, size_t key_size) +{ + const struct sieve_comparator *cmp = mctx->comparator; + const char *vend = (const char *) val + val_size; + const char *kend = (const char *) key + key_size; + const char *vp = val; + const char *kp = key; + + if ( val_size == 0 ) + return ( key_size == 0 ? 1 : 0 ); + + if ( cmp->def == NULL || cmp->def->char_match == NULL ) + return 0; + + while ( (vp < vend) && (kp < kend) ) { + if ( !cmp->def->char_match(cmp, &vp, vend, &kp, kend) ) + vp++; + } + + return ( kp == kend ? 1 : 0 ); +} + + diff --git a/pigeonhole/src/lib-sieve/mcht-is.c b/pigeonhole/src/lib-sieve/mcht-is.c new file mode 100644 index 0000000..db374bb --- /dev/null +++ b/pigeonhole/src/lib-sieve/mcht-is.c @@ -0,0 +1,52 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Match-type ':is': + */ + +#include "lib.h" + +#include "sieve-match-types.h" +#include "sieve-comparators.h" +#include "sieve-match.h" + +#include <string.h> +#include <stdio.h> + +/* + * Forward declarations + */ + +static int mcht_is_match_key + (struct sieve_match_context *mctx, const char *val, size_t val_size, + const char *key, size_t key_size); + +/* + * Match-type object + */ + +const struct sieve_match_type_def is_match_type = { + SIEVE_OBJECT("is", + &match_type_operand, SIEVE_MATCH_TYPE_IS), + .match_key = mcht_is_match_key +}; + +/* + * Match-type implementation + */ + +static int mcht_is_match_key +(struct sieve_match_context *mctx ATTR_UNUSED, + const char *val, size_t val_size, + const char *key, size_t key_size) +{ + if ( val_size == 0 ) + return ( key_size == 0 ? 1 : 0 ); + + if ( mctx->comparator->def != NULL && mctx->comparator->def->compare != NULL ) + return (mctx->comparator->def->compare(mctx->comparator, + val, val_size, key, key_size) == 0 ? 1 : 0 ); + + return 0; +} + diff --git a/pigeonhole/src/lib-sieve/mcht-matches.c b/pigeonhole/src/lib-sieve/mcht-matches.c new file mode 100644 index 0000000..050fce9 --- /dev/null +++ b/pigeonhole/src/lib-sieve/mcht-matches.c @@ -0,0 +1,440 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Match-type ':matches' + */ + +#include "lib.h" +#include "str.h" + +#include "sieve-match-types.h" +#include "sieve-comparators.h" +#include "sieve-match.h" + +#include <string.h> +#include <stdio.h> + +/* + * Forward declarations + */ + +static int mcht_matches_match_key + (struct sieve_match_context *mctx, const char *val, size_t val_size, + const char *key, size_t key_size); + +/* + * Match-type object + */ + +const struct sieve_match_type_def matches_match_type = { + SIEVE_OBJECT("matches", + &match_type_operand, SIEVE_MATCH_TYPE_MATCHES), + .validate_context = sieve_match_substring_validate_context, + .match_key = mcht_matches_match_key +}; + +/* + * Match-type implementation + */ + +/* Quick 'n dirty debug */ +//#define MATCH_DEBUG +#ifdef MATCH_DEBUG +#define debug_printf(...) printf ("match debug: " __VA_ARGS__) +#else +#define debug_printf(...) +#endif + +/* FIXME: Naive implementation, substitute this with dovecot src/lib/str-find.c + */ +static inline bool _string_find(const struct sieve_comparator *cmp, + const char **valp, const char *vend, const char **keyp, const char *kend) +{ + while ( (*valp < vend) && (*keyp < kend) ) { + if ( !cmp->def->char_match(cmp, valp, vend, keyp, kend) ) + (*valp)++; + } + + return (*keyp == kend); +} + +static char _scan_key_section + (string_t *section, const char **wcardp, const char *key_end) +{ + /* Find next wildcard and resolve escape sequences */ + str_truncate(section, 0); + while ( *wcardp < key_end && **wcardp != '*' && **wcardp != '?') { + if ( **wcardp == '\\' ) { + (*wcardp)++; + } + str_append_c(section, **wcardp); + (*wcardp)++; + } + + /* Record wildcard character or \0 */ + if ( *wcardp < key_end ) { + return **wcardp; + } + + i_assert( *wcardp == key_end ); + return '\0'; +} + +static int mcht_matches_match_key +(struct sieve_match_context *mctx, const char *val, size_t val_size, + const char *key, size_t key_size) +{ + const struct sieve_comparator *cmp = mctx->comparator; + struct sieve_match_values *mvalues; + string_t *mvalue = NULL, *mchars = NULL; + string_t *section, *subsection; + const char *vend, *kend, *vp, *kp, *wp, *pvp; + bool backtrack = FALSE; /* TRUE: match of '?'-connected sections failed */ + char wcard = '\0'; /* Current wildcard */ + char next_wcard = '\0'; /* Next widlcard */ + unsigned int key_offset = 0; + + if ( cmp->def == NULL || cmp->def->char_match == NULL ) + return 0; + + /* Key sections */ + section = t_str_new(32); /* Section (after beginning or *) */ + subsection = t_str_new(32); /* Sub-section (after ?) */ + + /* Mark end of value and key */ + vend = (const char *) val + val_size; + kend = (const char *) key + key_size; + + /* Initialize pointers */ + vp = val; /* Value pointer */ + kp = key; /* Key pointer */ + wp = key; /* Wildcard (key) pointer */ + + /* Start match values list if requested */ + if ( (mvalues = sieve_match_values_start(mctx->runenv)) != NULL ) { + /* Skip ${0} for now; added when match succeeds */ + sieve_match_values_add(mvalues, NULL); + + mvalue = t_str_new(32); /* Match value (*) */ + mchars = t_str_new(32); /* Match characters (.?..?.??) */ + } + + /* Match the pattern: + * <pattern> = <section>*<section>*<section>... + * <section> = <sub-section>?<sub-section>?<sub-section>... + * + * Escape sequences \? and \* need special attention. + */ + + debug_printf("=== Start ===\n"); + debug_printf(" key: %s\n", t_strdup_until(key, kend)); + debug_printf(" value: %s\n", t_strdup_until(val, vend)); + + /* Loop until either key or value ends */ + while (kp < kend && vp < vend ) { + const char *needle, *nend; + + if ( !backtrack ) { + /* Search the next '*' wildcard in the key string */ + + wcard = next_wcard; + + /* Find the needle to look for in the string */ + key_offset = 0; + for (;;) { + next_wcard = _scan_key_section(section, &wp, kend); + + if ( wcard == '\0' || str_len(section) > 0 ) + break; + + if ( next_wcard == '*' ) { + break; + } + + if ( wp < kend ) + wp++; + else + break; + key_offset++; + } + + debug_printf("found wildcard '%c' at pos [%d]\n", + next_wcard, (int) (wp-key)); + + if ( mvalues != NULL ) + str_truncate(mvalue, 0); + } else { + /* Backtracked; '*' wildcard is retained */ + debug_printf("backtracked"); + backtrack = FALSE; + } + + /* Determine what we are looking for */ + needle = str_c(section); + nend = PTR_OFFSET(needle, str_len(section)); + + debug_printf(" section needle: '%s'\n", t_strdup_until(needle, nend)); + debug_printf(" section key: '%s'\n", t_strdup_until(kp, kend)); + debug_printf(" section remnant: '%s'\n", t_strdup_until(wp, kend)); + debug_printf(" value remnant: '%s'\n", t_strdup_until(vp, vend)); + debug_printf(" key offset: %d\n", key_offset); + + pvp = vp; + if ( next_wcard == '\0' ) { + if ( wcard == '\0' ) { + /* No current wildcard; match needs to happen right at the beginning */ + debug_printf("next_wcard = NULL && wcard = NUL; needle should be equal to value.\n"); + + if ( (vend - vp) != (nend - needle) || + !cmp->def->char_match(cmp, &vp, vend, &needle, nend) ) { + debug_printf(" key not equal to value\n"); + break; + } + + } else { + const char *qp, *qend; + size_t slen; + + /* No more wildcards; find the needle substring at the end of string */ + debug_printf("next_wcard = NUL; must find needle at end\n"); + + /* Check if the value is still large enough */ + slen = str_len(section); + if ( (vp + slen) > vend ) { + debug_printf(" wont match: value is too short\n"); + break; + } + + /* Move value pointer to where the needle should be */ + vp = vend - slen; + + /* Record match values */ + qend = vp; + qp = vp - key_offset; + + if ( mvalues != NULL ) + str_append_data(mvalue, pvp, qp-pvp); + + /* Compare needle to end of value string */ + if ( !cmp->def->char_match(cmp, &vp, vend, &needle, nend) ) { + debug_printf(" match at end failed\n"); + break; + } + + /* Add match values */ + if ( mvalues != NULL ) { + /* Append '*' match value */ + sieve_match_values_add(mvalues, mvalue); + + /* Append any initial '?' match values */ + for ( ; qp < qend; qp++ ) + sieve_match_values_add_char(mvalues, *qp); + } + } + + /* Finish match */ + kp = kend; + vp = vend; + + debug_printf(" matched end of value\n"); + break; + } else { + /* Next wildcard found; match needle before next wildcard */ + + const char *prv = NULL; /* Stored value pointer for backtrack */ + const char *prk = NULL; /* Stored key pointer for backtrack */ + const char *prw = NULL; /* Stored wildcard pointer for backtrack */ + const char *chars; + + /* Reset '?' match values */ + if ( mvalues != NULL ) + str_truncate(mchars, 0); + + if ( wcard == '\0' ) { + /* No current wildcard; match needs to happen right at the beginning */ + debug_printf("wcard = NUL; needle should be found at the beginning.\n"); + debug_printf(" begin needle: '%s'\n", t_strdup_until(needle, nend)); + debug_printf(" begin value: '%s'\n", t_strdup_until(vp, vend)); + + if ( !cmp->def->char_match(cmp, &vp, vend, &needle, nend) ) { + debug_printf(" failed to find needle at beginning\n"); + break; + } + + } else { + /* Current wildcard present; match needle between current and next wildcard */ + debug_printf("wcard != NUL; must find needle at an offset (>= %d).\n", + key_offset); + + /* Match may happen at any offset (>= key offset): find substring */ + vp += key_offset; + if ( (vp >= vend) || !_string_find(cmp, &vp, vend, &needle, nend) ) { + debug_printf(" failed to find needle at an offset\n"); + break; + } + + prv = vp - str_len(section); + prk = kp; + prw = wp; + + /* Append match values */ + if ( mvalues != NULL ) { + const char *qend = vp - str_len(section); + const char *qp = qend - key_offset; + + /* Append '*' match value */ + str_append_data(mvalue, pvp, qp-pvp); + + /* Append any initial '?' match values (those that caused the key + * offset. + */ + for ( ; qp < qend; qp++ ) + str_append_c(mchars, *qp); + } + } + + /* Update wildcard and key pointers for next wildcard scan */ + if ( wp < kend ) wp++; + kp = wp; + + /* Scan successive '?' wildcards */ + while ( next_wcard == '?' ) { + debug_printf("next_wcard = '?'; need to match arbitrary character\n"); + + /* Add match value */ + if ( mvalues != NULL ) + str_append_c(mchars, *vp); + + vp++; + + /* Scan for next '?' wildcard */ + next_wcard = _scan_key_section(subsection, &wp, kend); + debug_printf("found next wildcard '%c' at pos [%d] (fixed match)\n", + next_wcard, (int) (wp-key)); + + /* Determine what we are looking for */ + needle = str_c(subsection); + nend = needle + str_len(subsection); + + debug_printf(" sub key: '%s'\n", t_strdup_until(needle, nend)); + debug_printf(" value remnant: '%s'\n", vp <= vend ? t_strdup_until(vp, vend) : ""); + + /* Try matching the needle at fixed position */ + if ( (needle == nend && next_wcard == '\0' && vp < vend ) || + !cmp->def->char_match(cmp, &vp, vend, &needle, nend) ) { + + /* Match failed: now we have a problem. We need to backtrack to the previous + * '*' wildcard occurrence and start scanning for the next possible match. + */ + + debug_printf(" failed fixed match\n"); + + /* Start backtrack */ + if ( prv != NULL && prv + 1 < vend ) { + /* Restore pointers */ + vp = prv; + kp = prk; + wp = prw; + + /* Skip forward one value character to scan the next possible match */ + if ( mvalues != NULL ) + str_append_c(mvalue, *vp); + vp++; + + /* Set wildcard state appropriately */ + wcard = '*'; + next_wcard = '?'; + + /* Backtrack */ + backtrack = TRUE; + + debug_printf(" BACKTRACK\n"); + } + + /* Break '?' wildcard scanning loop */ + break; + } + + /* Update wildcard and key pointers for next wildcard scan */ + if ( wp < kend ) wp++; + kp = wp; + } + + if ( !backtrack ) { + unsigned int i; + + if ( next_wcard == '?' ) { + debug_printf("failed to match '?'\n"); + break; + } + + if ( mvalues != NULL ) { + if ( prv != NULL ) + sieve_match_values_add(mvalues, mvalue); + + chars = (const char *) str_data(mchars); + + for ( i = 0; i < str_len(mchars); i++ ) { + sieve_match_values_add_char(mvalues, chars[i]); + } + } + + if ( next_wcard != '*' ) { + debug_printf("failed to match at end of string\n"); + break; + } + } + } + + /* Check whether string ends in a wildcard + * (avoid scanning the rest of the string) + */ + if ( kp == kend && next_wcard == '*' ) { + /* Add the rest of the string as match value */ + if ( mvalues != NULL ) { + str_truncate(mvalue, 0); + str_append_data(mvalue, vp, vend-vp); + sieve_match_values_add(mvalues, mvalue); + } + + /* Finish match */ + kp = kend; + vp = vend; + + debug_printf("key ends with '*'\n"); + break; + } + + debug_printf("== Loop ==\n"); + } + + /* Eat away a trailing series of *s */ + if ( vp == vend ) { + while ( kp < kend && *kp == '*' ) kp++; + } + + /* By definition, the match is only successful if both value and key pattern + * are exhausted. + */ + + debug_printf("=== Finish ===\n"); + debug_printf(" result: %s\n", (kp == kend && vp == vend) ? "true" : "false"); + + if (kp == kend && vp == vend) { + /* Activate new match values after successful match */ + if ( mvalues != NULL ) { + /* Set ${0} */ + string_t *matched = str_new_const(pool_datastack_create(), val, val_size); + sieve_match_values_set(mvalues, 0, matched); + + /* Commit new match values */ + sieve_match_values_commit(mctx->runenv, &mvalues); + } + return 1; + } + + /* No match; drop collected match values */ + sieve_match_values_abort(&mvalues); + return 0; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/Makefile.am b/pigeonhole/src/lib-sieve/plugins/Makefile.am new file mode 100644 index 0000000..2a1c054 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/Makefile.am @@ -0,0 +1,32 @@ +if BUILD_UNFINISHED +UNFINISHED = +endif + +SUBDIRS = \ + vacation \ + subaddress \ + comparator-i-ascii-numeric \ + relational \ + regex \ + imap4flags \ + copy \ + include \ + body \ + variables \ + enotify \ + notify \ + environment \ + mailbox \ + date \ + spamvirustest \ + ihave \ + editheader \ + duplicate \ + index \ + metadata \ + mime \ + special-use \ + vnd.dovecot \ + $(UNFINISHED) + + diff --git a/pigeonhole/src/lib-sieve/plugins/Makefile.in b/pigeonhole/src/lib-sieve/plugins/Makefile.in new file mode 100644 index 0000000..8443114 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/Makefile.in @@ -0,0 +1,719 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@BUILD_UNFINISHED_TRUE@UNFINISHED = +SUBDIRS = \ + vacation \ + subaddress \ + comparator-i-ascii-numeric \ + relational \ + regex \ + imap4flags \ + copy \ + include \ + body \ + variables \ + enotify \ + notify \ + environment \ + mailbox \ + date \ + spamvirustest \ + ihave \ + editheader \ + duplicate \ + index \ + metadata \ + mime \ + special-use \ + vnd.dovecot \ + $(UNFINISHED) + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/body/Makefile.am b/pigeonhole/src/lib-sieve/plugins/body/Makefile.am new file mode 100644 index 0000000..251b8d6 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/body/Makefile.am @@ -0,0 +1,16 @@ +noinst_LTLIBRARIES = libsieve_ext_body.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tsts = \ + tst-body.c + +libsieve_ext_body_la_SOURCES = \ + ext-body-common.c \ + $(tsts) \ + ext-body.c + +noinst_HEADERS = \ + ext-body-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/body/Makefile.in b/pigeonhole/src/lib-sieve/plugins/body/Makefile.in new file mode 100644 index 0000000..5d58bbd --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/body/Makefile.in @@ -0,0 +1,692 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/body +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_body_la_LIBADD = +am__objects_1 = tst-body.lo +am_libsieve_ext_body_la_OBJECTS = ext-body-common.lo $(am__objects_1) \ + ext-body.lo +libsieve_ext_body_la_OBJECTS = $(am_libsieve_ext_body_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ext-body-common.Plo \ + ./$(DEPDIR)/ext-body.Plo ./$(DEPDIR)/tst-body.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_body_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_body_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_body.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tsts = \ + tst-body.c + +libsieve_ext_body_la_SOURCES = \ + ext-body-common.c \ + $(tsts) \ + ext-body.c + +noinst_HEADERS = \ + ext-body-common.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/body/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/body/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_body.la: $(libsieve_ext_body_la_OBJECTS) $(libsieve_ext_body_la_DEPENDENCIES) $(EXTRA_libsieve_ext_body_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_body_la_OBJECTS) $(libsieve_ext_body_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-body-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-body.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-body.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-body-common.Plo + -rm -f ./$(DEPDIR)/ext-body.Plo + -rm -f ./$(DEPDIR)/tst-body.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ext-body-common.Plo + -rm -f ./$(DEPDIR)/ext-body.Plo + -rm -f ./$(DEPDIR)/tst-body.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/body/ext-body-common.c b/pigeonhole/src/lib-sieve/plugins/body/ext-body-common.c new file mode 100644 index 0000000..c19940e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/body/ext-body-common.c @@ -0,0 +1,102 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "mempool.h" +#include "buffer.h" +#include "array.h" +#include "str.h" +#include "istream.h" +#include "mail-storage.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-interpreter.h" + +#include "ext-body-common.h" + + +/* + * Body part stringlist + */ + +static int ext_body_stringlist_next_item + (struct sieve_stringlist *_strlist, string_t **str_r); +static void ext_body_stringlist_reset + (struct sieve_stringlist *_strlist); + +struct ext_body_stringlist { + struct sieve_stringlist strlist; + + struct sieve_message_part_data *body_parts; + struct sieve_message_part_data *body_parts_iter; +}; + +int ext_body_get_part_list +(const struct sieve_runtime_env *renv, enum tst_body_transform transform, + const char * const *content_types, struct sieve_stringlist **strlist_r) +{ + static const char * const _no_content_types[] = { "", NULL }; + struct ext_body_stringlist *strlist; + struct sieve_message_part_data *body_parts = NULL; + int ret; + + *strlist_r = NULL; + + if ( content_types == NULL ) content_types = _no_content_types; + + switch ( transform ) { + case TST_BODY_TRANSFORM_RAW: + if ( (ret=sieve_message_body_get_raw(renv, &body_parts)) <= 0 ) + return ret; + break; + case TST_BODY_TRANSFORM_CONTENT: + if ( (ret=sieve_message_body_get_content + (renv, content_types, &body_parts)) <= 0 ) + return ret; + break; + case TST_BODY_TRANSFORM_TEXT: + if ( (ret=sieve_message_body_get_text(renv, &body_parts)) <= 0 ) + return ret; + break; + default: + i_unreached(); + } + + strlist = t_new(struct ext_body_stringlist, 1); + strlist->strlist.runenv = renv; + strlist->strlist.next_item = ext_body_stringlist_next_item; + strlist->strlist.reset = ext_body_stringlist_reset; + strlist->body_parts = body_parts; + strlist->body_parts_iter = body_parts; + + *strlist_r = &strlist->strlist; + return SIEVE_EXEC_OK; +} + +static int ext_body_stringlist_next_item +(struct sieve_stringlist *_strlist, string_t **str_r) +{ + struct ext_body_stringlist *strlist = + (struct ext_body_stringlist *)_strlist; + + *str_r = NULL; + + if ( strlist->body_parts_iter->content == NULL ) return 0; + + *str_r = t_str_new_const + (strlist->body_parts_iter->content, strlist->body_parts_iter->size); + strlist->body_parts_iter++; + return 1; +} + +static void ext_body_stringlist_reset +(struct sieve_stringlist *_strlist) +{ + struct ext_body_stringlist *strlist = + (struct ext_body_stringlist *)_strlist; + + strlist->body_parts_iter = strlist->body_parts; +} diff --git a/pigeonhole/src/lib-sieve/plugins/body/ext-body-common.h b/pigeonhole/src/lib-sieve/plugins/body/ext-body-common.h new file mode 100644 index 0000000..290ca13 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/body/ext-body-common.h @@ -0,0 +1,40 @@ +#ifndef EXT_BODY_COMMON_H +#define EXT_BODY_COMMON_H + +/* + * Types + */ + +enum tst_body_transform { + TST_BODY_TRANSFORM_RAW, + TST_BODY_TRANSFORM_CONTENT, + TST_BODY_TRANSFORM_TEXT +}; + +/* + * Extension + */ + +extern const struct sieve_extension_def body_extension; + +/* + * Commands + */ + +extern const struct sieve_command_def body_test; + +/* + * Operations + */ + +extern const struct sieve_operation_def body_operation; + +/* + * Message body part extraction + */ + +int ext_body_get_part_list + (const struct sieve_runtime_env *renv, enum tst_body_transform transform, + const char * const *content_types, struct sieve_stringlist **strlist_r); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/body/ext-body.c b/pigeonhole/src/lib-sieve/plugins/body/ext-body.c new file mode 100644 index 0000000..27218bd --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/body/ext-body.c @@ -0,0 +1,54 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension body + * ------------------ + * + * Authors: Stephan Bosch + * Original CMUSieve implementation by Timo Sirainen + * Specification: RFC 5173 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-body-common.h" + +/* + * Extension + */ + +static bool ext_body_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def body_extension = { + .name = "body", + .validator_load = ext_body_validator_load, + SIEVE_EXT_DEFINE_OPERATION(body_operation) +}; + +static bool ext_body_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register new test */ + sieve_validator_register_command(valdtr, ext, &body_test); + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/body/tst-body.c b/pigeonhole/src/lib-sieve/plugins/body/tst-body.c new file mode 100644 index 0000000..f08dd54 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/body/tst-body.c @@ -0,0 +1,385 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-body-common.h" + +/* + * Body test + * + * Syntax + * body [COMPARATOR] [MATCH-TYPE] [BODY-TRANSFORM] + * <key-list: string-list> + */ + +static bool tst_body_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool tst_body_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_body_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def body_test = { + .identifier = "body", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_body_registered, + .validate = tst_body_validate, + .generate = tst_body_generate +}; + +/* + * Body operation + */ + +static bool ext_body_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int ext_body_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def body_operation = { + .mnemonic = "body", + .ext_def = &body_extension, + .dump = ext_body_operation_dump, + .execute = ext_body_operation_execute +}; + +/* + * Optional operands + */ + +enum tst_body_optional { + OPT_BODY_TRANSFORM = SIEVE_MATCH_OPT_LAST +}; + +/* + * Tagged arguments + */ + +/* Forward declarations */ + +static bool tag_body_transform_validate + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool tag_body_transform_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd); + +/* Argument objects */ + +static const struct sieve_argument_def body_raw_tag = { + .identifier = "raw", + .validate = tag_body_transform_validate, + .generate = tag_body_transform_generate +}; + +static const struct sieve_argument_def body_content_tag = { + .identifier = "content", + .validate = tag_body_transform_validate, + .generate = tag_body_transform_generate +}; + +static const struct sieve_argument_def body_text_tag = { + .identifier = "text", + .validate = tag_body_transform_validate, + .generate = tag_body_transform_generate +}; + +/* Argument implementation */ + +static bool tag_body_transform_validate +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + enum tst_body_transform transform; + struct sieve_ast_argument *tag = *arg; + + /* BODY-TRANSFORM: + * :raw + * / :content <content-types: string-list> + * / :text + */ + if ( (bool) cmd->data ) { + sieve_argument_validate_error(valdtr, *arg, + "the :raw, :content and :text arguments for the body test are mutually " + "exclusive, but more than one was specified"); + return FALSE; + } + + /* Skip tag */ + *arg = sieve_ast_argument_next(*arg); + + /* :content tag has a string-list argument */ + if ( sieve_argument_is(tag, body_raw_tag) ) + transform = TST_BODY_TRANSFORM_RAW; + + else if ( sieve_argument_is(tag, body_text_tag) ) + transform = TST_BODY_TRANSFORM_TEXT; + + else if ( sieve_argument_is(tag, body_content_tag) ) { + /* Check syntax: + * :content <content-types: string-list> + */ + if ( !sieve_validate_tag_parameter + (valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING_LIST, FALSE) ) { + return FALSE; + } + + /* Assign tag parameters */ + tag->parameters = *arg; + *arg = sieve_ast_arguments_detach(*arg,1); + + transform = TST_BODY_TRANSFORM_CONTENT; + } else + return FALSE; + + /* Signal the presence of this tag */ + cmd->data = (void *) TRUE; + + /* Assign context data */ + tag->argument->data = (void *) transform; + + return TRUE; +} + +/* + * Command Registration + */ + +static bool tst_body_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &body_raw_tag, OPT_BODY_TRANSFORM); + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &body_content_tag, OPT_BODY_TRANSFORM); + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &body_text_tag, OPT_BODY_TRANSFORM); + + return TRUE; +} + +/* + * Validation + */ + +static bool tst_body_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + const struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "key list", 1, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate + (valdtr, tst, arg, &mcht_default, &cmp_default); +} + +/* + * Code generation + */ + +static bool tst_body_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + (void)sieve_operation_emit(cgenv->sblock, cmd->ext, &body_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +static bool tag_body_transform_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + enum tst_body_transform transform = + POINTER_CAST_TO(arg->argument->data, enum tst_body_transform); + + sieve_binary_emit_byte(cgenv->sblock, transform); + sieve_generate_argument_parameters(cgenv, cmd, arg); + + return TRUE; +} + +/* + * Code dump + */ + +static bool ext_body_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + unsigned int transform; + int opt_code = 0; + + sieve_code_dumpf(denv, "BODY"); + sieve_code_descend(denv); + + /* Handle any optional arguments */ + for (;;) { + int opt; + + if ( (opt=sieve_match_opr_optional_dump(denv, address, &opt_code)) + < 0 ) + return FALSE; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_BODY_TRANSFORM: + if ( !sieve_binary_read_byte(denv->sblock, address, &transform) ) + return FALSE; + + switch ( transform ) { + case TST_BODY_TRANSFORM_RAW: + sieve_code_dumpf(denv, "BODY-TRANSFORM: RAW"); + break; + case TST_BODY_TRANSFORM_TEXT: + sieve_code_dumpf(denv, "BODY-TRANSFORM: TEXT"); + break; + case TST_BODY_TRANSFORM_CONTENT: + sieve_code_dumpf(denv, "BODY-TRANSFORM: CONTENT"); + + sieve_code_descend(denv); + if ( !sieve_opr_stringlist_dump(denv, address, "content types") ) + return FALSE; + sieve_code_ascend(denv); + break; + default: + return FALSE; + } + break; + default: + return FALSE; + } + }; + + return sieve_opr_stringlist_dump(denv, address, "key list"); +} + +/* + * Interpretation + */ + +static int ext_body_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + int opt_code = 0; + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + unsigned int transform = TST_BODY_TRANSFORM_TEXT; + struct sieve_stringlist *ctype_list, *value_list, *key_list; + bool mvalues_active; + const char * const *content_types = NULL; + int match, ret; + + /* + * Read operands + */ + + /* Optional operands */ + + ctype_list = NULL; + for (;;) { + int opt; + + if ( (opt=sieve_match_opr_optional_read + (renv, address, &opt_code, &ret, &cmp, &mcht)) < 0 ) + return ret; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_BODY_TRANSFORM: + if ( !sieve_binary_read_byte(renv->sblock, address, &transform) || + transform > TST_BODY_TRANSFORM_TEXT ) { + sieve_runtime_trace_error(renv, "invalid body transform type"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( transform == TST_BODY_TRANSFORM_CONTENT && + (ret=sieve_opr_stringlist_read + (renv, address, "content-type-list", &ctype_list)) <= 0 ) + return ret; + + break; + + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + } + + /* Read key-list */ + + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; + + if ( ctype_list != NULL && sieve_stringlist_read_all + (ctype_list, pool_datastack_create(), &content_types) < 0 ) { + sieve_runtime_trace_error(renv, "failed to read content-type-list operand"); + return ctype_list->exec_status; + } + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "body test"); + + /* Extract requested parts */ + if ( (ret=ext_body_get_part_list(renv, + (enum tst_body_transform) transform, content_types,&value_list)) <= 0 ) + return ret; + + /* Disable match values processing as required by RFC */ + mvalues_active = sieve_match_values_set_enabled(renv, FALSE); + + /* Perform match */ + match = sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret); + + /* Restore match values processing */ + (void)sieve_match_values_set_enabled(renv, mvalues_active); + + if ( match < 0 ) + return ret; + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.am b/pigeonhole/src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.am new file mode 100644 index 0000000..8e385c5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.am @@ -0,0 +1,8 @@ +noinst_LTLIBRARIES = libsieve_ext_comparator-i-ascii-numeric.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_comparator_i_ascii_numeric_la_SOURCES = \ + ext-cmp-i-ascii-numeric.c diff --git a/pigeonhole/src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.in b/pigeonhole/src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.in new file mode 100644 index 0000000..35ef51f --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.in @@ -0,0 +1,674 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/comparator-i-ascii-numeric +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_comparator_i_ascii_numeric_la_LIBADD = +am_libsieve_ext_comparator_i_ascii_numeric_la_OBJECTS = \ + ext-cmp-i-ascii-numeric.lo +libsieve_ext_comparator_i_ascii_numeric_la_OBJECTS = \ + $(am_libsieve_ext_comparator_i_ascii_numeric_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ext-cmp-i-ascii-numeric.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_comparator_i_ascii_numeric_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_comparator_i_ascii_numeric_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_comparator-i-ascii-numeric.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_comparator_i_ascii_numeric_la_SOURCES = \ + ext-cmp-i-ascii-numeric.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_comparator-i-ascii-numeric.la: $(libsieve_ext_comparator_i_ascii_numeric_la_OBJECTS) $(libsieve_ext_comparator_i_ascii_numeric_la_DEPENDENCIES) $(EXTRA_libsieve_ext_comparator_i_ascii_numeric_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_comparator_i_ascii_numeric_la_OBJECTS) $(libsieve_ext_comparator_i_ascii_numeric_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-cmp-i-ascii-numeric.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-cmp-i-ascii-numeric.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ext-cmp-i-ascii-numeric.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c b/pigeonhole/src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c new file mode 100644 index 0000000..20ec38b --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c @@ -0,0 +1,160 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension comparator-i;ascii-numeric + * ------------------------------------ + * + * Author: Stephan Bosch + * Specification: RFC 2244 + * Implementation: full + * Status: testing + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-comparators.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include <ctype.h> + +/* + * Forward declarations + */ + +static const struct sieve_operand_def my_comparator_operand; + +const struct sieve_comparator_def i_ascii_numeric_comparator; + +/* + * Extension + */ + +static bool ext_cmp_i_ascii_numeric_validator_load + (const struct sieve_extension *ext, struct sieve_validator *validator); + +const struct sieve_extension_def comparator_i_ascii_numeric_extension = { + .name = "comparator-i;ascii-numeric", + .validator_load = ext_cmp_i_ascii_numeric_validator_load, + SIEVE_EXT_DEFINE_OPERAND(my_comparator_operand) +}; + +static bool ext_cmp_i_ascii_numeric_validator_load +(const struct sieve_extension *ext, struct sieve_validator *validator) +{ + sieve_comparator_register(validator, ext, &i_ascii_numeric_comparator); + return TRUE; +} + +/* + * Operand + */ + +static const struct sieve_extension_objects ext_comparators = + SIEVE_EXT_DEFINE_COMPARATOR(i_ascii_numeric_comparator); + +static const struct sieve_operand_def my_comparator_operand = { + .name = "comparator-i;ascii-numeric", + .ext_def = &comparator_i_ascii_numeric_extension, + .class = &sieve_comparator_operand_class, + .interface = &ext_comparators +}; + +/* + * Comparator + */ + +/* Forward declarations */ + +static int cmp_i_ascii_numeric_compare + (const struct sieve_comparator *cmp, + const char *val1, size_t val1_size, const char *val2, size_t val2_size); + +/* Comparator object */ + +const struct sieve_comparator_def i_ascii_numeric_comparator = { + SIEVE_OBJECT("i;ascii-numeric", + &my_comparator_operand, 0), + .flags = + SIEVE_COMPARATOR_FLAG_ORDERING | + SIEVE_COMPARATOR_FLAG_EQUALITY, + .compare = cmp_i_ascii_numeric_compare +}; + +/* Comparator implementation */ + +static int cmp_i_ascii_numeric_compare + (const struct sieve_comparator *cmp ATTR_UNUSED, + const char *val, size_t val_size, const char *key, size_t key_size) +{ + const char *vend = val + val_size; + const char *kend = key + key_size; + const char *vp = val; + const char *kp = key; + int digits, i; + + /* RFC 4790: All input is valid; strings that do not start with a digit + * represent positive infinity. + */ + if ( !i_isdigit(*vp) ) { + if ( i_isdigit(*kp) ) { + /* Value is greater */ + return 1; + } + } else { + if ( !i_isdigit(*kp) ) { + /* Value is less */ + return -1; + } + } + + /* Ignore leading zeros */ + + while ( *vp == '0' && vp < vend ) + vp++; + + while ( *kp == '0' && kp < kend ) + kp++; + + /* Check whether both numbers are equally long in terms of digits */ + + digits = 0; + while ( vp < vend && kp < kend && i_isdigit(*vp) && i_isdigit(*kp) ) { + vp++; + kp++; + digits++; + } + + if ( vp == vend || !i_isdigit(*vp) ) { + if ( kp != kend && i_isdigit(*kp) ) { + /* Value is less */ + return -1; + } + } else { + /* Value is greater */ + return 1; + } + + /* Equally long: compare digits */ + + vp -= digits; + kp -= digits; + i = 0; + while ( i < digits ) { + if ( *vp > *kp ) + return 1; + else if ( *vp < *kp ) + return -1; + + kp++; + vp++; + i++; + } + + return 0; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/copy/Makefile.am b/pigeonhole/src/lib-sieve/plugins/copy/Makefile.am new file mode 100644 index 0000000..483032a --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/copy/Makefile.am @@ -0,0 +1,18 @@ +noinst_LTLIBRARIES = libsieve_ext_copy.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_copy_la_SOURCES = \ + ext-copy.c + +public_headers = \ + sieve-ext-copy.h + +headers = + +pkginc_libdir=$(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) + diff --git a/pigeonhole/src/lib-sieve/plugins/copy/Makefile.in b/pigeonhole/src/lib-sieve/plugins/copy/Makefile.in new file mode 100644 index 0000000..9824089 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/copy/Makefile.in @@ -0,0 +1,735 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/copy +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(pkginc_lib_HEADERS) $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_copy_la_LIBADD = +am_libsieve_ext_copy_la_OBJECTS = ext-copy.lo +libsieve_ext_copy_la_OBJECTS = $(am_libsieve_ext_copy_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ext-copy.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_copy_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_copy_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkginc_libdir)" +HEADERS = $(noinst_HEADERS) $(pkginc_lib_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_copy.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_copy_la_SOURCES = \ + ext-copy.c + +public_headers = \ + sieve-ext-copy.h + +headers = +pkginc_libdir = $(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/copy/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/copy/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_copy.la: $(libsieve_ext_copy_la_OBJECTS) $(libsieve_ext_copy_la_DEPENDENCIES) $(EXTRA_libsieve_ext_copy_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_copy_la_OBJECTS) $(libsieve_ext_copy_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-copy.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkginc_libHEADERS: $(pkginc_lib_HEADERS) + @$(NORMAL_INSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkginc_libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkginc_libdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkginc_libdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkginc_libdir)" || exit $$?; \ + done + +uninstall-pkginc_libHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkginc_libdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(pkginc_libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-copy.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pkginc_libHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ext-copy.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkginc_libHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-pkginc_libHEADERS install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pkginc_libHEADERS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/copy/ext-copy.c b/pigeonhole/src/lib-sieve/plugins/copy/ext-copy.c new file mode 100644 index 0000000..e7db9dd --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/copy/ext-copy.c @@ -0,0 +1,183 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension copy + * -------------- + * + * Authors: Stephan Bosch + * Specification: RFC 3894 + * Implementation: full + * Status: testing + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "sieve-ext-copy.h" + +/* + * Forward declarations + */ + +static const struct sieve_argument_def copy_tag; +static const struct sieve_operand_def copy_side_effect_operand; + +/* + * Extension + */ + +static bool +ext_copy_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr); + +const struct sieve_extension_def copy_extension = { + .name = "copy", + .validator_load = ext_copy_validator_load, + SIEVE_EXT_DEFINE_OPERAND(copy_side_effect_operand), +}; + +static bool +ext_copy_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr) +{ + /* Register copy tag with redirect and fileinto commands and we don't + care whether these commands are registered or even whether they will + be registered at all. The validator handles either situation + gracefully. + */ + sieve_validator_register_external_tag(valdtr, "redirect", ext, + ©_tag, SIEVE_OPT_SIDE_EFFECT); + sieve_validator_register_external_tag(valdtr, "fileinto", ext, + ©_tag, SIEVE_OPT_SIDE_EFFECT); + return TRUE; +} + +/* + * Side effect + */ + +static void +seff_copy_print(const struct sieve_side_effect *seffect, + const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep); +static int +seff_copy_post_execute(const struct sieve_side_effect *seffect ATTR_UNUSED, + const struct sieve_action_exec_env *aenv ATTR_UNUSED, + void *tr_context ATTR_UNUSED, + void *se_tr_context ATTR_UNUSED, bool *keep); + +const struct sieve_side_effect_def copy_side_effect = { + SIEVE_OBJECT("copy", ©_side_effect_operand, 0), + .to_action = &act_store, + .print = seff_copy_print, + .post_execute = seff_copy_post_execute, +}; + +/* + * Tagged argument + */ + +static bool +tag_copy_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, struct sieve_command *cmd); +static bool +tag_copy_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, struct sieve_command *cmd); + +static const struct sieve_argument_def copy_tag = { + .identifier = "copy", + .validate = tag_copy_validate, + .generate = tag_copy_generate, +}; + +/* + * Operand + */ + +static const struct sieve_extension_objects ext_side_effects = + SIEVE_EXT_DEFINE_SIDE_EFFECT(copy_side_effect); + +static const struct sieve_operand_def copy_side_effect_operand = { + .name = "copy operand", + .ext_def = ©_extension, + .class = &sieve_side_effect_operand_class, + .interface = &ext_side_effects, +}; + +/* + * Tag registration + */ + +void sieve_ext_copy_register_tag(struct sieve_validator *valdtr, + const struct sieve_extension *copy_ext, + const char *command) +{ + if (sieve_validator_extension_loaded(valdtr, copy_ext)) { + sieve_validator_register_external_tag( + valdtr, command, copy_ext, ©_tag, + SIEVE_OPT_SIDE_EFFECT); + } +} + +/* + * Tag validation + */ + +static bool +tag_copy_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_ast_argument **arg ATTR_UNUSED, + struct sieve_command *cmd ATTR_UNUSED) +{ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Code generation + */ + +static bool +tag_copy_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + if (sieve_ast_argument_type(arg) != SAAT_TAG) + return FALSE; + + sieve_opr_side_effect_emit(cgenv->sblock, sieve_argument_ext(arg), + ©_side_effect); + return TRUE; +} + +/* + * Side effect implementation + */ + +static void +seff_copy_print(const struct sieve_side_effect *seffect ATTR_UNUSED, + const struct sieve_action *action ATTR_UNUSED, + const struct sieve_result_print_env *rpenv, bool *keep) +{ + sieve_result_seffect_printf(rpenv, "preserve implicit keep"); + *keep = TRUE; +} + +static int +seff_copy_post_execute(const struct sieve_side_effect *seffect ATTR_UNUSED, + const struct sieve_action_exec_env *aenv ATTR_UNUSED, + void *tr_context ATTR_UNUSED, + void *se_tr_context ATTR_UNUSED, bool *keep) +{ + *keep = TRUE; + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/copy/sieve-ext-copy.h b/pigeonhole/src/lib-sieve/plugins/copy/sieve-ext-copy.h new file mode 100644 index 0000000..faf19dc --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/copy/sieve-ext-copy.h @@ -0,0 +1,21 @@ +#ifndef SIEVE_EXT_COPY_H +#define SIEVE_EXT_COPY_H + +/* sieve_ext_copy_get_extension(): + * Get the extension struct for the copy extension. + */ +static inline const struct sieve_extension *sieve_ext_copy_get_extension +(struct sieve_instance *svinst) +{ + return sieve_extension_get_by_name(svinst, "copy"); +} + +/* sieve_ext_copy_register_tag(): + * Register the :copy tagged argument for a command other than fileinto and + * redirect. + */ +void sieve_ext_copy_register_tag + (struct sieve_validator *valdtr, const struct sieve_extension *copy_ext, + const char *command); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/date/Makefile.am b/pigeonhole/src/lib-sieve/plugins/date/Makefile.am new file mode 100644 index 0000000..bf257ac --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/date/Makefile.am @@ -0,0 +1,16 @@ +noinst_LTLIBRARIES = libsieve_ext_date.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-date.c + +libsieve_ext_date_la_SOURCES = \ + $(tests) \ + ext-date-common.c \ + ext-date.c + +noinst_HEADERS = \ + ext-date-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/date/Makefile.in b/pigeonhole/src/lib-sieve/plugins/date/Makefile.in new file mode 100644 index 0000000..0bc3ec0 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/date/Makefile.in @@ -0,0 +1,692 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/date +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_date_la_LIBADD = +am__objects_1 = tst-date.lo +am_libsieve_ext_date_la_OBJECTS = $(am__objects_1) ext-date-common.lo \ + ext-date.lo +libsieve_ext_date_la_OBJECTS = $(am_libsieve_ext_date_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ext-date-common.Plo \ + ./$(DEPDIR)/ext-date.Plo ./$(DEPDIR)/tst-date.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_date_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_date_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_date.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-date.c + +libsieve_ext_date_la_SOURCES = \ + $(tests) \ + ext-date-common.c \ + ext-date.c + +noinst_HEADERS = \ + ext-date-common.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/date/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/date/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_date.la: $(libsieve_ext_date_la_OBJECTS) $(libsieve_ext_date_la_DEPENDENCIES) $(EXTRA_libsieve_ext_date_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_date_la_OBJECTS) $(libsieve_ext_date_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-date-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-date.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-date.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-date-common.Plo + -rm -f ./$(DEPDIR)/ext-date.Plo + -rm -f ./$(DEPDIR)/tst-date.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ext-date-common.Plo + -rm -f ./$(DEPDIR)/ext-date.Plo + -rm -f ./$(DEPDIR)/tst-date.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/date/ext-date-common.c b/pigeonhole/src/lib-sieve/plugins/date/ext-date-common.c new file mode 100644 index 0000000..7493b87 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/date/ext-date-common.c @@ -0,0 +1,593 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "utc-offset.h" +#include "str.h" +#include "iso8601-date.h" +#include "message-date.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-interpreter.h" +#include "sieve-message.h" + +#include "ext-date-common.h" + +#include <time.h> +#include <ctype.h> + +struct ext_date_context { + time_t current_date; + int zone_offset; +}; + +/* + * Runtime initialization + */ + +static int ext_date_runtime_init +(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + void *context ATTR_UNUSED, bool deferred ATTR_UNUSED) +{ + struct ext_date_context *dctx; + pool_t pool; + struct timeval msg_time; + time_t current_date; + struct tm *tm; + int zone_offset; + + /* Get current time at instance main script is started */ + sieve_message_context_time(renv->msgctx, &msg_time); + current_date = msg_time.tv_sec; + + tm = localtime(¤t_date); + zone_offset = utc_offset(tm, current_date); + + /* Create context */ + pool = sieve_message_context_pool(renv->msgctx); + dctx = p_new(pool, struct ext_date_context, 1); + dctx->current_date = current_date; + dctx->zone_offset = zone_offset; + + sieve_message_context_extension_set + (renv->msgctx, ext, (void *) dctx); + return SIEVE_EXEC_OK; +} + +static struct sieve_interpreter_extension +date_interpreter_extension = { + .ext_def = &date_extension, + .run = ext_date_runtime_init +}; + +bool ext_date_interpreter_load +(const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + /* Register runtime hook to obtain stript start timestamp */ + if ( renv->msgctx == NULL || + sieve_message_context_extension_get(renv->msgctx, ext) == NULL ) { + sieve_interpreter_extension_register + (renv->interp, ext, &date_interpreter_extension, NULL); + } + + return TRUE; +} + +/* + * Zone string + */ + +bool ext_date_parse_timezone +(const char *zone, int *zone_offset_r) +{ + const unsigned char *str = (const unsigned char *) zone; + size_t len = strlen(zone); + + if (len == 5 && (*str == '+' || *str == '-')) { + int offset; + + if (!i_isdigit(str[1]) || !i_isdigit(str[2]) || + !i_isdigit(str[3]) || !i_isdigit(str[4])) + return FALSE; + + offset = ((str[1]-'0') * 10 + (str[2]-'0')) * 60 + + (str[3]-'0') * 10 + (str[4]-'0'); + + if ( zone_offset_r != NULL ) + *zone_offset_r = *str == '+' ? offset : -offset; + + return TRUE; + } + + return FALSE; +} + +/* + * Current date + */ + +time_t ext_date_get_current_date +(const struct sieve_runtime_env *renv, int *zone_offset_r) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct ext_date_context *dctx = (struct ext_date_context *) + sieve_message_context_extension_get(renv->msgctx, this_ext); + + if ( dctx == NULL ) { + ext_date_runtime_init(this_ext, renv, NULL, FALSE); + dctx = (struct ext_date_context *) + sieve_message_context_extension_get(renv->msgctx, this_ext); + + i_assert(dctx != NULL); + } + + /* Read script start timestamp from message context */ + + if ( zone_offset_r != NULL ) + *zone_offset_r = dctx->zone_offset; + + return dctx->current_date; +} + +/* + * Date parts + */ + +/* "year" => the year, "0000" .. "9999". + */ + +static const char *ext_date_year_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part year_date_part = { + "year", + ext_date_year_part_get +}; + +/* "month" => the month, "01" .. "12". + */ + +static const char *ext_date_month_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part month_date_part = { + "month", + ext_date_month_part_get +}; + +/* "day" => the day, "01" .. "31". + */ + +static const char *ext_date_day_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part day_date_part = { + "day", + ext_date_day_part_get +}; + +/* "date" => the date in "yyyy-mm-dd" format. + */ + +static const char *ext_date_date_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part date_date_part = { + "date", + ext_date_date_part_get +}; + +/* "julian" => the Modified Julian Day, that is, the date + * expressed as an integer number of days since + * 00:00 UTC on November 17, 1858 (using the Gregorian + * calendar). This corresponds to the regular + * Julian Day minus 2400000.5. Sample routines to + * convert to and from modified Julian dates are + * given in Appendix A. + */ + +static const char *ext_date_julian_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part julian_date_part = { + "julian", + ext_date_julian_part_get +}; + +/* "hour" => the hour, "00" .. "23". + */ +static const char *ext_date_hour_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part hour_date_part = { + "hour", + ext_date_hour_part_get +}; + +/* "minute" => the minute, "00" .. "59". + */ +static const char *ext_date_minute_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part minute_date_part = { + "minute", + ext_date_minute_part_get +}; + +/* "second" => the second, "00" .. "60". + */ +static const char *ext_date_second_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part second_date_part = { + "second", + ext_date_second_part_get +}; + +/* "time" => the time in "hh:mm:ss" format. + */ +static const char *ext_date_time_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part time_date_part = { + "time", + ext_date_time_part_get +}; + +/* "iso8601" => the date and time in restricted ISO 8601 format. + */ +static const char *ext_date_iso8601_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part iso8601_date_part = { + "iso8601", + ext_date_iso8601_part_get +}; + +/* "std11" => the date and time in a format appropriate + * for use in a Date: header field [RFC2822]. + */ +static const char *ext_date_std11_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part std11_date_part = { + "std11", + ext_date_std11_part_get +}; + +/* "zone" => the time zone in use. If the user specified a + * time zone with ":zone", "zone" will + * contain that value. If :originalzone is specified + * this value will be the original zone specified + * in the date-time value. If neither argument is + * specified the value will be the server's default + * time zone in offset format "+hhmm" or "-hhmm". An + * offset of 0 (Zulu) always has a positive sign. + */ +static const char *ext_date_zone_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part zone_date_part = { + "zone", + ext_date_zone_part_get +}; + +/* "weekday" => the day of the week expressed as an integer between + * "0" and "6". "0" is Sunday, "1" is Monday, etc. + */ +static const char *ext_date_weekday_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part weekday_date_part = { + "weekday", + ext_date_weekday_part_get +}; + +/* + * Date part extraction + */ + +static const struct ext_date_part *date_parts[] = { + &year_date_part, &month_date_part, &day_date_part, &date_date_part, + &julian_date_part, &hour_date_part, &minute_date_part, &second_date_part, + &time_date_part, &iso8601_date_part, &std11_date_part, &zone_date_part, + &weekday_date_part +}; + +unsigned int date_parts_count = N_ELEMENTS(date_parts); + +const struct ext_date_part *ext_date_part_find(const char *part) +{ + unsigned int i; + + for ( i = 0; i < date_parts_count; i++ ) { + if ( strcasecmp(date_parts[i]->identifier, part) == 0 ) { + return date_parts[i]; + } + } + + return NULL; +} + +const char *ext_date_part_extract +(const struct ext_date_part *dpart, struct tm *tm, int zone_offset) +{ + if ( dpart == NULL || dpart->get_string == NULL ) + return NULL; + + return dpart->get_string(tm, zone_offset); +} + +/* + * Date part implementations + */ + +static const char *month_names[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +static const char *weekday_names[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + +static const char *ext_date_year_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + return t_strdup_printf("%04d", tm->tm_year + 1900); +} + +static const char *ext_date_month_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + return t_strdup_printf("%02d", tm->tm_mon + 1); +} + +static const char *ext_date_day_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + return t_strdup_printf("%02d", tm->tm_mday); +} + +static const char *ext_date_date_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + return t_strdup_printf("%04d-%02d-%02d", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); +} + +static const char *ext_date_julian_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + int year = tm->tm_year+1900; + int month = tm->tm_mon+1; + int day = tm->tm_mday; + int c, ya, jd; + + /* Modified from RFC 5260 Appendix A (refer to Errata) */ + + if ( month > 2 ) + month -= 3; + else { + month += 9; + year--; + } + + c = year / 100; + ya = year - c * 100; + + jd = c * 146097 / 4 + ya * 1461 / 4 + (month * 153 + 2) / 5 + day + 1721119; + + return t_strdup_printf("%d", jd - 2400001); +} + +static const char *ext_date_hour_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + return t_strdup_printf("%02d", tm->tm_hour); +} + +static const char *ext_date_minute_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + return t_strdup_printf("%02d", tm->tm_min); +} + +static const char *ext_date_second_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + return t_strdup_printf("%02d", tm->tm_sec); +} + +static const char *ext_date_time_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + return t_strdup_printf("%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); +} + +static const char *ext_date_iso8601_part_get +(struct tm *tm, int zone_offset) +{ + /* From RFC: `The restricted ISO 8601 format is specified by the date-time + * ABNF production given in [RFC3339], Section 5.6, with the added + * restrictions that the letters "T" and "Z" MUST be in upper case, and + * a time zone offset of zero MUST be represented by "Z" and not "+00:00". + */ + if ( zone_offset == 0 ) + zone_offset = INT_MAX; + + return iso8601_date_create_tm(tm, zone_offset); +} + + +static const char *ext_date_std11_part_get +(struct tm *tm, int zone_offset) +{ + return t_strdup_printf("%s, %02d %s %04d %02d:%02d:%02d %s", + weekday_names[tm->tm_wday], + tm->tm_mday, + month_names[tm->tm_mon], + tm->tm_year+1900, + tm->tm_hour, tm->tm_min, tm->tm_sec, + ext_date_zone_part_get(tm, zone_offset)); +} + +static const char *ext_date_zone_part_get +(struct tm *tm ATTR_UNUSED, int zone_offset) +{ + bool negative; + int offset = zone_offset; + + if (zone_offset >= 0) + negative = FALSE; + else { + negative = TRUE; + offset = -offset; + } + + return t_strdup_printf + ("%c%02d%02d", negative ? '-' : '+', offset / 60, offset % 60); +} + +static const char *ext_date_weekday_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + return t_strdup_printf("%d", tm->tm_wday); +} + +/* + * Date stringlist + */ + +/* Forward declarations */ + +static int ext_date_stringlist_next_item + (struct sieve_stringlist *_strlist, string_t **str_r); +static void ext_date_stringlist_reset + (struct sieve_stringlist *_strlist); + +/* Stringlist object */ + +struct ext_date_stringlist { + struct sieve_stringlist strlist; + + struct sieve_stringlist *field_values; + int time_zone; + const struct ext_date_part *date_part; + + time_t local_time; + int local_zone; + + bool read:1; +}; + +struct sieve_stringlist *ext_date_stringlist_create +(const struct sieve_runtime_env *renv, struct sieve_stringlist *field_values, + int time_zone, const struct ext_date_part *dpart) +{ + struct ext_date_stringlist *strlist; + + strlist = t_new(struct ext_date_stringlist, 1); + strlist->strlist.runenv = renv; + strlist->strlist.exec_status = SIEVE_EXEC_OK; + strlist->strlist.next_item = ext_date_stringlist_next_item; + strlist->strlist.reset = ext_date_stringlist_reset; + strlist->field_values = field_values; + strlist->time_zone = time_zone; + strlist->date_part = dpart; + + strlist->local_time = ext_date_get_current_date(renv, &strlist->local_zone); + + return &strlist->strlist; +} + +/* Stringlist implementation */ + +static int ext_date_stringlist_next_item +(struct sieve_stringlist *_strlist, string_t **str_r) +{ + struct ext_date_stringlist *strlist = + (struct ext_date_stringlist *) _strlist; + bool got_date = FALSE; + time_t date_value; + const char *part_value = NULL; + int original_zone; + + /* Check whether the item was already read */ + if ( strlist->read ) return 0; + + if ( strlist->field_values != NULL ) { + string_t *hdr_item; + const char *header_value, *date_string; + int ret; + + /* Use header field value */ + + /* Read first */ + if ( (ret=sieve_stringlist_next_item(strlist->field_values, &hdr_item)) + <= 0 ) + return ret; + + /* Extract the date string value */ + + header_value = str_c(hdr_item); + date_string = strrchr(header_value, ';'); + + if ( date_string == NULL ) { + /* Direct header value */ + date_string = header_value; + } else { + /* Delimited by ';', e.g. a Received: header */ + date_string++; + } + + /* Parse the date value */ + if ( message_date_parse((const unsigned char *) date_string, + strlen(date_string), &date_value, &original_zone) ) { + got_date = TRUE; + } + } else { + /* Use time stamp recorded at the time the script first started */ + date_value = strlist->local_time; + original_zone = strlist->local_zone; + got_date = TRUE; + } + + if ( got_date ) { + int wanted_zone; + struct tm *date_tm; + + /* Apply wanted timezone */ + + switch ( strlist->time_zone ) { + case EXT_DATE_TIMEZONE_LOCAL: + wanted_zone = strlist->local_zone; + break; + case EXT_DATE_TIMEZONE_ORIGINAL: + wanted_zone = original_zone; + break; + default: + wanted_zone = strlist->time_zone; + } + + date_value += wanted_zone * 60; + + /* Convert timestamp to struct tm */ + + if ( (date_tm=gmtime(&date_value)) != NULL ) { + /* Extract the date part */ + part_value = ext_date_part_extract + (strlist->date_part, date_tm, wanted_zone); + } + } + + strlist->read = TRUE; + + if ( part_value == NULL ) + return 0; + + *str_r = t_str_new_const(part_value, strlen(part_value)); + return 1; +} + +static void ext_date_stringlist_reset +(struct sieve_stringlist *_strlist) +{ + struct ext_date_stringlist *strlist = + (struct ext_date_stringlist *) _strlist; + + if ( strlist->field_values != NULL ) + sieve_stringlist_reset(strlist->field_values); + strlist->read = FALSE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/date/ext-date-common.h b/pigeonhole/src/lib-sieve/plugins/date/ext-date-common.h new file mode 100644 index 0000000..116af3e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/date/ext-date-common.h @@ -0,0 +1,80 @@ +#ifndef EXT_DATE_COMMON_H +#define EXT_DATE_COMMON_H + +#include "sieve-common.h" + +#include <time.h> + +/* + * Extension + */ + +extern const struct sieve_extension_def date_extension; + +bool ext_date_interpreter_load + (const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED); + +/* + * Tests + */ + +extern const struct sieve_command_def date_test; +extern const struct sieve_command_def currentdate_test; + +/* + * Operations + */ + +enum ext_date_opcode { + EXT_DATE_OPERATION_DATE, + EXT_DATE_OPERATION_CURRENTDATE +}; + +extern const struct sieve_operation_def date_operation; +extern const struct sieve_operation_def currentdate_operation; + +/* + * Zone string + */ + +bool ext_date_parse_timezone(const char *zone, int *zone_offset_r); + +/* + * Current date + */ + +time_t ext_date_get_current_date + (const struct sieve_runtime_env *renv, int *zone_offset_r); + +/* + * Date part + */ + +struct ext_date_part { + const char *identifier; + + const char *(*get_string)(struct tm *tm, int zone_offset); +}; + +const struct ext_date_part *ext_date_part_find(const char *part); + +const char *ext_date_part_extract + (const struct ext_date_part *dpart, struct tm *tm, int zone_offset); + +/* + * Date stringlist + */ + +enum ext_date_timezone_special { + EXT_DATE_TIMEZONE_LOCAL = 100, + EXT_DATE_TIMEZONE_ORIGINAL = 101 +}; + +struct sieve_stringlist *ext_date_stringlist_create +(const struct sieve_runtime_env *renv, struct sieve_stringlist *field_values, + int time_zone, const struct ext_date_part *dpart); + + + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/date/ext-date.c b/pigeonhole/src/lib-sieve/plugins/date/ext-date.c new file mode 100644 index 0000000..3880d82 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/date/ext-date.c @@ -0,0 +1,62 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension date + * ------------------ + * + * Authors: Stephan Bosch + * Specification: RFC 5260 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-common.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-date-common.h" + +/* + * Extension + */ + +static bool ext_date_validator_load +(const struct sieve_extension *ext, struct sieve_validator *validator); + +const struct sieve_operation_def *ext_date_operations[] = { + &date_operation, + ¤tdate_operation +}; + +const struct sieve_extension_def date_extension = { + .name = "date", + .validator_load = ext_date_validator_load, + .interpreter_load = ext_date_interpreter_load, + SIEVE_EXT_DEFINE_OPERATIONS(ext_date_operations) +}; + +static bool ext_date_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register new test */ + sieve_validator_register_command(valdtr, ext, &date_test); + sieve_validator_register_command(valdtr, ext, ¤tdate_test); + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/date/tst-date.c b/pigeonhole/src/lib-sieve/plugins/date/tst-date.c new file mode 100644 index 0000000..60ee92c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/date/tst-date.c @@ -0,0 +1,496 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" +#include "sieve-message.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-date-common.h" + +#include <time.h> + +/* + * Tests + */ + +static bool tst_date_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_date_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +/* Date test + * + * Syntax: + * date [<":zone" <time-zone: string>> / ":originalzone"] + * [COMPARATOR] [MATCH-TYPE] <header-name: string> + * <date-part: string> <key-list: string-list> + */ + +static bool tst_date_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); + +const struct sieve_command_def date_test = { + .identifier = "date", + .type = SCT_TEST, + .positional_args = 3, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_date_registered, + .validate = tst_date_validate, + .generate = tst_date_generate +}; + +/* Currentdate test + * + * Syntax: + * currentdate [":zone" <time-zone: string>] + * [COMPARATOR] [MATCH-TYPE] + * <date-part: string> <key-list: string-list> + */ + +static bool tst_currentdate_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); + +const struct sieve_command_def currentdate_test = { + .identifier = "currentdate", + .type = SCT_TEST, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_currentdate_registered, + .validate = tst_date_validate, + .generate = tst_date_generate +}; + +/* + * Tagged arguments + */ + +/* Forward declarations */ + +static bool tag_zone_validate + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool tag_zone_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd); + +/* Argument objects */ + +static const struct sieve_argument_def date_zone_tag = { + .identifier = "zone", + .validate = tag_zone_validate, + .generate = tag_zone_generate +}; + +static const struct sieve_argument_def date_originalzone_tag = { + .identifier = "originalzone", + .validate = tag_zone_validate, + .generate = tag_zone_generate +}; + +/* + * Date operation + */ + +static bool tst_date_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_date_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def date_operation = { + .mnemonic = "DATE", + .ext_def = &date_extension, + .code = EXT_DATE_OPERATION_DATE, + .dump = tst_date_operation_dump, + .execute = tst_date_operation_execute +}; + +const struct sieve_operation_def currentdate_operation = { + .mnemonic = "CURRENTDATE", + .ext_def = &date_extension, + .code = EXT_DATE_OPERATION_CURRENTDATE, + .dump = tst_date_operation_dump, + .execute = tst_date_operation_execute +}; + +/* + * Optional operands + */ + +enum tst_date_optional { + OPT_DATE_ZONE = SIEVE_AM_OPT_LAST, + OPT_DATE_LAST +}; + +/* + * Tag implementation + */ + +static bool tag_zone_validate +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + + if ( (bool) cmd->data ) { + if ( sieve_command_is(cmd, date_test) ) { + sieve_argument_validate_error(valdtr, *arg, + "multiple :zone or :originalzone arguments specified for " + "the currentdate test"); + } else { + sieve_argument_validate_error(valdtr, *arg, + "multiple :zone arguments specified for the currentdate test"); + } + return FALSE; + } + + /* Skip tag */ + *arg = sieve_ast_argument_next(*arg); + + /* :content tag has a string-list argument */ + if ( sieve_argument_is(tag, date_zone_tag) ) { + + /* Check syntax: + * :zone <time-zone: string> + */ + if ( !sieve_validate_tag_parameter + (valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING, FALSE) ) { + return FALSE; + } + + /* Check it */ + if ( sieve_argument_is_string_literal(*arg) ) { + const char *zone = sieve_ast_argument_strc(*arg); + + if ( !ext_date_parse_timezone(zone, NULL) ) { + sieve_argument_validate_warning(valdtr, *arg, + "specified :zone argument '%s' is not a valid timezone", + str_sanitize(zone, 40)); + } + } + + /* Assign tag parameters */ + tag->parameters = *arg; + *arg = sieve_ast_arguments_detach(*arg,1); + } + + cmd->data = (void *) TRUE; + + return TRUE; +} + +/* + * Test registration + */ + +static bool tst_date_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &date_zone_tag, OPT_DATE_ZONE); + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &date_originalzone_tag, OPT_DATE_ZONE); + + return TRUE; +} + +static bool tst_currentdate_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &date_zone_tag, OPT_DATE_ZONE); + + return TRUE; +} + +/* + * Validation + */ + +static bool tst_date_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + unsigned int arg_offset = 0 ; + const struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + + /* Check header name */ + + if ( sieve_command_is(tst, date_test) ) { + arg_offset = 1; + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "header name", 1, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + if ( !sieve_command_verify_headers_argument(valdtr, arg) ) + return FALSE; + + arg = sieve_ast_argument_next(arg); + } + + /* Check date part */ + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "date part", arg_offset + 1, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + if ( sieve_argument_is_string_literal(arg) ) { + const char * part = sieve_ast_argument_strc(arg); + + if ( ext_date_part_find(part) == NULL ) { + sieve_argument_validate_warning + (valdtr, arg, "specified date part `%s' is not known", + str_sanitize(part, 80)); + } + } + + arg = sieve_ast_argument_next(arg); + + /* Check key list */ + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "key list", arg_offset + 2, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate + (valdtr, tst, arg, &mcht_default, &cmp_default); +} + +/* + * Code generation + */ + +static bool tst_date_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *tst) +{ + if ( sieve_command_is(tst, date_test) ) + sieve_operation_emit(cgenv->sblock, tst->ext, &date_operation); + else if ( sieve_command_is(tst, currentdate_test) ) + sieve_operation_emit(cgenv->sblock, tst->ext, ¤tdate_operation); + else + i_unreached(); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +static bool tag_zone_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd) +{ + if ( arg->parameters == NULL ) { + sieve_opr_omitted_emit(cgenv->sblock); + return TRUE; + } + + return sieve_generate_argument_parameters(cgenv, cmd, arg); +} + +/* + * Code dump + */ + +static bool tst_date_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + int opt_code = 0; + const struct sieve_operation *op = denv->oprtn; + + sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(op)); + sieve_code_descend(denv); + + /* Handle any optional arguments */ + for (;;) { + int opt; + + if ( (opt=sieve_message_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_DATE_ZONE: + if ( !sieve_opr_string_dump_ex(denv, address, "zone", "ORIGINAL") ) + return FALSE; + break; + default: + return FALSE; + } + } + + if ( sieve_operation_is(op, date_operation) && + !sieve_opr_string_dump(denv, address, "header name") ) + return FALSE; + + return + sieve_opr_string_dump(denv, address, "date part") && + sieve_opr_stringlist_dump(denv, address, "key list"); +} + + +/* + * Code execution + */ + +static int tst_date_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_operation *op = renv->oprtn; + int opt_code = 0; + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + ARRAY_TYPE(sieve_message_override) svmos; + string_t *date_part = NULL, *zone = NULL; + struct sieve_stringlist *hdr_list = NULL, *hdr_value_list; + struct sieve_stringlist *value_list, *key_list; + bool zone_specified = FALSE, zone_literal = TRUE; + const struct ext_date_part *dpart; + int time_zone; + int match, ret; + + /* Read optional operands */ + for (;;) { + int opt; + + /* Optional operands */ + i_zero(&svmos); + if ( (opt=sieve_message_opr_optional_read + (renv, address, &opt_code, &ret, NULL, &mcht, &cmp, &svmos)) < 0 ) + return ret; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_DATE_ZONE: + if ( (ret=sieve_opr_string_read_ex + (renv, address, "zone", TRUE, &zone, &zone_literal)) <= 0 ) + return ret; + + zone_specified = TRUE; + break; + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + } + + if ( sieve_operation_is(op, date_operation) ) { + /* Read header name as stringlist */ + if ( (ret=sieve_opr_stringlist_read + (renv, address, "header-name", &hdr_list)) <= 0 ) + return ret; + } + + /* Read date part */ + if ( (ret=sieve_opr_string_read(renv, address, "date-part", &date_part)) + <= 0 ) + return ret; + + /* Read key-list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; + + /* Determine what time zone to use in the result */ + if ( !zone_specified ) { + time_zone = EXT_DATE_TIMEZONE_LOCAL; + } else if ( zone == NULL ) { + time_zone = EXT_DATE_TIMEZONE_ORIGINAL; + } else if ( !ext_date_parse_timezone(str_c(zone), &time_zone) ) { + if ( !zone_literal ) + sieve_runtime_warning(renv, NULL, + "specified :zone argument `%s' is not a valid timezone " + "(using local zone)", str_sanitize(str_c(zone), 40)); + time_zone = EXT_DATE_TIMEZONE_LOCAL; + } + + if ( (dpart=ext_date_part_find(str_c(date_part))) == NULL ) { + sieve_runtime_warning(renv, NULL, + "specified date part argument `%s' is not known", + str_sanitize(str_c(date_part), 40)); + sieve_interpreter_set_test_result(renv->interp, FALSE); + return SIEVE_EXEC_OK; + } + + /* + * Perform test + */ + + if ( sieve_operation_is(op, date_operation) ) { + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "date test"); + + /* Get header */ + sieve_runtime_trace_descend(renv); + if ( (ret=sieve_message_get_header_fields + (renv, hdr_list, &svmos, FALSE, &hdr_value_list)) <= 0 ) + return ret; + sieve_runtime_trace_ascend(renv); + + /* Create value stringlist */ + value_list = ext_date_stringlist_create + (renv, hdr_value_list, time_zone, dpart); + + } else if ( sieve_operation_is(op, currentdate_operation) ) { + /* Use time stamp recorded at the time the script first started */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "currentdatedate test"); + + /* Create value stringlist */ + value_list = ext_date_stringlist_create(renv, NULL, time_zone, dpart); + } else { + i_unreached(); + } + + /* Perform match */ + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/duplicate/Makefile.am b/pigeonhole/src/lib-sieve/plugins/duplicate/Makefile.am new file mode 100644 index 0000000..7469b98 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/duplicate/Makefile.am @@ -0,0 +1,20 @@ +noinst_LTLIBRARIES = libsieve_ext_duplicate.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-duplicate.c + +extensions = \ + ext-duplicate.c + +libsieve_ext_duplicate_la_SOURCES = \ + $(tests) \ + $(extensions) \ + ext-duplicate-common.c + +noinst_HEADERS = \ + ext-duplicate-common.h + diff --git a/pigeonhole/src/lib-sieve/plugins/duplicate/Makefile.in b/pigeonhole/src/lib-sieve/plugins/duplicate/Makefile.in new file mode 100644 index 0000000..d29f834 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/duplicate/Makefile.in @@ -0,0 +1,697 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/duplicate +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_duplicate_la_LIBADD = +am__objects_1 = tst-duplicate.lo +am__objects_2 = ext-duplicate.lo +am_libsieve_ext_duplicate_la_OBJECTS = $(am__objects_1) \ + $(am__objects_2) ext-duplicate-common.lo +libsieve_ext_duplicate_la_OBJECTS = \ + $(am_libsieve_ext_duplicate_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ext-duplicate-common.Plo \ + ./$(DEPDIR)/ext-duplicate.Plo ./$(DEPDIR)/tst-duplicate.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_duplicate_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_duplicate_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_duplicate.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-duplicate.c + +extensions = \ + ext-duplicate.c + +libsieve_ext_duplicate_la_SOURCES = \ + $(tests) \ + $(extensions) \ + ext-duplicate-common.c + +noinst_HEADERS = \ + ext-duplicate-common.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/duplicate/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/duplicate/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_duplicate.la: $(libsieve_ext_duplicate_la_OBJECTS) $(libsieve_ext_duplicate_la_DEPENDENCIES) $(EXTRA_libsieve_ext_duplicate_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_duplicate_la_OBJECTS) $(libsieve_ext_duplicate_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-duplicate-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-duplicate.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-duplicate.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-duplicate-common.Plo + -rm -f ./$(DEPDIR)/ext-duplicate.Plo + -rm -f ./$(DEPDIR)/tst-duplicate.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ext-duplicate-common.Plo + -rm -f ./$(DEPDIR)/ext-duplicate.Plo + -rm -f ./$(DEPDIR)/tst-duplicate.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/duplicate/ext-duplicate-common.c b/pigeonhole/src/lib-sieve/plugins/duplicate/ext-duplicate-common.c new file mode 100644 index 0000000..5af7e04 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/duplicate/ext-duplicate-common.c @@ -0,0 +1,298 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "md5.h" +#include "ioloop.h" +#include "str.h" +#include "str-sanitize.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-settings.h" +#include "sieve-error.h" +#include "sieve-extensions.h" +#include "sieve-message.h" +#include "sieve-code.h" +#include "sieve-runtime.h" +#include "sieve-interpreter.h" +#include "sieve-actions.h" +#include "sieve-result.h" + +#include "ext-duplicate-common.h" + +/* + * Extension configuration + */ + +#define EXT_DUPLICATE_DEFAULT_PERIOD (12*60*60) +#define EXT_DUPLICATE_DEFAULT_MAX_PERIOD (2*24*60*60) + +bool ext_duplicate_load(const struct sieve_extension *ext, void **context) +{ + struct sieve_instance *svinst = ext->svinst; + struct ext_duplicate_config *config; + sieve_number_t default_period, max_period; + + if (*context != NULL) + ext_duplicate_unload(ext); + + if (!sieve_setting_get_duration_value( + svinst, "sieve_duplicate_default_period", &default_period)) + default_period = EXT_DUPLICATE_DEFAULT_PERIOD; + if (!sieve_setting_get_duration_value( + svinst, "sieve_duplicate_max_period", &max_period)) { + max_period = EXT_DUPLICATE_DEFAULT_MAX_PERIOD; + } + + config = i_new(struct ext_duplicate_config, 1); + config->default_period = default_period; + config->max_period = max_period; + + *context = (void *) config; + return TRUE; +} + +void ext_duplicate_unload(const struct sieve_extension *ext) +{ + struct ext_duplicate_config *config = + (struct ext_duplicate_config *)ext->context; + + i_free(config); +} + +/* + * Duplicate_mark action + */ + +struct act_duplicate_mark_data { + const char *handle; + unsigned int period; + unsigned char hash[MD5_RESULTLEN]; + bool last:1; +}; + +static void +act_duplicate_mark_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, + bool *keep); +static void +act_duplicate_mark_finish(const struct sieve_action_exec_env *aenv, + void *tr_context, int status); + +static const struct sieve_action_def act_duplicate_mark = { + .name = "duplicate_mark", + .print = act_duplicate_mark_print, + .finish = act_duplicate_mark_finish +}; + +static void +act_duplicate_mark_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, + bool *keep ATTR_UNUSED) +{ + struct act_duplicate_mark_data *data = + (struct act_duplicate_mark_data *)action->context; + const char *last = (data->last ? " last" : ""); + + if (data->handle != NULL) { + sieve_result_action_printf( + rpenv, "track%s duplicate with handle: %s", + last, str_sanitize(data->handle, 128)); + } else { + sieve_result_action_printf(rpenv, "track%s duplicate", last); + } +} + +static void +act_duplicate_mark_finish(const struct sieve_action_exec_env *aenv, + void *tr_context ATTR_UNUSED, int status) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct act_duplicate_mark_data *data = + (struct act_duplicate_mark_data *)aenv->action->context; + + if (status != SIEVE_EXEC_OK) { + e_debug(aenv->event, "Not marking duplicate (status=%s)", + sieve_execution_exitcode_to_str(status)); + return; + } + + e_debug(aenv->event, "Marking duplicate"); + + /* Message was handled successfully, so track duplicate for this + * message. + */ + eenv->exec_status->significant_action_executed = TRUE; + sieve_action_duplicate_mark(aenv, data->hash, sizeof(data->hash), + ioloop_time + data->period); +} + +/* + * Duplicate checking + */ + +struct ext_duplicate_handle { + const char *handle; + bool last:1; + bool duplicate:1; +}; + +struct ext_duplicate_hash { + unsigned char hash[MD5_RESULTLEN]; + ARRAY(struct ext_duplicate_handle) handles; +}; + +struct ext_duplicate_context { + ARRAY(struct ext_duplicate_hash) hashes; +}; + +static void +ext_duplicate_hash(string_t *handle, const char *value, size_t value_len, + bool last, unsigned char hash_r[]) +{ + static const char *id = "sieve duplicate"; + struct md5_context md5ctx; + + md5_init(&md5ctx); + md5_update(&md5ctx, id, strlen(id)); + if (last) + md5_update(&md5ctx, "0", 1); + else + md5_update(&md5ctx, "+", 1); + if (handle != NULL) { + md5_update(&md5ctx, "h-", 2); + md5_update(&md5ctx, str_c(handle), str_len(handle)); + } else { + md5_update(&md5ctx, "default", 7); + } + md5_update(&md5ctx, value, value_len); + md5_final(&md5ctx, hash_r); +} + +int ext_duplicate_check(const struct sieve_runtime_env *renv, string_t *handle, + const char *value, size_t value_len, + sieve_number_t period, bool last, bool *duplicate_r) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct ext_duplicate_context *rctx; + bool duplicate = FALSE; + pool_t msg_pool = NULL, result_pool = NULL; + unsigned char hash[MD5_RESULTLEN]; + struct ext_duplicate_hash *hash_record = NULL; + struct ext_duplicate_handle *handle_record = NULL; + struct act_duplicate_mark_data *act; + int ret; + + *duplicate_r = FALSE; + + if (!sieve_execute_duplicate_check_available(eenv)) { + sieve_runtime_warning( + renv, NULL, "duplicate test: " + "duplicate checking not available in this context"); + return SIEVE_EXEC_OK; + } + + if (value == NULL) + return SIEVE_EXEC_OK; + + /* Create hash */ + ext_duplicate_hash(handle, value, value_len, last, hash); + + /* Get context; find out whether duplicate was checked earlier */ + rctx = (struct ext_duplicate_context *) + sieve_message_context_extension_get(renv->msgctx, this_ext); + + if (rctx == NULL) { + /* Create context */ + msg_pool = sieve_message_context_pool(renv->msgctx); + rctx = p_new(msg_pool, struct ext_duplicate_context, 1); + sieve_message_context_extension_set(renv->msgctx, this_ext, + (void *)rctx); + } else if (array_is_created(&rctx->hashes)) { + struct ext_duplicate_hash *record; + + array_foreach_modifiable(&rctx->hashes, record) { + if (memcmp(record->hash, hash, MD5_RESULTLEN) == 0) { + hash_record = record; + break; + } + } + } + if (hash_record != NULL) { + const struct ext_duplicate_handle *rhandle; + array_foreach(&hash_record->handles, rhandle) { + const char *handle_str = + (handle == NULL ? NULL : str_c(handle)); + if (null_strcmp(rhandle->handle, handle_str) == 0 && + rhandle->last == last) + return (rhandle->duplicate ? + SIEVE_DUPLICATE_CHECK_RESULT_EXISTS : + SIEVE_DUPLICATE_CHECK_RESULT_NOT_FOUND); + } + } + + result_pool = sieve_result_pool(renv->result); + act = p_new(result_pool, struct act_duplicate_mark_data, 1); + if (handle != NULL) + act->handle = p_strdup(result_pool, str_c(handle)); + act->period = period; + memcpy(act->hash, hash, MD5_RESULTLEN); + act->last = last; + + /* Check duplicate */ + ret = sieve_execute_duplicate_check(eenv, hash, sizeof(hash), + &duplicate); + if (ret >= SIEVE_EXEC_OK && !duplicate && last) { + unsigned char no_last_hash[MD5_RESULTLEN]; + + /* Check for entry without :last */ + ext_duplicate_hash(handle, value, value_len, + FALSE, no_last_hash); + ret = sieve_execute_duplicate_check( + eenv, no_last_hash, sizeof(no_last_hash), + &duplicate); + } + if (ret < SIEVE_EXEC_OK) { + sieve_runtime_critical( + renv, NULL, "failed to check for duplicate", + "failed to check for duplicate%s", + (ret == SIEVE_EXEC_TEMP_FAILURE ? + " (temporary failure)" : "")); + return ret; + } + + /* We may only mark the message as duplicate when Sieve script executes + * successfully; therefore defer this operation until successful result + * execution. + */ + if (!duplicate || last) { + if (sieve_result_add_action(renv, NULL, NULL, + &act_duplicate_mark, + NULL, (void *) act, 0, FALSE) < 0) + return SIEVE_EXEC_FAILURE; + } + + /* Cache result */ + if (msg_pool == NULL) + msg_pool = sieve_message_context_pool(renv->msgctx); + if (hash_record == NULL) { + if (!array_is_created(&rctx->hashes)) + p_array_init(&rctx->hashes, msg_pool, 64); + hash_record = array_append_space(&rctx->hashes); + memcpy(hash_record->hash, hash, MD5_RESULTLEN); + p_array_init(&hash_record->handles, msg_pool, 64); + } + + handle_record = array_append_space(&hash_record->handles); + if (handle != NULL) + handle_record->handle = p_strdup(msg_pool, str_c(handle)); + handle_record->last = last; + handle_record->duplicate = duplicate; + + *duplicate_r = duplicate; + + return SIEVE_EXEC_OK; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/duplicate/ext-duplicate-common.h b/pigeonhole/src/lib-sieve/plugins/duplicate/ext-duplicate-common.h new file mode 100644 index 0000000..c802b08 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/duplicate/ext-duplicate-common.h @@ -0,0 +1,41 @@ +#ifndef EXT_DUPLICATE_COMMON_H +#define EXT_DUPLICATE_COMMON_H + +#include "sieve-common.h" + +/* + * Extension + */ + +struct ext_duplicate_config { + unsigned int default_period; + unsigned int max_period; +}; + +bool ext_duplicate_load(const struct sieve_extension *ext, void **context); +void ext_duplicate_unload(const struct sieve_extension *ext); + +extern const struct sieve_extension_def duplicate_extension; +extern const struct sieve_extension_def vnd_duplicate_extension; + +/* + * Tests + */ + +extern const struct sieve_command_def tst_duplicate; + +/* + * Operations + */ + +extern const struct sieve_operation_def tst_duplicate_operation; + +/* + * Duplicate checking + */ + +int ext_duplicate_check(const struct sieve_runtime_env *renv, string_t *handle, + const char *value, size_t value_len, + sieve_number_t period, bool last, bool *duplicate_r); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/duplicate/ext-duplicate.c b/pigeonhole/src/lib-sieve/plugins/duplicate/ext-duplicate.c new file mode 100644 index 0000000..54de5e5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/duplicate/ext-duplicate.c @@ -0,0 +1,107 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension duplicate + * ------------------- + * + * Authors: Stephan Bosch + * Specification: vendor-defined; spec-bosch-sieve-duplicate + * Implementation: full + * Status: experimental + * + */ + +/* Extension vnd.dovecot.duplicate + * ------------------------------- + * + * Authors: Stephan Bosch + * Specification: vendor-defined; spec-bosch-sieve-duplicate + * Implementation: full, but deprecated; provided for backwards compatibility + * Status: experimental + * + */ + +#include "lib.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-binary.h" + +#include "sieve-validator.h" + +#include "ext-duplicate-common.h" + +/* + * Extensions + */ + +static bool ext_duplicate_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def duplicate_extension = { + .name = "duplicate", + .load = ext_duplicate_load, + .unload = ext_duplicate_unload, + .validator_load = ext_duplicate_validator_load, + SIEVE_EXT_DEFINE_OPERATION(tst_duplicate_operation) +}; + +const struct sieve_extension_def vnd_duplicate_extension = { + .name = "vnd.dovecot.duplicate", + .load = ext_duplicate_load, + .unload = ext_duplicate_unload, + .validator_load = ext_duplicate_validator_load, + SIEVE_EXT_DEFINE_OPERATION(tst_duplicate_operation) +}; + +/* + * Validation + */ + +static bool ext_duplicate_validator_check_conflict + (const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + const struct sieve_extension *ext_other, + bool required); + +const struct sieve_validator_extension +duplicate_validator_extension = { + .ext = &vnd_duplicate_extension, + .check_conflict = ext_duplicate_validator_check_conflict +}; + +static bool ext_duplicate_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register validator extension to check for conflict between + vnd.dovecot.duplicate and duplicate extensions */ + if ( sieve_extension_is(ext, vnd_duplicate_extension) ) { + sieve_validator_extension_register + (valdtr, ext, &duplicate_validator_extension, NULL); + } + + /* Register duplicate test */ + sieve_validator_register_command(valdtr, ext, &tst_duplicate); + + return TRUE; +} + +static bool ext_duplicate_validator_check_conflict +(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_validator *valdtr, void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg, + const struct sieve_extension *ext_other, + bool required ATTR_UNUSED) +{ + /* Check for conflict with duplicate extension */ + if ( sieve_extension_name_is(ext_other, "duplicate") ) { + sieve_argument_validate_error(valdtr, require_arg, + "the (deprecated) vnd.dovecot.duplicate extension " + "cannot be used together with the duplicate extension"); + return FALSE; + } + + return TRUE; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/duplicate/tst-duplicate.c b/pigeonhole/src/lib-sieve/plugins/duplicate/tst-duplicate.c new file mode 100644 index 0000000..d211e04 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/duplicate/tst-duplicate.c @@ -0,0 +1,449 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "mail-storage.h" + +#include "sieve-common.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-duplicate-common.h" + +/* Duplicate test + * + * Syntax: + * Usage: "duplicate" [":handle" <handle: string>] + * [":header" <header-name: string> / + * ":uniqueid" <value: string>] + * [":seconds" <timeout: number>] [":last"] + */ + +static bool +tst_duplicate_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool +tst_duplicate_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def tst_duplicate = { + .identifier = "duplicate", + .type = SCT_TEST, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_duplicate_registered, + .generate = tst_duplicate_generate +}; + +/* + * Duplicate test tags + */ + +static bool +tst_duplicate_validate_number_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +tst_duplicate_validate_string_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +static const struct sieve_argument_def duplicate_seconds_tag = { + .identifier = "seconds", + .validate = tst_duplicate_validate_number_tag +}; + +static const struct sieve_argument_def duplicate_header_tag = { + .identifier = "header", + .validate = tst_duplicate_validate_string_tag +}; + +static const struct sieve_argument_def duplicate_uniqueid_tag = { + .identifier = "uniqueid", + .validate = tst_duplicate_validate_string_tag +}; + +static const struct sieve_argument_def duplicate_value_tag = { + .identifier = "value", /* vnd.dovecot.duplicate (deprecated) */ + .validate = tst_duplicate_validate_string_tag +}; + +static const struct sieve_argument_def duplicate_handle_tag = { + .identifier = "handle", + .validate = tst_duplicate_validate_string_tag +}; + +static const struct sieve_argument_def duplicate_last_tag = { + .identifier = "last" +}; + +/* Codes for optional arguments */ + +enum tst_duplicate_optional { + OPT_END, + OPT_SECONDS, + OPT_HEADER, + OPT_UNIQUEID, + OPT_LAST, + OPT_HANDLE +}; + +/* + * Duplicate operation + */ + +static bool +tst_duplicate_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +tst_duplicate_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def tst_duplicate_operation = { + .mnemonic = "DUPLICATE", + .ext_def = &duplicate_extension, + .dump = tst_duplicate_operation_dump, + .execute = tst_duplicate_operation_execute +}; + +/* + * Tag validation + */ + +static bool +tst_duplicate_validate_number_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + const struct sieve_extension *ext = sieve_argument_ext(*arg); + const struct ext_duplicate_config *config = + (const struct ext_duplicate_config *)ext->context; + struct sieve_ast_argument *tag = *arg; + sieve_number_t seconds; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :seconds number + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_NUMBER, FALSE)) + return FALSE; + + seconds = sieve_ast_argument_number(*arg); + /* Enforce :days <= max_period */ + if (config->max_period > 0 && seconds > config->max_period) { + seconds = config->max_period; + + sieve_argument_validate_warning( + valdtr, *arg, + "specified :seconds value '%llu' is over the maximum", + (unsigned long long)seconds); + } + + sieve_ast_argument_number_set(*arg, seconds); + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + return TRUE; +} + +static bool +tst_duplicate_validate_string_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + const struct sieve_extension *ext = cmd->ext; + struct sieve_ast_argument *tag = *arg; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :header <header-name: string> + * :value <value: string> + * :handle <handle: string> + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING, FALSE)) + return FALSE; + + if (!sieve_argument_is(tag, duplicate_handle_tag) && (bool)cmd->data) { + sieve_argument_validate_error( + valdtr, *arg, + "conflicting :header and %s arguments specified " + "for the duplicate test", + (sieve_extension_is(ext, duplicate_extension) ? + ":uniqueid" : ":value")); + return FALSE; + } + + /* :header <header-name: string> */ + if (sieve_argument_is(tag, duplicate_header_tag)) { + if (!sieve_command_verify_headers_argument(valdtr, *arg)) + return FALSE; + cmd->data = (void *)TRUE; + /* :handle <handle: string> */ + } else if (sieve_argument_is(tag, duplicate_handle_tag)) { + /* nothing to be done */ + } else if (sieve_argument_is(tag, duplicate_uniqueid_tag)) { + i_assert(sieve_extension_is(ext, duplicate_extension)); + cmd->data = (void *)TRUE; + /* :value <value: string> (vnd.dovecot.duplicate) */ + } else if (sieve_argument_is(tag, duplicate_value_tag)) { + i_assert(sieve_extension_is(ext, vnd_duplicate_extension)); + cmd->data = (void *)TRUE; + } else { + i_unreached(); + } + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + return TRUE; +} + +/* + * Command registration + */ + +static bool +tst_duplicate_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &duplicate_seconds_tag, OPT_SECONDS); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &duplicate_last_tag, OPT_LAST); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &duplicate_header_tag, OPT_HEADER); + if (sieve_extension_is(ext, duplicate_extension)) { + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &duplicate_uniqueid_tag, + OPT_UNIQUEID); + } else { + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &duplicate_value_tag, + OPT_UNIQUEID); + } + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &duplicate_handle_tag, OPT_HANDLE); + return TRUE; +} + +/* + * Code generation + */ + +static bool +tst_duplicate_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &tst_duplicate_operation); + + if (!sieve_generate_arguments(cgenv, cmd, NULL)) + return FALSE; + return TRUE; +} + +/* + * Code dump + */ + +static bool +tst_duplicate_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + const struct sieve_extension *ext = denv->oprtn->ext; + int opt_code = 0; + + sieve_code_dumpf(denv, "DUPLICATE"); + sieve_code_descend(denv); + + /* Dump optional operands */ + + for (;;) { + int opt; + bool opok = TRUE; + + if ((opt = sieve_opr_optional_dump(denv, address, + &opt_code)) < 0) + return FALSE; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_SECONDS: + opok = sieve_opr_number_dump(denv, address, "seconds"); + break; + case OPT_LAST: + sieve_code_dumpf(denv, "last"); + break; + case OPT_HEADER: + opok = sieve_opr_string_dump(denv, address, "header"); + break; + case OPT_UNIQUEID: + if (sieve_extension_is(ext, duplicate_extension)) { + opok = sieve_opr_string_dump(denv, address, + "uniqueid"); + } else { + opok = sieve_opr_string_dump(denv, address, + "value"); + } + break; + case OPT_HANDLE: + opok = sieve_opr_string_dump(denv, address, "handle"); + break; + default: + return FALSE; + } + + if (!opok) + return FALSE; + } + + return TRUE; +} + +/* + * Code execution + */ + +static int +tst_duplicate_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_extension *ext = renv->oprtn->ext; + const struct ext_duplicate_config *config = + (const struct ext_duplicate_config *)ext->context; + struct mail *mail = eenv->msgdata->mail; + int opt_code = 0; + string_t *handle = NULL, *header = NULL, *uniqueid = NULL; + const char *val = NULL; + size_t val_len = 0; + sieve_number_t seconds = config->default_period; + bool last = FALSE, duplicate = FALSE; + int ret; + + /* + * Read operands + */ + + /* Optional operands */ + + for (;;) { + int opt; + + if ((opt = sieve_opr_optional_read(renv, address, + &opt_code)) < 0) + return SIEVE_EXEC_BIN_CORRUPT; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_SECONDS: + ret = sieve_opr_number_read(renv, address, "seconds", + &seconds); + break; + case OPT_LAST: + last = TRUE; + ret = SIEVE_EXEC_OK; + break; + case OPT_HEADER: + ret = sieve_opr_string_read(renv, address, "header", + &header); + break; + case OPT_UNIQUEID: + if (sieve_extension_is(ext, duplicate_extension)) { + ret = sieve_opr_string_read(renv, address, + "uniqueid", + &uniqueid); + } else { + ret = sieve_opr_string_read(renv, address, + "value", &uniqueid); + } + break; + case OPT_HANDLE: + ret = sieve_opr_string_read(renv, address, + "handle", &handle); + break; + default: + sieve_runtime_trace_error( + renv, "unknown optional operand"); + ret = SIEVE_EXEC_BIN_CORRUPT; + } + + if (ret <= 0) + return ret; + } + + /* + * Perform operation + */ + + /* Trace */ + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "duplicate test"); + sieve_runtime_trace_descend(renv); + + /* Get value */ + if (uniqueid != NULL) { + val = str_c(uniqueid); + val_len = str_len(uniqueid); + } else { + if (header == NULL) { + ret = mail_get_message_id(mail, &val); + if (ret < 0) { + return sieve_runtime_mail_error( + renv, mail, "duplicate test: " + "failed to read header field `message-id'"); + } + } else { + ret = mail_get_first_header_utf8(mail, str_c(header), + &val); + if (ret < 0) { + return sieve_runtime_mail_error( + renv, mail, "duplicate test: " + "failed to read header field `%s'", + str_c(header)); + } + } + + if (ret > 0) + val_len = strlen(val); + } + + /* Check duplicate */ + if (val == NULL) { + duplicate = FALSE; + } else { + ret = ext_duplicate_check(renv, handle, val, val_len, + seconds, last, &duplicate); + if (ret < SIEVE_EXEC_OK) + return ret; + } + + /* Trace */ + if (duplicate) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "message is a duplicate"); + } else { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "message is not a duplicate"); + } + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, duplicate); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/editheader/Makefile.am b/pigeonhole/src/lib-sieve/plugins/editheader/Makefile.am new file mode 100644 index 0000000..6824ec0 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/editheader/Makefile.am @@ -0,0 +1,19 @@ +noinst_LTLIBRARIES = libsieve_ext_editheader.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../util \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-addheader.c \ + cmd-deleteheader.c + +libsieve_ext_editheader_la_SOURCES = \ + $(commands) \ + ext-editheader.c \ + ext-editheader-common.c + +noinst_HEADERS = \ + ext-editheader-limits.h \ + ext-editheader-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/editheader/Makefile.in b/pigeonhole/src/lib-sieve/plugins/editheader/Makefile.in new file mode 100644 index 0000000..75d9571 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/editheader/Makefile.in @@ -0,0 +1,701 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/editheader +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_editheader_la_LIBADD = +am__objects_1 = cmd-addheader.lo cmd-deleteheader.lo +am_libsieve_ext_editheader_la_OBJECTS = $(am__objects_1) \ + ext-editheader.lo ext-editheader-common.lo +libsieve_ext_editheader_la_OBJECTS = \ + $(am_libsieve_ext_editheader_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/cmd-addheader.Plo \ + ./$(DEPDIR)/cmd-deleteheader.Plo \ + ./$(DEPDIR)/ext-editheader-common.Plo \ + ./$(DEPDIR)/ext-editheader.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_editheader_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_editheader_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_editheader.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../util \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-addheader.c \ + cmd-deleteheader.c + +libsieve_ext_editheader_la_SOURCES = \ + $(commands) \ + ext-editheader.c \ + ext-editheader-common.c + +noinst_HEADERS = \ + ext-editheader-limits.h \ + ext-editheader-common.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/editheader/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/editheader/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_editheader.la: $(libsieve_ext_editheader_la_OBJECTS) $(libsieve_ext_editheader_la_DEPENDENCIES) $(EXTRA_libsieve_ext_editheader_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_editheader_la_OBJECTS) $(libsieve_ext_editheader_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-addheader.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-deleteheader.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-editheader-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-editheader.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-addheader.Plo + -rm -f ./$(DEPDIR)/cmd-deleteheader.Plo + -rm -f ./$(DEPDIR)/ext-editheader-common.Plo + -rm -f ./$(DEPDIR)/ext-editheader.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/cmd-addheader.Plo + -rm -f ./$(DEPDIR)/cmd-deleteheader.Plo + -rm -f ./$(DEPDIR)/ext-editheader-common.Plo + -rm -f ./$(DEPDIR)/ext-editheader.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/editheader/cmd-addheader.c b/pigeonhole/src/lib-sieve/plugins/editheader/cmd-addheader.c new file mode 100644 index 0000000..f39cbb7 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/editheader/cmd-addheader.c @@ -0,0 +1,337 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" +#include "mail-storage.h" + +#include "rfc2822.h" +#include "edit-mail.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-message.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-editheader-common.h" + +/* + * Addheader command + * + * Syntax + * "addheader" [":last"] <field-name: string> <value: string> + */ + +static bool cmd_addheader_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool cmd_addheader_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool cmd_addheader_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def addheader_command = { + .identifier = "addheader", + .type = SCT_COMMAND, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_addheader_registered, + .validate = cmd_addheader_validate, + .generate = cmd_addheader_generate +}; + +/* + * Addheader command tags + */ + +/* Argument objects */ + +static const struct sieve_argument_def addheader_last_tag = { + .identifier = "last" +}; + +/* Codes for optional arguments */ + +enum cmd_addheader_optional { + OPT_END, + OPT_LAST +}; + +/* + * Addheader operation + */ + +static bool cmd_addheader_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_addheader_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def addheader_operation = { + .mnemonic = "ADDHEADER", + .ext_def = &editheader_extension, + .code = EXT_EDITHEADER_OPERATION_ADDHEADER, + .dump = cmd_addheader_operation_dump, + .execute = cmd_addheader_operation_execute +}; + +/* + * Utility + */ + +static bool _str_contains_nul(const string_t *str) +{ + const unsigned char *p, *pend; + + p = str_data(str); + pend = p + str_len(str); + while (p < pend) { + if (*p == '\0') + return TRUE; + p++; + } + return FALSE; +} + +/* + * Validation + */ + +static bool cmd_addheader_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + /* Check field-name syntax */ + + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "field-name", 1, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) ) + return FALSE; + + if ( sieve_argument_is_string_literal(arg) ) { + string_t *fname = sieve_ast_argument_str(arg); + + if ( !rfc2822_header_field_name_verify(str_c(fname), str_len(fname)) ) { + sieve_argument_validate_error + (valdtr, arg, "addheader command: specified field name `%s' is invalid", + str_sanitize(str_c(fname), 80)); + return FALSE; + } + + if ( !ext_editheader_header_allow_add + (cmd->ext, str_c(fname)) ) { + sieve_argument_validate_warning + (valdtr, arg, "addheader command: " + "adding specified header field `%s' is forbidden; " + "modification will be denied", + str_sanitize(str_c(fname), 80)); + } + } + + /* Check value syntax */ + + arg = sieve_ast_argument_next(arg); + + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "value", 2, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) ) + return FALSE; + + if ( sieve_argument_is_string_literal(arg) ) { + string_t *fvalue = sieve_ast_argument_str(arg); + + if ( _str_contains_nul(fvalue) ) { + sieve_argument_validate_error(valdtr, arg, + "addheader command: specified value `%s' is invalid " + "(contains NUL character)", str_sanitize(str_c(fvalue), 80)); + return FALSE; + } + + if ( !rfc2822_header_field_body_verify + (str_c(fvalue), str_len(fvalue), TRUE, TRUE) ) { + sieve_argument_validate_warning(valdtr, arg, + "addheader command: specified value `%s' is invalid", + str_sanitize(str_c(fvalue), 80)); + } + + if ( ext_editheader_header_too_large(cmd->ext, str_len(fvalue)) ) { + sieve_argument_validate_error(valdtr, arg, "addheader command: " + "specified header value `%s' is too large (%zu bytes)", + str_sanitize(str_c(fvalue), 80), str_len(fvalue)); + return SIEVE_EXEC_FAILURE; + } + } + + return TRUE; +} + +/* + * Command registration + */ + +static bool cmd_addheader_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &addheader_last_tag, OPT_LAST); + return TRUE; +} + +/* + * Code generation + */ + +static bool cmd_addheader_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + (void)sieve_operation_emit(cgenv->sblock, cmd->ext, &addheader_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool cmd_addheader_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "addheader"); + sieve_code_descend(denv); + + /* Dump optional operands */ + + for (;;) { + int opt; + + if ( (opt=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + + if ( opt == 0 ) break; + + if ( opt_code == OPT_LAST ) { + sieve_code_dumpf(denv, "last"); + } else { + return FALSE; + } + } + + return + sieve_opr_string_dump(denv, address, "field-name") && + sieve_opr_string_dump(denv, address, "value"); +} + +/* + * Interpretation + */ + +static int cmd_addheader_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + string_t *field_name; + string_t *value; + struct edit_mail *edmail; + bool last = FALSE; + int opt_code = 0; + int ret; + + /* + * Read operands + */ + + /* Optional operands */ + + for (;;) { + int opt; + + if ( (opt=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_LAST: + last = TRUE; + break; + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + } + + /* Read message */ + + if ( (ret=sieve_opr_string_read + (renv, address, "field-name", &field_name)) <= 0 ) + return ret; + + if ( (ret=sieve_opr_string_read + (renv, address, "value", &value)) <= 0 ) + return ret; + + /* + * Verify arguments + */ + + if ( !rfc2822_header_field_name_verify + (str_c(field_name), str_len(field_name)) ) { + sieve_runtime_error(renv, NULL, "addheader action: " + "specified field name `%s' is invalid", + str_sanitize(str_c(field_name), 80)); + return SIEVE_EXEC_FAILURE; + } + + if ( !ext_editheader_header_allow_add + (this_ext, str_c(field_name)) ) { + sieve_runtime_warning(renv, NULL, "addheader action: " + "adding specified header field `%s' is forbidden; " + "modification denied", str_sanitize(str_c(field_name), 80)); + return SIEVE_EXEC_OK; + } + + if ( _str_contains_nul(value) ) { + sieve_runtime_error(renv, NULL, "addheader action: " + "specified value `%s' is invalid (contains NUL character)", + str_sanitize(str_c(value), 80)); + return SIEVE_EXEC_FAILURE; + } + + if ( ext_editheader_header_too_large(this_ext, str_len(value)) ) { + sieve_runtime_error(renv, NULL, "addheader action: " + "specified header value `%s' is too large (%zu bytes)", + str_sanitize(str_c(value), 80), str_len(value)); + return SIEVE_EXEC_FAILURE; + } + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "addheader \"%s: %s\"", + str_sanitize(str_c(field_name), 80), str_sanitize(str_c(value), 80)); + + edmail = sieve_message_edit(renv->msgctx); + edit_mail_header_add(edmail, + rfc2822_header_field_name_sanitize(str_c(field_name)), + str_c(value), last); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/editheader/cmd-deleteheader.c b/pigeonhole/src/lib-sieve/plugins/editheader/cmd-deleteheader.c new file mode 100644 index 0000000..a6964b7 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/editheader/cmd-deleteheader.c @@ -0,0 +1,551 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" +#include "mail-storage.h" + +#include "rfc2822.h" +#include "edit-mail.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-editheader-common.h" + +/* + * Deleteheader command + * + * Syntax: + * deleteheader [":index" <fieldno: number> [":last"]] + * [COMPARATOR] [MATCH-TYPE] + * <field-name: string> [<value-patterns: string-list>] + */ + +static bool cmd_deleteheader_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool cmd_deleteheader_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_deleteheader_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + +const struct sieve_command_def deleteheader_command = { + .identifier = "deleteheader", + .type = SCT_COMMAND, + .positional_args = -1, /* We check positional arguments ourselves */ + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_deleteheader_registered, + .validate = cmd_deleteheader_validate, + .generate = cmd_deleteheader_generate +}; + +/* + * Deleteheader command tags + */ + +/* Forward declarations */ + +static bool cmd_deleteheader_validate_index_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool cmd_deleteheader_validate_last_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +/* Argument objects */ + +static const struct sieve_argument_def deleteheader_index_tag = { + .identifier = "index", + .validate = cmd_deleteheader_validate_index_tag +}; + +static const struct sieve_argument_def deleteheader_last_tag = { + .identifier = "last", + .validate = cmd_deleteheader_validate_last_tag +}; + +/* Codes for optional arguments */ + +enum cmd_deleteheader_optional { + OPT_INDEX = SIEVE_MATCH_OPT_LAST, + OPT_LAST +}; + +/* + * Deleteheader operation + */ + +static bool cmd_deleteheader_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_deleteheader_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def deleteheader_operation = { + .mnemonic = "DELETEHEADER", + .ext_def = &editheader_extension, + .code = EXT_EDITHEADER_OPERATION_DELETEHEADER, + .dump = cmd_deleteheader_operation_dump, + .execute = cmd_deleteheader_operation_execute +}; + +/* + * Command registration + */ + +static bool cmd_deleteheader_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &deleteheader_index_tag, OPT_INDEX); + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &deleteheader_last_tag, OPT_LAST); + + return TRUE; +} + +/* + * Command validation context + */ + +struct cmd_deleteheader_context_data { + struct sieve_ast_argument *arg_index; + struct sieve_ast_argument *arg_last; +}; + +/* + * Tag validation + */ + +static struct cmd_deleteheader_context_data * +cmd_deleteheader_get_context +(struct sieve_command *cmd) +{ + struct cmd_deleteheader_context_data *ctx_data = + (struct cmd_deleteheader_context_data *)cmd->data; + + if ( ctx_data != NULL ) return ctx_data; + + ctx_data = p_new + (sieve_command_pool(cmd), struct cmd_deleteheader_context_data, 1); + cmd->data = (void *)ctx_data; + + return ctx_data; +} + +static bool cmd_deleteheader_validate_index_tag +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct cmd_deleteheader_context_data *ctx_data; + sieve_number_t index; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :index number + */ + if ( !sieve_validate_tag_parameter + (valdtr, cmd, tag, *arg, NULL, 0, SAAT_NUMBER, FALSE) ) { + return FALSE; + } + + index = sieve_ast_argument_number(*arg); + if ( index > INT_MAX ) { + sieve_argument_validate_warning(valdtr, *arg, + "the :%s tag for the %s %s has a parameter value '%llu' " + "exceeding the maximum (%d)", + sieve_argument_identifier(tag), sieve_command_identifier(cmd), + sieve_command_type_name(cmd), (unsigned long long) index, + INT_MAX); + return FALSE; + } + + ctx_data = cmd_deleteheader_get_context(cmd); + ctx_data->arg_index = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +static bool cmd_deleteheader_validate_last_tag +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct cmd_deleteheader_context_data *ctx_data; + + ctx_data = cmd_deleteheader_get_context(cmd); + ctx_data->arg_last = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Validation + */ + +static bool cmd_deleteheader_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + struct cmd_deleteheader_context_data *ctx_data = + (struct cmd_deleteheader_context_data *)cmd->data; + struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + + if ( ctx_data != NULL ) { + if ( ctx_data->arg_last != NULL && ctx_data->arg_index == NULL ) { + sieve_argument_validate_error(valdtr, ctx_data->arg_last, + "the :last tag for the %s %s cannot be specified " + "without the :index tag", + sieve_command_identifier(cmd), sieve_command_type_name(cmd)); + } + } + + /* Field name argument */ + + if ( arg == NULL ) { + sieve_command_validate_error(valdtr, cmd, + "the %s %s expects at least one positional argument, but none was found", + sieve_command_identifier(cmd), sieve_command_type_name(cmd)); + return FALSE; + } + + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "field name", 1, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) ) + return FALSE; + + if ( sieve_argument_is_string_literal(arg) ) { + string_t *fname = sieve_ast_argument_str(arg); + + if ( !rfc2822_header_field_name_verify(str_c(fname), str_len(fname)) ) { + sieve_argument_validate_error(valdtr, arg, "deleteheader command:" + "specified field name `%s' is invalid", + str_sanitize(str_c(fname), 80)); + return FALSE; + } + + if ( !ext_editheader_header_allow_delete + (cmd->ext, str_c(fname)) ) { + sieve_argument_validate_warning + (valdtr, arg, "deleteheader command: " + "deleting specified header field `%s' is forbidden; " + "modification will be denied", + str_sanitize(str_c(fname), 80)); + } + } + + /* Value patterns argument */ + + arg = sieve_ast_argument_next(arg); + if ( arg == NULL ) { + /* There is none; let's not generate code for useless match arguments */ + sieve_match_type_arguments_remove(valdtr, cmd); + + return TRUE; + } + + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "value patterns", 2, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) ) + return FALSE; + + /* Validate the value patterns to a specified match type */ + return sieve_match_type_validate + (valdtr, cmd, arg, &mcht_default, &cmp_default); +} + +/* + * Code generation + */ + +static bool cmd_deleteheader_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &deleteheader_operation); + + /* Generate arguments */ + if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) + return FALSE; + + /* Emit a placeholder when the value-patterns argument is missing */ + if ( sieve_ast_argument_next(cmd->first_positional) == NULL ) + sieve_opr_omitted_emit(cgenv->sblock); + + return TRUE; +} + +/* + * Code dump + */ + +static bool cmd_deleteheader_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "DELETEHEADER"); + sieve_code_descend(denv); + + /* Optional operands */ + for (;;) { + int opt; + + if ( (opt=sieve_match_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_INDEX: + if ( !sieve_opr_number_dump(denv, address, "index") ) + return FALSE; + break; + case OPT_LAST: + sieve_code_dumpf(denv, "last"); + break; + default: + return FALSE; + } + }; + + if ( !sieve_opr_string_dump(denv, address, "field name") ) + return FALSE; + + return sieve_opr_stringlist_dump_ex(denv, address, "value patterns", ""); +} + +/* + * Code execution + */ + +static int cmd_deleteheader_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + int opt_code = 0; + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + string_t *field_name; + struct sieve_stringlist *vpattern_list = NULL; + struct edit_mail *edmail; + sieve_number_t index_offset = 0; + bool index_last = FALSE; + bool trace = FALSE; + int ret; + + /* + * Read operands + */ + + for (;;) { + int opt; + + if ( (opt=sieve_match_opr_optional_read + (renv, address, &opt_code, &ret, &cmp, &mcht)) < 0 ) + return ret; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_INDEX: + if ( (ret=sieve_opr_number_read(renv, address, "index", &index_offset)) + <= 0 ) + return ret; + + if ( index_offset > INT_MAX ) { + sieve_runtime_trace_error(renv, "index is > %d", INT_MAX); + return SIEVE_EXEC_BIN_CORRUPT; + } + + break; + case OPT_LAST: + index_last = TRUE; + break; + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + } + + /* Read field-name */ + if ( (ret=sieve_opr_string_read(renv, address, "field-name", &field_name)) + <= 0 ) + return ret; + + /* Read value-patterns */ + if ( (ret=sieve_opr_stringlist_read_ex + (renv, address, "value-patterns", TRUE, &vpattern_list)) <= 0 ) + return ret; + + /* + * Verify arguments + */ + + if ( !rfc2822_header_field_name_verify + (str_c(field_name), str_len(field_name)) ) { + sieve_runtime_error(renv, NULL, "deleteheader action: " + "specified field name `%s' is invalid", + str_sanitize(str_c(field_name), 80)); + return SIEVE_EXEC_FAILURE; + } + + if ( !ext_editheader_header_allow_delete + (this_ext, str_c(field_name)) ) { + sieve_runtime_warning(renv, NULL, "deleteheader action: " + "deleting specified header field `%s' is forbidden; " + "modification denied", + str_sanitize(str_c(field_name), 80)); + return SIEVE_EXEC_OK; + } + + /* + * Execute command + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "deleteheader command"); + + /* Start editing the mail */ + edmail = sieve_message_edit(renv->msgctx); + + trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS); + + /* Either do string matching or just kill all/indexed notify action(s) */ + if ( vpattern_list != NULL ) { + struct edit_mail_header_iter *edhiter; + struct sieve_match_context *mctx; + + if ( trace ) { + sieve_runtime_trace_descend(renv); + if ( index_offset != 0 ) { + sieve_runtime_trace(renv, 0, + "deleting matching occurrences of header `%s' at index %llu%s", + str_c(field_name), (unsigned long long)index_offset, + ( index_last ? " from last": "")); + } else { + sieve_runtime_trace(renv, 0, + "deleting matching occurrences of header `%s'", str_c(field_name)); + } + } + + /* Iterate through all headers and delete those that match */ + if ( (ret=edit_mail_headers_iterate_init + (edmail, str_c(field_name), index_last, &edhiter)) > 0 ) + { + int mret = 0; + sieve_number_t pos = 0; + + /* Initialize match */ + mctx = sieve_match_begin(renv, &mcht, &cmp); + + /* Match */ + for (;;) { + pos++; + + /* Check index if any */ + if ( index_offset == 0 || pos == index_offset ) { + const char *value; + int match; + + /* Match value against all value patterns */ + edit_mail_headers_iterate_get(edhiter, &value); + if ( (match=sieve_match_value + (mctx, value, strlen(value), vpattern_list)) < 0 ) + break; + + if ( match > 0 ) { + /* Remove it and iterate to next */ + sieve_runtime_trace(renv, 0, "deleting header with value `%s'", + value); + + if ( !edit_mail_headers_iterate_remove(edhiter) ) break; + continue; + } + } + + if ( !edit_mail_headers_iterate_next(edhiter) ) + break; + } + + /* Finish match */ + mret = sieve_match_end(&mctx, &ret); + + edit_mail_headers_iterate_deinit(&edhiter); + + if ( mret < 0 ) + return ret; + } + + if ( ret == 0 ) { + sieve_runtime_trace(renv, 0, "header `%s' not found", str_c(field_name)); + } else if ( ret < 0 ) { + sieve_runtime_warning(renv, NULL, "deleteheader action: " + "failed to delete occurrences of header `%s' (this should not happen!)", + str_c(field_name)); + } + + } else { + int index = ( index_last ? -((int)index_offset) : ((int)index_offset) ); + + if ( trace ) { + sieve_runtime_trace_descend(renv); + if ( index_offset != 0 ) { + sieve_runtime_trace(renv, 0, "deleting header `%s' at index %llu%s", + str_c(field_name), (unsigned long long)index_offset, + ( index_last ? " from last": "")); + } else { + sieve_runtime_trace(renv, 0, "deleting header `%s'", str_c(field_name)); + } + } + + /* Delete all occurrences of header */ + ret = edit_mail_header_delete(edmail, str_c(field_name), index); + + if ( ret < 0 ) { + sieve_runtime_warning(renv, NULL, "deleteheader action: " + "failed to delete occurrences of header `%s' (this should not happen!)", + str_c(field_name)); + } else if ( trace ) { + sieve_runtime_trace(renv, 0, "deleted %d occurrences of header `%s'", + ret, str_c(field_name)); + } + + } + + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader-common.c b/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader-common.c new file mode 100644 index 0000000..89fb180 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader-common.c @@ -0,0 +1,211 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "mempool.h" +#include "array.h" + +#include "rfc2822.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-settings.h" +#include "sieve-extensions.h" + +#include "ext-editheader-limits.h" +#include "ext-editheader-common.h" + +/* + * Extension configuration + */ + +struct ext_editheader_header { + const char *name; + + bool forbid_add:1; + bool forbid_delete:1; +}; + +struct ext_editheader_config { + pool_t pool; + + ARRAY(struct ext_editheader_header) headers; + + size_t max_header_size; +}; + +static struct ext_editheader_header * +ext_editheader_config_header_find(struct ext_editheader_config *ext_config, + const char *hname) +{ + struct ext_editheader_header *headers; + unsigned int count, i; + + headers = array_get_modifiable(&ext_config->headers, &count); + for (i = 0; i < count; i++) { + if (strcasecmp(hname, headers[i].name) == 0) + return &headers[i]; + } + return NULL; +} + +static void +ext_editheader_config_headers(struct sieve_instance *svinst, + struct ext_editheader_config *ext_config, + const char *setting, bool forbid_add, + bool forbid_delete) +{ + const char *setval; + + setval = sieve_setting_get(svinst, setting); + if (setval != NULL) { + const char **headers = t_strsplit_spaces(setval, " \t"); + + while (*headers != NULL) { + struct ext_editheader_header *header; + + if (!rfc2822_header_field_name_verify( + *headers, strlen(*headers))) { + e_warning(svinst->event, "editheader: " + "setting %s contains invalid header field name " + "`%s' (ignored)", + setting, *headers); + headers++; + continue; + } + + header = ext_editheader_config_header_find( + ext_config, *headers); + if (header == NULL) { + header = array_append_space( + &ext_config->headers); + header->name = p_strdup(ext_config->pool, + *headers); + } + + if (forbid_add) + header->forbid_add = TRUE; + if (forbid_delete) + header->forbid_delete = TRUE; + + headers++; + } + } +} + +bool ext_editheader_load(const struct sieve_extension *ext, void **context) +{ + struct ext_editheader_config *ext_config; + struct sieve_instance *svinst = ext->svinst; + size_t max_header_size; + pool_t pool; + + if (*context != NULL) { + ext_editheader_unload(ext); + *context = NULL; + } + + T_BEGIN { + pool = pool_alloconly_create("editheader_config", 1024); + ext_config = p_new(pool, struct ext_editheader_config, 1); + ext_config->pool = pool; + ext_config->max_header_size = + EXT_EDITHEADER_DEFAULT_MAX_HEADER_SIZE; + + p_array_init(&ext_config->headers, pool, 16); + + ext_editheader_config_headers( + svinst, ext_config, + "sieve_editheader_protected", TRUE, TRUE); + ext_editheader_config_headers( + svinst, ext_config, + "sieve_editheader_forbid_add", TRUE, FALSE); + ext_editheader_config_headers( + svinst, ext_config, + "sieve_editheader_forbid_delete", FALSE, TRUE); + + if (sieve_setting_get_size_value( + svinst, "sieve_editheader_max_header_size", + &max_header_size)) { + if (max_header_size < EXT_EDITHEADER_MINIMUM_MAX_HEADER_SIZE) { + e_warning(svinst->event, "editheader: " + "value of sieve_editheader_max_header_size setting " + "(=%zu) is less than the minimum (=%zu) " + "(ignored)", max_header_size, + (size_t)EXT_EDITHEADER_MINIMUM_MAX_HEADER_SIZE); + } else { + ext_config->max_header_size = max_header_size; + } + } + } T_END; + + *context = (void *)ext_config; + return TRUE; +} + +void ext_editheader_unload(const struct sieve_extension *ext) +{ + struct ext_editheader_config *ext_config = + (struct ext_editheader_config *)ext->context; + + if (ext_config != NULL) + pool_unref(&ext_config->pool); +} + +/* + * Protected headers + */ + +bool ext_editheader_header_allow_add(const struct sieve_extension *ext, + const char *hname) +{ + struct ext_editheader_config *ext_config = + (struct ext_editheader_config *)ext->context; + const struct ext_editheader_header *header; + + if (strcasecmp(hname, "subject") == 0) + return TRUE; + if (strcasecmp(hname, "x-sieve-redirected-from") == 0) + return FALSE; + + header = ext_editheader_config_header_find(ext_config, hname); + if (header == NULL) + return TRUE; + + return !header->forbid_add; +} + +bool ext_editheader_header_allow_delete(const struct sieve_extension *ext, + const char *hname) +{ + struct ext_editheader_config *ext_config = + (struct ext_editheader_config *)ext->context; + const struct ext_editheader_header *header; + + if (strcasecmp(hname, "received") == 0 || + strcasecmp(hname, "auto-submitted") == 0) + return FALSE; + if (strcasecmp(hname, "x-sieve-redirected-from") == 0) + return FALSE; + if (strcasecmp(hname, "subject") == 0) + return TRUE; + + header = ext_editheader_config_header_find(ext_config, hname); + if (header == NULL) + return TRUE; + + return !header->forbid_delete; +} + +/* + * Limits + */ + +bool ext_editheader_header_too_large(const struct sieve_extension *ext, + size_t size) +{ + struct ext_editheader_config *ext_config = + (struct ext_editheader_config *)ext->context; + + return size > ext_config->max_header_size; +} diff --git a/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader-common.h b/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader-common.h new file mode 100644 index 0000000..8a6cc36 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader-common.h @@ -0,0 +1,48 @@ +#ifndef EXT_EDITHEADER_COMMON_H +#define EXT_EDITHEADER_COMMON_H + +/* + * Commands + */ + +extern const struct sieve_command_def addheader_command; +extern const struct sieve_command_def deleteheader_command; + +/* + * Operations + */ + +enum ext_imap4flags_opcode { + EXT_EDITHEADER_OPERATION_ADDHEADER, + EXT_EDITHEADER_OPERATION_DELETEHEADER, +}; + +extern const struct sieve_operation_def addheader_operation; +extern const struct sieve_operation_def deleteheader_operation; + +/* + * Extension + */ + +extern const struct sieve_extension_def editheader_extension; + +bool ext_editheader_load(const struct sieve_extension *ext, void **context); +void ext_editheader_unload(const struct sieve_extension *ext); + +/* + * Protected headers + */ + +bool ext_editheader_header_allow_add(const struct sieve_extension *ext, + const char *hname); +bool ext_editheader_header_allow_delete(const struct sieve_extension *ext, + const char *hname); + +/* + * Limits + */ + +bool ext_editheader_header_too_large(const struct sieve_extension *ext, + size_t size); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader-limits.h b/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader-limits.h new file mode 100644 index 0000000..a8e834b --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader-limits.h @@ -0,0 +1,7 @@ +#ifndef EXT_EDITHEADER_LIMITS_H +#define EXT_EDITHEADER_LIMITS_H + +#define EXT_EDITHEADER_MINIMUM_MAX_HEADER_SIZE 1024 +#define EXT_EDITHEADER_DEFAULT_MAX_HEADER_SIZE 2048 + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader.c b/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader.c new file mode 100644 index 0000000..dc8eb12 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader.c @@ -0,0 +1,66 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension debug + * --------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5293 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-editheader-common.h" + +/* + * Operations + */ + +const struct sieve_operation_def *editheader_operations[] = { + &addheader_operation, + &deleteheader_operation +}; + +/* + * Extension + */ + +static bool ext_editheader_validator_load + (const struct sieve_extension *ext, struct sieve_validator *validator); + +const struct sieve_extension_def editheader_extension = { + .name = "editheader", + .load = ext_editheader_load, + .unload = ext_editheader_unload, + .validator_load = ext_editheader_validator_load, + SIEVE_EXT_DEFINE_OPERATIONS(editheader_operations) +}; + +static bool ext_editheader_validator_load +(const struct sieve_extension *ext, struct sieve_validator *validator) +{ + /* Register new commands */ + sieve_validator_register_command(validator, ext, &addheader_command); + sieve_validator_register_command(validator, ext, &deleteheader_command); + + return TRUE; +} + + + diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/Makefile.am b/pigeonhole/src/lib-sieve/plugins/enotify/Makefile.am new file mode 100644 index 0000000..4b65630 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/Makefile.am @@ -0,0 +1,44 @@ +SUBDIRS = mailto + +noinst_LTLIBRARIES = libsieve_ext_enotify.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-notify.c + +tests = \ + tst-valid-notify-method.c \ + tst-notify-method-capability.c + +var_modifiers = \ + vmodf-encodeurl.c + +notify_methods = \ + ./mailto/libsieve_ext_enotify_mailto.la + +libsieve_ext_enotify_la_DEPENDENCIES = \ + $(notify_methods) +libsieve_ext_enotify_la_LIBADD = \ + $(notify_methods) + +libsieve_ext_enotify_la_SOURCES = \ + ext-enotify.c \ + ext-enotify-common.c \ + $(commands) \ + $(tests) \ + $(var_modifiers) + +public_headers = \ + sieve-ext-enotify.h + +headers = \ + ext-enotify-limits.h \ + ext-enotify-common.h + +pkginc_libdir=$(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/Makefile.in b/pigeonhole/src/lib-sieve/plugins/enotify/Makefile.in new file mode 100644 index 0000000..fea2423 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/Makefile.in @@ -0,0 +1,904 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/enotify +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(pkginc_lib_HEADERS) $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +am__objects_1 = cmd-notify.lo +am__objects_2 = tst-valid-notify-method.lo \ + tst-notify-method-capability.lo +am__objects_3 = vmodf-encodeurl.lo +am_libsieve_ext_enotify_la_OBJECTS = ext-enotify.lo \ + ext-enotify-common.lo $(am__objects_1) $(am__objects_2) \ + $(am__objects_3) +libsieve_ext_enotify_la_OBJECTS = \ + $(am_libsieve_ext_enotify_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/cmd-notify.Plo \ + ./$(DEPDIR)/ext-enotify-common.Plo ./$(DEPDIR)/ext-enotify.Plo \ + ./$(DEPDIR)/tst-notify-method-capability.Plo \ + ./$(DEPDIR)/tst-valid-notify-method.Plo \ + ./$(DEPDIR)/vmodf-encodeurl.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_enotify_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_enotify_la_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkginc_libdir)" +HEADERS = $(noinst_HEADERS) $(pkginc_lib_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = mailto +noinst_LTLIBRARIES = libsieve_ext_enotify.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-notify.c + +tests = \ + tst-valid-notify-method.c \ + tst-notify-method-capability.c + +var_modifiers = \ + vmodf-encodeurl.c + +notify_methods = \ + ./mailto/libsieve_ext_enotify_mailto.la + +libsieve_ext_enotify_la_DEPENDENCIES = \ + $(notify_methods) + +libsieve_ext_enotify_la_LIBADD = \ + $(notify_methods) + +libsieve_ext_enotify_la_SOURCES = \ + ext-enotify.c \ + ext-enotify-common.c \ + $(commands) \ + $(tests) \ + $(var_modifiers) + +public_headers = \ + sieve-ext-enotify.h + +headers = \ + ext-enotify-limits.h \ + ext-enotify-common.h + +pkginc_libdir = $(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/enotify/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/enotify/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_enotify.la: $(libsieve_ext_enotify_la_OBJECTS) $(libsieve_ext_enotify_la_DEPENDENCIES) $(EXTRA_libsieve_ext_enotify_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_enotify_la_OBJECTS) $(libsieve_ext_enotify_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-notify.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-enotify-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-enotify.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-notify-method-capability.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-valid-notify-method.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmodf-encodeurl.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkginc_libHEADERS: $(pkginc_lib_HEADERS) + @$(NORMAL_INSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkginc_libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkginc_libdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkginc_libdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkginc_libdir)" || exit $$?; \ + done + +uninstall-pkginc_libHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkginc_libdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(pkginc_libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-recursive + -rm -f ./$(DEPDIR)/cmd-notify.Plo + -rm -f ./$(DEPDIR)/ext-enotify-common.Plo + -rm -f ./$(DEPDIR)/ext-enotify.Plo + -rm -f ./$(DEPDIR)/tst-notify-method-capability.Plo + -rm -f ./$(DEPDIR)/tst-valid-notify-method.Plo + -rm -f ./$(DEPDIR)/vmodf-encodeurl.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-pkginc_libHEADERS + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f ./$(DEPDIR)/cmd-notify.Plo + -rm -f ./$(DEPDIR)/ext-enotify-common.Plo + -rm -f ./$(DEPDIR)/ext-enotify.Plo + -rm -f ./$(DEPDIR)/tst-notify-method-capability.Plo + -rm -f ./$(DEPDIR)/tst-valid-notify-method.Plo + -rm -f ./$(DEPDIR)/vmodf-encodeurl.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-pkginc_libHEADERS + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--depfiles check check-am clean clean-generic clean-libtool \ + clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkginc_libHEADERS \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am \ + uninstall-pkginc_libHEADERS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/cmd-notify.c b/pigeonhole/src/lib-sieve/plugins/enotify/cmd-notify.c new file mode 100644 index 0000000..4fe121a --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/cmd-notify.c @@ -0,0 +1,621 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-result.h" + +#include "ext-enotify-common.h" + +/* + * Forward declarations + */ + +static const struct sieve_argument_def notify_importance_tag; +static const struct sieve_argument_def notify_from_tag; +static const struct sieve_argument_def notify_options_tag; +static const struct sieve_argument_def notify_message_tag; + +/* + * Notify command + * + * Syntax: + * notify [":from" string] + * [":importance" <"1" / "2" / "3">] + * [":options" string-list] + * [":message" string] + * <method: string> + */ + +static bool +cmd_notify_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool +cmd_notify_pre_validate(struct sieve_validator *validator, + struct sieve_command *cmd); +static bool +cmd_notify_validate(struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool +cmd_notify_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def notify_command = { + .identifier = "notify", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_notify_registered, + .pre_validate = cmd_notify_pre_validate, + .validate = cmd_notify_validate, + .generate = cmd_notify_generate, +}; + +/* + * Notify command tags + */ + +/* Forward declarations */ + +static bool +cmd_notify_validate_string_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +cmd_notify_validate_stringlist_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +cmd_notify_validate_importance_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +/* Argument objects */ + +static const struct sieve_argument_def notify_from_tag = { + .identifier = "from", + .validate = cmd_notify_validate_string_tag +}; + +static const struct sieve_argument_def notify_options_tag = { + .identifier = "options", + .validate = cmd_notify_validate_stringlist_tag +}; + +static const struct sieve_argument_def notify_message_tag = { + .identifier = "message", + .validate = cmd_notify_validate_string_tag +}; + +static const struct sieve_argument_def notify_importance_tag = { + .identifier = "importance", + .validate = cmd_notify_validate_importance_tag +}; + +/* + * Notify operation + */ + +static bool +cmd_notify_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_notify_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def notify_operation = { + .mnemonic = "NOTIFY", + .ext_def = &enotify_extension, + .code = EXT_ENOTIFY_OPERATION_NOTIFY, + .dump = cmd_notify_operation_dump, + .execute = cmd_notify_operation_execute +}; + +/* + * Notify action + */ + +/* Forward declarations */ + +static int +act_notify_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other); +static void +act_notify_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, + bool *keep); +static int +act_notify_commit(const struct sieve_action_exec_env *aenv, void *tr_context); + +/* Action object */ + +const struct sieve_action_def act_notify = { + .name = "notify", + .check_duplicate =act_notify_check_duplicate, + .print = act_notify_print, + .commit = act_notify_commit, +}; + +/* + * Command validation context + */ + +struct cmd_notify_context_data { + struct sieve_ast_argument *from; + struct sieve_ast_argument *message; + struct sieve_ast_argument *options; +}; + +/* + * Tag validation + */ + +static bool +cmd_notify_validate_string_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct cmd_notify_context_data *ctx_data = + (struct cmd_notify_context_data *)cmd->data; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :from <string> + * :message <string> + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING, FALSE)) + return FALSE; + + if (sieve_argument_is(tag, notify_from_tag)) { + ctx_data->from = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + } else if (sieve_argument_is(tag, notify_message_tag)) { + ctx_data->message = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + } + return TRUE; +} + +static bool +cmd_notify_validate_stringlist_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct cmd_notify_context_data *ctx_data = + (struct cmd_notify_context_data *)cmd->data; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :options string-list + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING_LIST, FALSE)) + return FALSE; + + /* Assign context */ + ctx_data->options = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +static bool +cmd_notify_validate_importance_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + const struct sieve_ast_argument *tag = *arg; + const char *impstr; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :importance <"1" / "2" / "3"> + */ + if (sieve_ast_argument_type(*arg) != SAAT_STRING) { + /* Not a string */ + sieve_argument_validate_error( + valdtr, *arg, + "the :importance tag for the notify command requires a string parameter, " + "but %s was found", sieve_ast_argument_name(*arg)); + return FALSE; + } + + impstr = sieve_ast_argument_strc(*arg); + if (impstr[0] < '1' || impstr[0] > '3' || impstr[1] != '\0') { + /* Invalid importance */ + sieve_argument_validate_error( + valdtr, *arg, + "invalid :importance value for notify command: %s", + impstr); + return FALSE; + } + + sieve_ast_argument_number_substitute(*arg, impstr[0] - '0'); + (*arg)->argument = sieve_argument_create((*arg)->ast, &number_argument, + tag->argument->ext, + tag->argument->id_code); + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Command registration + */ + +static bool +cmd_notify_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag(valdtr, cmd_reg, ext, + ¬ify_importance_tag, + CMD_NOTIFY_OPT_IMPORTANCE); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + ¬ify_from_tag, CMD_NOTIFY_OPT_FROM); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + ¬ify_options_tag, + CMD_NOTIFY_OPT_OPTIONS); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + ¬ify_message_tag, + CMD_NOTIFY_OPT_MESSAGE); + return TRUE; +} + +/* + * Command validation + */ + +static bool +cmd_notify_pre_validate(struct sieve_validator *validator ATTR_UNUSED, + struct sieve_command *cmd) +{ + struct cmd_notify_context_data *ctx_data; + + /* Assign context */ + ctx_data = p_new(sieve_command_pool(cmd), + struct cmd_notify_context_data, 1); + cmd->data = ctx_data; + + return TRUE; +} + +static bool +cmd_notify_validate(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + struct cmd_notify_context_data *ctx_data = + (struct cmd_notify_context_data *)cmd->data; + + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "method", 1, + SAAT_STRING)) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE)) + return FALSE; + + return ext_enotify_compile_check_arguments( + valdtr, cmd, arg, ctx_data->message, ctx_data->from, + ctx_data->options); +} + +/* + * Code generation + */ + +static bool +cmd_notify_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, ¬ify_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool +cmd_notify_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "NOTIFY"); + sieve_code_descend(denv); + + /* Dump optional operands */ + + for (;;) { + int opt; + bool opok = TRUE; + + if ((opt = sieve_opr_optional_dump(denv, address, + &opt_code)) < 0) + return FALSE; + + if (opt == 0) + break; + + switch (opt_code) { + case CMD_NOTIFY_OPT_IMPORTANCE: + opok = sieve_opr_number_dump(denv, address, + "importance"); + break; + case CMD_NOTIFY_OPT_FROM: + opok = sieve_opr_string_dump(denv, address, "from"); + break; + case CMD_NOTIFY_OPT_OPTIONS: + opok = sieve_opr_stringlist_dump(denv, address, + "options"); + break; + case CMD_NOTIFY_OPT_MESSAGE: + opok = sieve_opr_string_dump(denv, address, "message"); + break; + default: + return FALSE; + } + + if (!opok) + return FALSE; + } + + /* Dump method operand */ + return sieve_opr_string_dump(denv, address, "method"); +} + +/* + * Code execution + */ + +static int +cmd_notify_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct sieve_side_effects_list *slist = NULL; + struct sieve_enotify_action *act; + void *method_context; + pool_t pool; + int opt_code = 0; + sieve_number_t importance = 2; + struct sieve_stringlist *options = NULL; + const struct sieve_enotify_method *method; + string_t *method_uri, *message = NULL, *from = NULL; + int ret; + + /* + * Read operands + */ + + /* Optional operands */ + + for (;;) { + int opt; + + if ((opt = sieve_opr_optional_read(renv, address, + &opt_code)) < 0) + return SIEVE_EXEC_BIN_CORRUPT; + + if (opt == 0) break; + + switch (opt_code) { + case CMD_NOTIFY_OPT_IMPORTANCE: + ret = sieve_opr_number_read(renv, address, "importance", + &importance); + break; + case CMD_NOTIFY_OPT_FROM: + ret = sieve_opr_string_read(renv, address, "from", + &from); + break; + case CMD_NOTIFY_OPT_MESSAGE: + ret = sieve_opr_string_read(renv, address, "message", + &message); + break; + case CMD_NOTIFY_OPT_OPTIONS: + ret = sieve_opr_stringlist_read(renv, address, + "options", &options); + break; + default: + sieve_runtime_trace_error( + renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if (ret <= 0) + return ret; + } + + /* Method operand */ + + if ((ret = sieve_opr_string_read(renv, address, "method", + &method_uri)) <= 0) + return ret; + + /* + * Perform operation + */ + + /* Enforce 0 < importance < 4 (just to be sure) */ + + if (importance < 1) + importance = 1; + else if (importance > 3) + importance = 3; + + /* Trace */ + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_ACTIONS)) { + sieve_runtime_trace(renv, 0, "notify action"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace(renv, 0, "notify with uri `%s'", + str_sanitize(str_c(method_uri), 80)); + } + + /* Check operands */ + + if ((ret = ext_enotify_runtime_check_operands(renv, method_uri, message, + from, options, &method, + &method_context)) > 0) + { + /* Add notify action to the result */ + pool = sieve_result_pool(renv->result); + act = p_new(pool, struct sieve_enotify_action, 1); + act->method = method; + act->method_context = method_context; + act->importance = importance; + if (message != NULL) + act->message = p_strdup(pool, str_c(message)); + if (from != NULL) + act->from = p_strdup(pool, str_c(from)); + + if (sieve_result_add_action(renv, this_ext, "notify", + &act_notify, slist, + (void *)act, 0, FALSE) < 0) + return SIEVE_EXEC_FAILURE; + + return SIEVE_EXEC_OK; + } + return ret; +} + +/* + * Action + */ + +/* Runtime verification */ + +static int +act_notify_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_enotify_action *nact, *nact_other; + const struct sieve_enotify_method_def *nmth_def; + struct sieve_enotify_env nenv; + int result; + + if (act->context == NULL || act_other->context == NULL) + return 0; + + nact = (const struct sieve_enotify_action *)act->context; + nact_other = (const struct sieve_enotify_action *)act_other->context; + + if (nact->method == NULL || nact->method->def == NULL) + return 0; + + nmth_def = nact->method->def; + if (nmth_def->action_check_duplicates == NULL) + return 0; + + i_zero(&nenv); + nenv.svinst = eenv->svinst; + nenv.method = nact->method; + nenv.ehandler = renv->ehandler; + nenv.location = act->location; + nenv.event = event_create(nenv.svinst->event); + event_set_append_log_prefix(nenv.event, "notify: "); + + result = nmth_def->action_check_duplicates(&nenv, nact, nact_other); + + event_unref(&nenv.event); + + return result; +} + +/* Result printing */ + +static void +act_notify_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, + bool *keep ATTR_UNUSED) +{ + const struct sieve_enotify_action *act = + (const struct sieve_enotify_action *)action->context; + const struct sieve_enotify_method *method; + + method = act->method; + + if (method->def != NULL) { + sieve_result_action_printf( + rpenv, "send notification with method '%s:':", + method->def->identifier); + + if (method->def->action_print != NULL) { + struct sieve_enotify_print_env penv; + + i_zero(&penv); + penv.result_penv = rpenv; + + method->def->action_print(&penv, act); + } + } +} + +/* Result execution */ + +static int +act_notify_commit(const struct sieve_action_exec_env *aenv, + void *tr_context ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + const struct sieve_enotify_action *act = + (const struct sieve_enotify_action *)aenv->action->context; + const struct sieve_enotify_method *method = act->method; + struct sieve_enotify_exec_env nenv; + int ret = 0; + + if (method->def != NULL && method->def->action_execute != NULL) { + /* Compose log structure */ + i_zero(&nenv); + nenv.svinst = eenv->svinst; + nenv.flags = eenv->flags; + nenv.method = method; + nenv.scriptenv = eenv->scriptenv; + nenv.msgdata = eenv->msgdata; + nenv.msgctx = aenv->msgctx; + + nenv.ehandler = aenv->ehandler; + nenv.event = aenv->event; + + ret = method->def->action_execute(&nenv, act); + if (ret >= 0) + eenv->exec_status->significant_action_executed = TRUE; + } + + return (ret >= 0 ? SIEVE_EXEC_OK : SIEVE_EXEC_TEMP_FAILURE); +} diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify-common.c b/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify-common.c new file mode 100644 index 0000000..e0539f0 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify-common.c @@ -0,0 +1,718 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-ast.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "ext-enotify-limits.h" +#include "ext-enotify-common.h" + +#include <ctype.h> + +/* FIXME: (from draft RFC) + + Header/envelope tests [Sieve] together with Sieve variables can be used to + extract the list of users to receive notifications from the incoming email + message or its envelope. This is potentially quite dangerous, as this can be + used for Deny Of Service attacks on recipients controlled by the message + sender. For this reason implementations SHOULD NOT allow use of variables + containing values extracted from the email message in the method parameter to + the notify action. Note that violation of this SHOULD NOT may result in* the + creation of an open relay, i.e. any sender would be able to create specially + crafted email messages that would result in notifications delivered to + recipients under the control of the sender. In worst case this might result + in financial loss by user controlling the Sieve script and/or by recipients + of notifications (e.g. if a notification is an SMS message). + + --> This is currently not possible to check. + */ + +/* + * Notify capability + */ + +static const char * +ext_notify_get_methods_string(const struct sieve_extension *ntfy_ext); + +const struct sieve_extension_capabilities notify_capabilities = { + "notify", + ext_notify_get_methods_string +}; + +/* + * Core notification methods + */ + +extern const struct sieve_enotify_method_def mailto_notify; + +/* + * Notify method registry + */ + +static const struct sieve_enotify_method * +ext_enotify_method_register(struct sieve_instance *svinst, + struct ext_enotify_context *ectx, + const struct sieve_enotify_method_def *nmth_def) +{ + struct sieve_enotify_method *nmth; + int nmth_id = (int)array_count(&ectx->notify_methods); + + nmth = array_append_space(&ectx->notify_methods); + nmth->def = nmth_def; + nmth->id = nmth_id; + nmth->svinst = svinst; + + if (nmth_def->load != NULL) + nmth_def->load(nmth, &nmth->context); + + return nmth; +} + +void ext_enotify_methods_init(struct sieve_instance *svinst, + struct ext_enotify_context *ectx) +{ + p_array_init(&ectx->notify_methods, default_pool, 4); + + ext_enotify_method_register(svinst, ectx, &mailto_notify); +} + +void ext_enotify_methods_deinit(struct ext_enotify_context *ectx) +{ + const struct sieve_enotify_method *methods; + unsigned int meth_count, i; + + methods = array_get(&ectx->notify_methods, &meth_count); + for (i = 0; i < meth_count; i++) { + if (methods[i].def != NULL && methods[i].def->unload != NULL) + methods[i].def->unload(&methods[i]); + } + + array_free(&ectx->notify_methods); +} + +const struct sieve_enotify_method * +sieve_enotify_method_register(struct sieve_instance *svinst, + const struct sieve_enotify_method_def *nmth_def) +{ + const struct sieve_extension *ntfy_ext = + sieve_extension_get_by_name(svinst, "enotify"); + + if (ntfy_ext != NULL) { + struct ext_enotify_context *ectx = + (struct ext_enotify_context *) ntfy_ext->context; + + return ext_enotify_method_register(svinst, ectx, nmth_def); + } + return NULL; +} + +void sieve_enotify_method_unregister(const struct sieve_enotify_method *nmth) +{ + struct sieve_instance *svinst = nmth->svinst; + const struct sieve_extension *ntfy_ext = + sieve_extension_get_by_name(svinst, "enotify"); + + if (ntfy_ext != NULL) { + struct ext_enotify_context *ectx = + (struct ext_enotify_context *) ntfy_ext->context; + int nmth_id = nmth->id; + + if (nmth_id >= 0 && + nmth_id < (int)array_count(&ectx->notify_methods)) { + struct sieve_enotify_method *nmth_mod = + array_idx_modifiable(&ectx->notify_methods, + nmth_id); + + nmth_mod->def = NULL; + } + } +} + +const struct sieve_enotify_method * +ext_enotify_method_find(const struct sieve_extension *ntfy_ext, + const char *identifier) +{ + struct ext_enotify_context *ectx = + (struct ext_enotify_context *)ntfy_ext->context; + unsigned int meth_count, i; + const struct sieve_enotify_method *methods; + + methods = array_get(&ectx->notify_methods, &meth_count); + for (i = 0; i < meth_count; i++) { + if (methods[i].def == NULL) + continue; + + if (strcasecmp(methods[i].def->identifier, identifier) == 0) + return &methods[i]; + } + return NULL; +} + +static const char * +ext_notify_get_methods_string(const struct sieve_extension *ntfy_ext) +{ + struct ext_enotify_context *ectx = + (struct ext_enotify_context *) ntfy_ext->context; + unsigned int meth_count, i; + const struct sieve_enotify_method *methods; + string_t *result = t_str_new(128); + + methods = array_get(&ectx->notify_methods, &meth_count); + if (meth_count > 0) { + for (i = 0; i < meth_count; i++) { + if (str_len(result) > 0) + str_append_c(result, ' '); + if (methods[i].def != NULL) + str_append(result, methods[i].def->identifier); + } + return str_c(result); + } + return NULL; +} + +/* + * Compile-time argument validation + */ + +static const char *ext_enotify_uri_scheme_parse(const char **uri_p) +{ + string_t *scheme = t_str_new(EXT_ENOTIFY_MAX_SCHEME_LEN); + const char *p = *uri_p; + unsigned int len = 0; + + /* RFC 3968: + + scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + + FIXME: we do not allow '%' in schemes. Is this correct? + */ + + if (!i_isalpha(*p)) + return NULL; + + str_append_c(scheme, *p); + p++; + + while (*p != '\0' && len < EXT_ENOTIFY_MAX_SCHEME_LEN) { + if (!i_isalnum(*p) && *p != '+' && *p != '-' && *p != '.') + break; + + str_append_c(scheme, *p); + p++; + len++; + } + + if (*p != ':') + return NULL; + p++; + + *uri_p = p; + return str_c(scheme); +} + +static bool +ext_enotify_option_parse(struct sieve_enotify_env *nenv, + const char *option, bool name_only, + const char **opt_name_r, const char **opt_value_r) +{ + const char *p = option; + + /* "<optionname>=<value>". + + l-d = ALPHA / DIGIT + l-d-p = l-d / "." / "-" / "_" + optionname = l-d *l-d-p + value = *(%x01-09 / %x0B-0C / %x0E-FF) + */ + + /* + * Parse option name + */ + + /* optionname = l-d *l-d-p + */ + + /* Explicitly report empty option as such */ + if (*p == '\0') { + sieve_enotify_error(nenv, "empty option specified"); + return FALSE; + } + + /* l-d = ALPHA / DIGIT */ + if (i_isalnum(*p)) { + p++; + + /* l-d-p = l-d / "." / "-" / "_" */ + while (i_isalnum(*p) || *p == '.' || *p == '-' || *p == '_') + p++; + } + + /* Parsing must end at '=' and we must parse at least one character */ + if (*p != '=' || p == option) { + sieve_enotify_error( + nenv, "invalid option name specified in option '%s'", + str_sanitize(option, 80)); + return FALSE; + } + + /* Assign option name */ + if (opt_name_r != NULL) + *opt_name_r = t_strdup_until(option, p); + + /* Skip '=' */ + p++; + + /* Exit now if only the option name is of interest */ + if (name_only) + return TRUE; + + /* + * Parse option value + */ + + /* value = *(%x01-09 / %x0B-0C / %x0E-FF) */ + while (*p != '\0' && *p != 0x0A && *p != 0x0D) + p++; + + /* Parse must end at end of string */ + if (*p != '\0') { + sieve_enotify_error( + nenv, "notify command: " + "invalid option value specified in option '%s'", + str_sanitize(option, 80)); + return FALSE; + } + + /* Assign option value */ + if (opt_value_r != NULL) + *opt_value_r = p; + + return TRUE; +} + +struct _ext_enotify_option_check_context { + struct sieve_instance *svinst; + struct sieve_validator *valdtr; + const struct sieve_enotify_method *method; +}; + +static int +_ext_enotify_option_check(void *context, struct sieve_ast_argument *arg) +{ + struct _ext_enotify_option_check_context *optn_context = + (struct _ext_enotify_option_check_context *) context; + struct sieve_validator *valdtr = optn_context->valdtr; + const struct sieve_enotify_method *method = optn_context->method; + struct sieve_enotify_env nenv; + const char *option = sieve_ast_argument_strc(arg); + const char *opt_name = NULL, *opt_value = NULL; + bool check = TRUE; + int result = 1; + + /* Compose log structure */ + i_zero(&nenv); + nenv.svinst = optn_context->svinst; + nenv.method = method; + nenv.ehandler = sieve_validator_error_handler(valdtr); + nenv.location = sieve_error_script_location( + sieve_validator_script(valdtr), arg->source_line); + nenv.event = event_create(nenv.svinst->event); + event_set_append_log_prefix(nenv.event, "notify command: "); + + /* Parse option */ + if (!sieve_argument_is_string_literal(arg)) { + /* Variable string: partial option parse + + If the string item is not a string literal, it cannot be + validated fully at compile time. We can however check whether + the '=' is in the string specification and whether the part + before the '=' is a valid option name. In that case, the + method option check function is called with the value + parameter equal to NULL, meaning that it should only check + the validity of the option itself and not the assigned value. + */ + if (!ext_enotify_option_parse(NULL, option, TRUE, + &opt_name, &opt_value)) + check = FALSE; + } else { + /* Literal string: full option parse */ + if (!ext_enotify_option_parse(&nenv, option, FALSE, + &opt_name, &opt_value)) + result = -1; + } + + /* Call method's option check function */ + if (result > 0 && check && method->def != NULL && + method->def->compile_check_option != NULL) { + result = (method->def->compile_check_option(&nenv, opt_name, + opt_value) ? + 1 : -1 ); + } + + event_unref(&nenv.event); + return result; +} + +bool ext_enotify_compile_check_arguments(struct sieve_validator *valdtr, + struct sieve_command *cmd, + struct sieve_ast_argument *uri_arg, + struct sieve_ast_argument *msg_arg, + struct sieve_ast_argument *from_arg, + struct sieve_ast_argument *options_arg) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct sieve_instance *svinst = this_ext->svinst; + const char *uri = sieve_ast_argument_strc(uri_arg); + const char *scheme; + const struct sieve_enotify_method *method; + struct sieve_enotify_env nenv; + bool result = TRUE; + + /* If the uri string is not a constant literal, we cannot determine + which method is used, so we bail out successfully and defer checking + to runtime. + */ + if (!sieve_argument_is_string_literal(uri_arg)) + return TRUE; + + /* Parse scheme part of URI */ + if ((scheme = ext_enotify_uri_scheme_parse(&uri)) == NULL) { + sieve_argument_validate_error( + valdtr, uri_arg, "notify command: " + "invalid scheme part for method URI '%s'", + str_sanitize(sieve_ast_argument_strc(uri_arg), 80)); + return FALSE; + } + + /* Find used method with the parsed scheme identifier */ + if ((method = ext_enotify_method_find(this_ext, scheme)) == NULL) { + sieve_argument_validate_error( + valdtr, uri_arg, "notify command: " + "invalid method '%s'", scheme); + return FALSE; + } + + if (method->def == NULL) + return TRUE; + + /* Compose log structure */ + i_zero(&nenv); + nenv.svinst = svinst; + nenv.method = method; + + /* Check URI itself */ + if (result && method->def->compile_check_uri != NULL) { + /* Set log location to location of URI argument */ + nenv.ehandler = sieve_validator_error_handler(valdtr); + nenv.location = sieve_error_script_location( + sieve_validator_script(valdtr), uri_arg->source_line); + nenv.event = event_create(nenv.svinst->event); + event_set_append_log_prefix(nenv.event, "notify command: "); + + /* Execute method check function */ + result = method->def->compile_check_uri( + &nenv, sieve_ast_argument_strc(uri_arg), uri); + } + + /* Check :message argument */ + if (result && msg_arg != NULL && + sieve_argument_is_string_literal(msg_arg) && + method->def->compile_check_message != NULL ) { + /* Set log location to location of :message argument */ + event_unref(&nenv.event); + nenv.ehandler = sieve_validator_error_handler(valdtr); + nenv.location = sieve_error_script_location( + sieve_validator_script(valdtr), msg_arg->source_line); + nenv.event = event_create(nenv.svinst->event); + event_set_append_log_prefix(nenv.event, "notify command: "); + + /* Execute method check function */ + result = method->def->compile_check_message( + &nenv, sieve_ast_argument_str(msg_arg)); + } + + /* Check :from argument */ + if (result && from_arg != NULL && + sieve_argument_is_string_literal(from_arg) && + method->def->compile_check_from != NULL ) { + /* Set log location to location of :from argument */ + event_unref(&nenv.event); + nenv.ehandler = sieve_validator_error_handler(valdtr); + nenv.location = sieve_error_script_location( + sieve_validator_script(valdtr), from_arg->source_line); + nenv.event = event_create(nenv.svinst->event); + event_set_append_log_prefix(nenv.event, "notify command: "); + + /* Execute method check function */ + result = method->def->compile_check_from( + &nenv, sieve_ast_argument_str(from_arg)); + } + + event_unref(&nenv.event); + + /* Check :options argument */ + if (result && options_arg != NULL) { + struct sieve_ast_argument *option = options_arg; + struct _ext_enotify_option_check_context optn_context = { + svinst, valdtr, method }; + + /* Parse and check options */ + result = (sieve_ast_stringlist_map( + &option, (void *) &optn_context, + _ext_enotify_option_check) > 0); + + /* Discard argument if options are not accepted by method */ + if (result && method->def->compile_check_option == NULL) { + sieve_argument_validate_warning( + valdtr, options_arg, "notify command: " + "method '%s' accepts no options", scheme); + (void)sieve_ast_arguments_detach(options_arg, 1); + } + } + return result; +} + +/* + * Runtime operand checking + */ + +bool ext_enotify_runtime_method_validate(const struct sieve_runtime_env *renv, + string_t *method_uri) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_extension *this_ext = renv->oprtn->ext; + const struct sieve_enotify_method *method; + const char *uri = str_c(method_uri); + const char *scheme; + bool result = TRUE; + + /* Get the method */ + + if ((scheme = ext_enotify_uri_scheme_parse(&uri)) == NULL) + return FALSE; + if ((method = ext_enotify_method_find(this_ext, scheme)) == NULL) + return FALSE; + + /* Validate the provided URI */ + + if (method->def != NULL && method->def->runtime_check_uri != NULL) { + struct sieve_enotify_env nenv; + + i_zero(&nenv); + nenv.svinst = eenv->svinst; + nenv.method = method; + nenv.ehandler = renv->ehandler; + nenv.location = sieve_runtime_get_full_command_location(renv), + nenv.event = event_create(nenv.svinst->event); + event_set_append_log_prefix(nenv.event, + "valid_notify_method test: "); + + /* Use the method check function to validate the URI */ + result = method->def->runtime_check_uri( + &nenv, str_c(method_uri), uri); + + event_unref(&nenv.event); + } + + return result; +} + +static const struct +sieve_enotify_method *ext_enotify_get_method( + const struct sieve_runtime_env *renv, string_t *method_uri, + const char **uri_body_r) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + const struct sieve_enotify_method *method; + const char *uri = str_c(method_uri); + const char *scheme; + + /* Parse part before ':' of the uri (the scheme) and use it to identify + notify method. + */ + if ((scheme = ext_enotify_uri_scheme_parse(&uri)) == NULL) { + sieve_runtime_error( + renv, NULL, "invalid scheme part for method URI '%s'", + str_sanitize(str_c(method_uri), 80)); + return NULL; + } + + /* Find the notify method */ + if ((method = ext_enotify_method_find(this_ext, scheme)) == NULL) { + sieve_runtime_error(renv, NULL, "invalid notify method '%s'", + scheme); + return NULL; + } + + /* Return the parse pointer and the found method */ + *uri_body_r = uri; + return method; +} + +const char * +ext_enotify_runtime_get_method_capability(const struct sieve_runtime_env *renv, + string_t *method_uri, + const char *capability) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_enotify_method *method; + const char *uri_body; + const char *result = NULL; + + /* Get method */ + method = ext_enotify_get_method(renv, method_uri, &uri_body); + if ( method == NULL ) return NULL; + + /* Get requested capability */ + if (method->def != NULL && + method->def->runtime_get_method_capability != NULL) { + struct sieve_enotify_env nenv; + + i_zero(&nenv); + nenv.svinst = eenv->svinst; + nenv.method = method; + nenv.ehandler = renv->ehandler; + nenv.location = sieve_runtime_get_full_command_location(renv), + nenv.event = event_create(nenv.svinst->event); + event_set_append_log_prefix(nenv.event, + "notify_method_capability test: "); + + /* Execute method function to acquire capability value */ + result = method->def->runtime_get_method_capability( + &nenv, str_c(method_uri), uri_body, capability); + + event_unref(&nenv.event); + } + + return result; +} + +int ext_enotify_runtime_check_operands( + const struct sieve_runtime_env *renv, string_t *method_uri, + string_t *message, string_t *from, struct sieve_stringlist *options, + const struct sieve_enotify_method **method_r, void **method_context) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_enotify_method *method; + const char *uri_body; + + /* Get method */ + method = ext_enotify_get_method(renv, method_uri, &uri_body); + if (method == NULL) + return SIEVE_EXEC_FAILURE; + + /* Check provided operands */ + if (method->def != NULL && + method->def->runtime_check_operands != NULL) { + struct sieve_enotify_env nenv; + int result = SIEVE_EXEC_OK; + + i_zero(&nenv); + nenv.svinst = eenv->svinst; + nenv.method = method; + nenv.ehandler = renv->ehandler; + nenv.location = sieve_runtime_get_full_command_location(renv), + nenv.event = event_create(nenv.svinst->event); + event_set_append_log_prefix(nenv.event, "notify_action: "); + + /* Execute check function */ + if (method->def->runtime_check_operands( + &nenv, str_c(method_uri), uri_body, message, from, + sieve_result_pool(renv->result), method_context)) { + + /* Check any provided options */ + if (options != NULL) { + string_t *option = NULL; + int ret; + + /* Iterate through all provided options */ + while ((ret = sieve_stringlist_next_item( + options, &option)) > 0) { + const char *opt_name = NULL; + const char *opt_value = NULL; + + /* Parse option into <optionname> and + <value> */ + if (ext_enotify_option_parse( + &nenv, str_c(option), FALSE, + &opt_name, &opt_value)) { + + /* Set option */ + if (method->def->runtime_set_option != NULL) { + (void)method->def->runtime_set_option( + &nenv, *method_context, + opt_name, opt_value); + } + } + } + + /* Check for binary corruptions encountered + during string list iteration */ + if (ret >= 0) { + *method_r = method; + } else { + /* Binary corrupt */ + sieve_runtime_trace_error( + renv, "invalid item in options string list"); + result = SIEVE_EXEC_BIN_CORRUPT; + } + + } else { + /* No options */ + *method_r = method; + } + + } else { + /* Operand check failed */ + result = SIEVE_EXEC_FAILURE; + } + + event_unref(&nenv.event); + return result; + } + + /* No check function defined: a most unlikely situation */ + *method_context = NULL; + *method_r = method; + return SIEVE_EXEC_OK; +} + +/* + * Notify method printing + */ + +void sieve_enotify_method_printf(const struct sieve_enotify_print_env *penv, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + sieve_result_vprintf(penv->result_penv, fmt, args); + va_end(args); +} + +/* + * Action execution + */ + +struct event_passthrough * +sieve_enotify_create_finish_event(const struct sieve_enotify_exec_env *nenv) +{ + struct event_passthrough *e = + event_create_passthrough(nenv->event)-> + set_name("sieve_action_finished"); + + return e; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify-common.h b/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify-common.h new file mode 100644 index 0000000..ec43202 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify-common.h @@ -0,0 +1,122 @@ +#ifndef EXT_ENOTIFY_COMMON_H +#define EXT_ENOTIFY_COMMON_H + +#include "lib.h" +#include "array.h" + +#include "sieve-common.h" + +#include "sieve-ext-variables.h" + +#include "sieve-ext-enotify.h" + +/* + * Extension + */ + +extern const struct sieve_extension_def enotify_extension; +extern const struct sieve_extension_capabilities notify_capabilities; + +struct ext_enotify_context { + const struct sieve_extension *var_ext; + ARRAY(struct sieve_enotify_method) notify_methods; +}; + + +/* + * Commands + */ + +extern const struct sieve_command_def notify_command; + +/* Codes for optional arguments */ + +enum cmd_notify_optional { + CMD_NOTIFY_OPT_END, + CMD_NOTIFY_OPT_FROM, + CMD_NOTIFY_OPT_OPTIONS, + CMD_NOTIFY_OPT_MESSAGE, + CMD_NOTIFY_OPT_IMPORTANCE +}; + +/* + * Tests + */ + +extern const struct sieve_command_def valid_notify_method_test; +extern const struct sieve_command_def notify_method_capability_test; + +/* + * Operations + */ + +extern const struct sieve_operation_def notify_operation; +extern const struct sieve_operation_def valid_notify_method_operation; +extern const struct sieve_operation_def notify_method_capability_operation; + +enum ext_variables_opcode { + EXT_ENOTIFY_OPERATION_NOTIFY, + EXT_ENOTIFY_OPERATION_VALID_NOTIFY_METHOD, + EXT_ENOTIFY_OPERATION_NOTIFY_METHOD_CAPABILITY +}; + +/* + * Operands + */ + +extern const struct sieve_operand_def encodeurl_operand; + +/* + * Modifiers + */ + +extern const struct sieve_variables_modifier_def encodeurl_modifier; + +/* + * Notify methods + */ + +void ext_enotify_methods_init(struct sieve_instance *svinst, + struct ext_enotify_context *ectx); +void ext_enotify_methods_deinit(struct ext_enotify_context *ectx); + +const struct sieve_enotify_method * +ext_enotify_method_find(const struct sieve_extension *ntfy_ext, + const char *identifier); + +/* + * Validation + */ + +bool ext_enotify_compile_check_arguments( + struct sieve_validator *valdtr, struct sieve_command *cmd, + struct sieve_ast_argument *uri_arg, struct sieve_ast_argument *msg_arg, + struct sieve_ast_argument *from_arg, + struct sieve_ast_argument *options_arg); + +/* + * Runtime + */ + +bool ext_enotify_runtime_method_validate(const struct sieve_runtime_env *renv, + string_t *method_uri); + +const char * +ext_enotify_runtime_get_method_capability(const struct sieve_runtime_env *renv, + string_t *method_uri, + const char *capability); + +int ext_enotify_runtime_check_operands( + const struct sieve_runtime_env *renv, string_t *method_uri, + string_t *message, string_t *from, struct sieve_stringlist *options, + const struct sieve_enotify_method **method_r, void **method_context); + +/* + * Method printing + */ + +struct sieve_enotify_print_env { + const struct sieve_result_print_env *result_penv; +}; + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify-limits.h b/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify-limits.h new file mode 100644 index 0000000..aac48df --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify-limits.h @@ -0,0 +1,6 @@ +#ifndef EXT_ENOTIFY_LIMITS_H +#define EXT_ENOTIFY_LIMITS_H + +#define EXT_ENOTIFY_MAX_SCHEME_LEN 32 + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify.c b/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify.c new file mode 100644 index 0000000..df479b3 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify.c @@ -0,0 +1,103 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension enotify + * ------------------ + * + * Authors: Stephan Bosch + * Specification: RFC 5435 + * Implementation: full + * Status: testing + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "sieve-ext-variables.h" + +#include "ext-enotify-common.h" + +/* + * Operations + */ + +const struct sieve_operation_def *ext_enotify_operations[] = { + ¬ify_operation, + &valid_notify_method_operation, + ¬ify_method_capability_operation +}; + +/* + * Extension + */ + +static bool ext_enotify_load(const struct sieve_extension *ext, void **context); +static void ext_enotify_unload(const struct sieve_extension *ext); +static bool ext_enotify_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def enotify_extension = { + .name = "enotify", + .load = ext_enotify_load, + .unload = ext_enotify_unload, + .validator_load = ext_enotify_validator_load, + SIEVE_EXT_DEFINE_OPERATIONS(ext_enotify_operations), + SIEVE_EXT_DEFINE_OPERAND(encodeurl_operand) +}; + +static bool ext_enotify_load(const struct sieve_extension *ext, void **context) +{ + struct ext_enotify_context *ectx; + + if ( *context != NULL ) { + ext_enotify_unload(ext); + } + + ectx = i_new(struct ext_enotify_context, 1); + ectx->var_ext = sieve_ext_variables_get_extension(ext->svinst); + *context = (void *) ectx; + + ext_enotify_methods_init(ext->svinst, ectx); + + sieve_extension_capabilities_register(ext, ¬ify_capabilities); + + return TRUE; +} + +static void ext_enotify_unload(const struct sieve_extension *ext) +{ + struct ext_enotify_context *ectx = + (struct ext_enotify_context *) ext->context; + + ext_enotify_methods_deinit(ectx); + + i_free(ectx); +} + +static bool ext_enotify_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + struct ext_enotify_context *ectx = + (struct ext_enotify_context *) ext->context; + + /* Register new commands */ + sieve_validator_register_command(valdtr, ext, ¬ify_command); + sieve_validator_register_command(valdtr, ext, &valid_notify_method_test); + sieve_validator_register_command(valdtr, ext, ¬ify_method_capability_test); + + /* Register new set modifier for variables extension */ + sieve_variables_modifier_register + (ectx->var_ext, valdtr, ext, &encodeurl_modifier); + + return TRUE; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/mailto/Makefile.am b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/Makefile.am new file mode 100644 index 0000000..83f129c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/Makefile.am @@ -0,0 +1,16 @@ +noinst_LTLIBRARIES = libsieve_ext_enotify_mailto.la + +AM_CPPFLAGS = \ + -I$(srcdir)/.. \ + -I$(srcdir)/../../.. \ + -I$(srcdir)/../../../util \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_enotify_mailto_la_SOURCES = \ + uri-mailto.c \ + ntfy-mailto.c + +noinst_HEADERS = \ + uri-mailto.h + + diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/mailto/Makefile.in b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/Makefile.in new file mode 100644 index 0000000..49aa41a --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/Makefile.in @@ -0,0 +1,687 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/enotify/mailto +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_enotify_mailto_la_LIBADD = +am_libsieve_ext_enotify_mailto_la_OBJECTS = uri-mailto.lo \ + ntfy-mailto.lo +libsieve_ext_enotify_mailto_la_OBJECTS = \ + $(am_libsieve_ext_enotify_mailto_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ntfy-mailto.Plo \ + ./$(DEPDIR)/uri-mailto.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_enotify_mailto_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_enotify_mailto_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_enotify_mailto.la +AM_CPPFLAGS = \ + -I$(srcdir)/.. \ + -I$(srcdir)/../../.. \ + -I$(srcdir)/../../../util \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_enotify_mailto_la_SOURCES = \ + uri-mailto.c \ + ntfy-mailto.c + +noinst_HEADERS = \ + uri-mailto.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/enotify/mailto/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/enotify/mailto/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_enotify_mailto.la: $(libsieve_ext_enotify_mailto_la_OBJECTS) $(libsieve_ext_enotify_mailto_la_DEPENDENCIES) $(EXTRA_libsieve_ext_enotify_mailto_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_enotify_mailto_la_OBJECTS) $(libsieve_ext_enotify_mailto_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfy-mailto.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uri-mailto.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ntfy-mailto.Plo + -rm -f ./$(DEPDIR)/uri-mailto.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ntfy-mailto.Plo + -rm -f ./$(DEPDIR)/uri-mailto.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c new file mode 100644 index 0000000..4e104d1 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c @@ -0,0 +1,794 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Notify method mailto + * -------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5436 + * Implementation: full + * Status: testing + * + */ + +/* FIXME: URI syntax conforms to something somewhere in between RFC 2368 and + * draft-duerst-mailto-bis-05.txt. Should fully migrate to new specification + * when it matures. This requires modifications to the address parser (no + * whitespace allowed within the address itself) and UTF-8 support will be + * required in the URL. + */ + +#include "lib.h" +#include "array.h" +#include "str.h" +#include "ioloop.h" +#include "str-sanitize.h" +#include "ostream.h" +#include "message-date.h" +#include "mail-storage.h" + +#include "sieve-common.h" +#include "sieve-address.h" +#include "sieve-address-source.h" +#include "sieve-message.h" +#include "sieve-smtp.h" +#include "sieve-settings.h" + +#include "sieve-ext-enotify.h" + +#include "rfc2822.h" + +#include "uri-mailto.h" + +/* + * Configuration + */ + +#define NTFY_MAILTO_MAX_RECIPIENTS 8 +#define NTFY_MAILTO_MAX_HEADERS 16 +#define NTFY_MAILTO_MAX_SUBJECT 256 + +/* + * Mailto notification configuration + */ + +struct ntfy_mailto_config { + pool_t pool; + struct sieve_address_source envelope_from; +}; + +/* + * Mailto notification method + */ + +static bool ntfy_mailto_load + (const struct sieve_enotify_method *nmth, void **context); +static void ntfy_mailto_unload + (const struct sieve_enotify_method *nmth); + +static bool ntfy_mailto_compile_check_uri + (const struct sieve_enotify_env *nenv, const char *uri, const char *uri_body); +static bool ntfy_mailto_compile_check_from + (const struct sieve_enotify_env *nenv, string_t *from); + +static const char *ntfy_mailto_runtime_get_notify_capability + (const struct sieve_enotify_env *nenv, const char *uri, const char *uri_body, + const char *capability); +static bool ntfy_mailto_runtime_check_uri + (const struct sieve_enotify_env *nenv, const char *uri, const char *uri_body); +static bool ntfy_mailto_runtime_check_operands + (const struct sieve_enotify_env *nenv, const char *uri,const char *uri_body, + string_t *message, string_t *from, pool_t context_pool, + void **method_context); + +static int ntfy_mailto_action_check_duplicates + (const struct sieve_enotify_env *nenv, + const struct sieve_enotify_action *nact, + const struct sieve_enotify_action *nact_other); + +static void ntfy_mailto_action_print + (const struct sieve_enotify_print_env *penv, + const struct sieve_enotify_action *nact); + +static int ntfy_mailto_action_execute + (const struct sieve_enotify_exec_env *nenv, + const struct sieve_enotify_action *nact); + +const struct sieve_enotify_method_def mailto_notify = { + "mailto", + ntfy_mailto_load, + ntfy_mailto_unload, + ntfy_mailto_compile_check_uri, + NULL, + ntfy_mailto_compile_check_from, + NULL, + ntfy_mailto_runtime_check_uri, + ntfy_mailto_runtime_get_notify_capability, + ntfy_mailto_runtime_check_operands, + NULL, + ntfy_mailto_action_check_duplicates, + ntfy_mailto_action_print, + ntfy_mailto_action_execute +}; + +/* + * Reserved and unique headers + */ + +static const char *_reserved_headers[] = { + "auto-submitted", + "received", + "message-id", + "data", + "bcc", + "in-reply-to", + "references", + "resent-date", + "resent-from", + "resent-sender", + "resent-to", + "resent-cc", + "resent-bcc", + "resent-msg-id", + "from", + "sender", + NULL +}; + +static const char *_unique_headers[] = { + "reply-to", + NULL +}; + +/* + * Method context data + */ + +struct ntfy_mailto_context { + struct uri_mailto *uri; + const struct smtp_address *from_address; +}; + +/* + * Method registration + */ + +static bool ntfy_mailto_load +(const struct sieve_enotify_method *nmth, void **context) +{ + struct sieve_instance *svinst = nmth->svinst; + struct ntfy_mailto_config *config; + pool_t pool; + + if ( *context != NULL ) { + ntfy_mailto_unload(nmth); + } + + pool = pool_alloconly_create("ntfy_mailto_config", 256); + config = p_new(pool, struct ntfy_mailto_config, 1); + config->pool = pool; + + (void)sieve_address_source_parse_from_setting (svinst, + config->pool, "sieve_notify_mailto_envelope_from", + &config->envelope_from); + + *context = (void *) config; + + return TRUE; +} + +static void ntfy_mailto_unload +(const struct sieve_enotify_method *nmth) +{ + struct ntfy_mailto_config *config = + (struct ntfy_mailto_config *) nmth->context; + + pool_unref(&config->pool); +} + +/* + * URI parsing + */ + +struct ntfy_mailto_uri_env { + const struct sieve_enotify_env *nenv; + + struct event *event; + + struct uri_mailto_log uri_log; +}; + +static void ATTR_FORMAT(5, 0) +ntfy_mailto_uri_logv(void *context, enum log_type log_type, + const char *csrc_filename, unsigned int csrc_linenum, + const char *fmt, va_list args) +{ + struct ntfy_mailto_uri_env *nmuenv = context; + const struct sieve_enotify_env *nenv = nmuenv->nenv; + + sieve_event_logv(nenv->svinst, nenv->ehandler, nmuenv->event, + log_type, csrc_filename, csrc_linenum, + nenv->location, 0, fmt, args); +} + +static void +ntfy_mailto_uri_env_init(struct ntfy_mailto_uri_env *nmuenv, + const struct sieve_enotify_env *nenv) +{ + i_zero(nmuenv); + nmuenv->nenv = nenv; + nmuenv->event = event_create(nenv->event); + event_set_append_log_prefix(nmuenv->event, "mailto URI: "); + + nmuenv->uri_log.context = nmuenv; + nmuenv->uri_log.logv = ntfy_mailto_uri_logv; +} + +static void +ntfy_mailto_uri_env_deinit(struct ntfy_mailto_uri_env *nmuenv) +{ + event_unref(&nmuenv->event); +} + +/* + * Validation + */ + + +static bool ntfy_mailto_compile_check_uri +(const struct sieve_enotify_env *nenv, const char *uri ATTR_UNUSED, + const char *uri_body) +{ + struct ntfy_mailto_uri_env nmuenv; + bool result; + + ntfy_mailto_uri_env_init(&nmuenv, nenv); + result = uri_mailto_validate( + uri_body, _reserved_headers, _unique_headers, + NTFY_MAILTO_MAX_RECIPIENTS, NTFY_MAILTO_MAX_HEADERS, + &nmuenv.uri_log); + ntfy_mailto_uri_env_deinit(&nmuenv); + + return result; +} + +static bool ntfy_mailto_compile_check_from +(const struct sieve_enotify_env *nenv, string_t *from) +{ + const char *error; + bool result = FALSE; + + T_BEGIN { + result = sieve_address_validate_str(from, &error); + if ( !result ) { + sieve_enotify_error(nenv, + "specified :from address '%s' is invalid for " + "the mailto method: %s", + str_sanitize(str_c(from), 128), error); + } + } T_END; + + return result; +} + +/* + * Runtime + */ + +struct ntfy_mailto_runtime_env { + const struct sieve_enotify_env *nenv; + + struct event *event; +}; + +static const char *ntfy_mailto_runtime_get_notify_capability +(const struct sieve_enotify_env *nenv ATTR_UNUSED, const char *uri ATTR_UNUSED, + const char *uri_body, const char *capability) +{ + if ( !uri_mailto_validate(uri_body, _reserved_headers, _unique_headers, + NTFY_MAILTO_MAX_RECIPIENTS, NTFY_MAILTO_MAX_HEADERS, NULL) ) { + return NULL; + } + + if ( strcasecmp(capability, "online") == 0 ) + return "maybe"; + + return NULL; +} + +static bool ntfy_mailto_runtime_check_uri +(const struct sieve_enotify_env *nenv ATTR_UNUSED, const char *uri ATTR_UNUSED, + const char *uri_body) +{ + return uri_mailto_validate + (uri_body, _reserved_headers, _unique_headers, + NTFY_MAILTO_MAX_RECIPIENTS, NTFY_MAILTO_MAX_HEADERS, NULL); +} + +static bool ntfy_mailto_runtime_check_operands +(const struct sieve_enotify_env *nenv, const char *uri ATTR_UNUSED, + const char *uri_body, string_t *message ATTR_UNUSED, string_t *from, + pool_t context_pool, void **method_context) +{ + struct ntfy_mailto_context *mtctx; + struct uri_mailto *parsed_uri; + const struct smtp_address *address; + struct ntfy_mailto_uri_env nmuenv; + const char *error; + + /* Need to create context before validation to have arrays present */ + mtctx = p_new(context_pool, struct ntfy_mailto_context, 1); + + /* Validate :from */ + if ( from != NULL ) { + T_BEGIN { + address = sieve_address_parse_str(from, &error); + if ( address == NULL ) { + sieve_enotify_error(nenv, + "specified :from address '%s' is invalid for " + "the mailto method: %s", + str_sanitize(str_c(from), 128), error); + } else + mtctx->from_address = + smtp_address_clone(context_pool, address); + } T_END; + + if ( address == NULL ) return FALSE; + } + + ntfy_mailto_uri_env_init(&nmuenv, nenv); + parsed_uri = uri_mailto_parse(uri_body, context_pool, + _reserved_headers, _unique_headers, + NTFY_MAILTO_MAX_RECIPIENTS, + NTFY_MAILTO_MAX_HEADERS, + &nmuenv.uri_log); + ntfy_mailto_uri_env_deinit(&nmuenv); + + if (parsed_uri == NULL) + return FALSE; + + mtctx->uri = parsed_uri; + *method_context = (void *) mtctx; + return TRUE; +} + +/* + * Action duplicates + */ + +static int ntfy_mailto_action_check_duplicates +(const struct sieve_enotify_env *nenv ATTR_UNUSED, + const struct sieve_enotify_action *nact, + const struct sieve_enotify_action *nact_other) +{ + struct ntfy_mailto_context *mtctx = + (struct ntfy_mailto_context *) nact->method_context; + struct ntfy_mailto_context *mtctx_other = + (struct ntfy_mailto_context *) nact_other->method_context; + const struct uri_mailto_recipient *new_rcpts, *old_rcpts; + unsigned int new_count, old_count, i, j; + unsigned int del_start = 0, del_len = 0; + + new_rcpts = array_get(&mtctx->uri->recipients, &new_count); + old_rcpts = array_get(&mtctx_other->uri->recipients, &old_count); + + for ( i = 0; i < new_count; i++ ) { + for ( j = 0; j < old_count; j++ ) { + if ( smtp_address_equals + (new_rcpts[i].address, old_rcpts[j].address) ) + break; + } + + if ( j == old_count ) { + /* Not duplicate */ + if ( del_len > 0 ) { + /* Perform pending deletion */ + array_delete(&mtctx->uri->recipients, del_start, del_len); + + /* Make sure the loop integrity is maintained */ + i -= del_len; + new_rcpts = array_get(&mtctx->uri->recipients, &new_count); + } + del_len = 0; + } else { + /* Mark deletion */ + if ( del_len == 0 ) + del_start = i; + del_len++; + } + } + + /* Perform pending deletion */ + if ( del_len > 0 ) { + array_delete(&mtctx->uri->recipients, del_start, del_len); + } + + return ( array_count(&mtctx->uri->recipients) > 0 ? 0 : 1 ); +} + +/* + * Action printing + */ + +static void ntfy_mailto_action_print +(const struct sieve_enotify_print_env *penv, + const struct sieve_enotify_action *nact) +{ + unsigned int count, i; + const struct uri_mailto_recipient *recipients; + const struct uri_mailto_header_field *headers; + struct ntfy_mailto_context *mtctx = + (struct ntfy_mailto_context *) nact->method_context; + + /* Print main method parameters */ + + sieve_enotify_method_printf + (penv, " => importance : %llu\n", + (unsigned long long)nact->importance); + + if ( nact->message != NULL ) + sieve_enotify_method_printf + (penv, " => subject : %s\n", nact->message); + else if ( mtctx->uri->subject != NULL ) + sieve_enotify_method_printf + (penv, " => subject : %s\n", mtctx->uri->subject); + + if ( nact->from != NULL ) + sieve_enotify_method_printf + (penv, " => from : %s\n", nact->from); + + /* Print mailto: recipients */ + + sieve_enotify_method_printf(penv, " => recipients :\n" ); + + recipients = array_get(&mtctx->uri->recipients, &count); + if ( count == 0 ) { + sieve_enotify_method_printf(penv, " NONE, action has no effect\n"); + } else { + for ( i = 0; i < count; i++ ) { + if ( recipients[i].carbon_copy ) + sieve_enotify_method_printf + (penv, " + Cc: %s\n", recipients[i].full); + else + sieve_enotify_method_printf + (penv, " + To: %s\n", recipients[i].full); + } + } + + /* Print accepted headers for notification message */ + + headers = array_get(&mtctx->uri->headers, &count); + if ( count > 0 ) { + sieve_enotify_method_printf(penv, " => headers :\n" ); + for ( i = 0; i < count; i++ ) { + sieve_enotify_method_printf(penv, " + %s: %s\n", + headers[i].name, headers[i].body); + } + } + + /* Print body for notification message */ + + if ( mtctx->uri->body != NULL ) + sieve_enotify_method_printf + (penv, " => body : \n--\n%s\n--\n", mtctx->uri->body); + + /* Finish output with an empty line */ + + sieve_enotify_method_printf(penv, "\n"); +} + +/* + * Action execution + */ + +static bool _contains_8bit(const char *msg) +{ + const unsigned char *s = (const unsigned char *)msg; + + for (; *s != '\0'; s++) { + if ((*s & 0x80) != 0) + return TRUE; + } + + return FALSE; +} + +static int ntfy_mailto_send +(const struct sieve_enotify_exec_env *nenv, + const struct sieve_enotify_action *nact, + const struct smtp_address *owner_email) +{ + struct sieve_instance *svinst = nenv->svinst; + const struct sieve_message_data *msgdata = nenv->msgdata; + const struct sieve_script_env *senv = nenv->scriptenv; + struct ntfy_mailto_context *mtctx = + (struct ntfy_mailto_context *) nact->method_context; + struct ntfy_mailto_config *mth_config = + (struct ntfy_mailto_config *)nenv->method->context; + struct sieve_address_source env_from = + mth_config->envelope_from; + const char *from = NULL; + const struct smtp_address *from_smtp = NULL; + const char *subject = mtctx->uri->subject; + const char *body = mtctx->uri->body; + string_t *to, *cc, *all; + const struct uri_mailto_recipient *recipients; + const struct uri_mailto_header_field *headers; + struct sieve_smtp_context *sctx; + struct ostream *output; + string_t *msg; + unsigned int count, i, hcount, h; + const char *outmsgid, *error; + int ret; + + /* Get recipients */ + recipients = array_get(&mtctx->uri->recipients, &count); + if ( count == 0 ) { + sieve_enotify_warning(nenv, + "notify mailto uri specifies no recipients; action has no effect"); + return 0; + } + + /* Just to be sure */ + if ( !sieve_smtp_available(senv) ) { + sieve_enotify_global_warning(nenv, + "notify mailto method has no means to send mail"); + return 0; + } + + /* Determine which sender to use + + From RFC 5436, Section 2.3: + + The ":from" tag overrides the default sender of the notification + message. "Sender", here, refers to the value used in the [RFC5322] + "From" header. Implementations MAY also use this value in the + [RFC5321] "MAIL FROM" command (the "envelope sender"), or they may + prefer to establish a mailbox that receives bounces from notification + messages. + */ + if ( (nenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0 ) { + from_smtp = sieve_message_get_sender(nenv->msgctx); + if ( from_smtp == NULL ) { + /* "<>" */ + i_zero(&env_from); + env_from.type = SIEVE_ADDRESS_SOURCE_EXPLICIT; + } + } + from = nact->from; + if ( (ret=sieve_address_source_get_address(&env_from, svinst, + senv, nenv->msgctx, nenv->flags, &from_smtp)) < 0 ) { + from_smtp = NULL; + } else if ( ret == 0 ) { + if ( mtctx->from_address != NULL ) + from_smtp = mtctx->from_address; + else if ( svinst->user_email != NULL ) + from_smtp = svinst->user_email; + else { + from_smtp = sieve_get_postmaster_smtp(senv); + if (from == NULL) + from = sieve_get_postmaster_address(senv); + } + } + + /* Determine message from address */ + if ( from == NULL ) { + if ( from_smtp == NULL ) + from = sieve_get_postmaster_address(senv); + else { + from = t_strdup_printf("<%s>", + smtp_address_encode(from_smtp)); + } + } + + /* Determine subject */ + if ( nact->message != NULL ) { + /* FIXME: handle UTF-8 */ + subject = str_sanitize(nact->message, NTFY_MAILTO_MAX_SUBJECT); + } else if ( subject == NULL ) { + const char *const *hsubject; + + /* Fetch subject from original message */ + if ( mail_get_headers_utf8 + (msgdata->mail, "subject", &hsubject) > 0 ) + subject = str_sanitize(t_strdup_printf("Notification: %s", hsubject[0]), + NTFY_MAILTO_MAX_SUBJECT); + else + subject = "Notification: (no subject)"; + } + + /* Compose To and Cc headers */ + to = NULL; + cc = NULL; + all = t_str_new(256); + for ( i = 0; i < count; i++ ) { + if ( recipients[i].carbon_copy ) { + if ( cc == NULL ) { + cc = t_str_new(256); + str_append(cc, recipients[i].full); + } else { + str_append(cc, ", "); + str_append(cc, recipients[i].full); + } + } else { + if ( to == NULL ) { + to = t_str_new(256); + str_append(to, recipients[i].full); + } else { + str_append(to, ", "); + str_append(to, recipients[i].full); + } + } + if ( i < 3) { + if ( i > 0 ) + str_append(all, ", "); + str_append(all, + smtp_address_encode_path(recipients[i].address)); + } else if (i == 3) { + str_printfa(all, ", ... (%u total)", count); + } + } + + msg = t_str_new(512); + outmsgid = sieve_message_get_new_id(svinst); + + rfc2822_header_write(msg, "X-Sieve", SIEVE_IMPLEMENTATION); + rfc2822_header_write(msg, "Message-ID", outmsgid); + rfc2822_header_write(msg, "Date", message_date_create(ioloop_time)); + rfc2822_header_utf8_printf(msg, "Subject", "%s", subject); + + rfc2822_header_write_address(msg, "From", from); + + if ( to != NULL ) + rfc2822_header_write_address(msg, "To", str_c(to)); + if ( cc != NULL ) + rfc2822_header_write_address(msg, "Cc", str_c(cc)); + + rfc2822_header_printf(msg, "Auto-Submitted", + "auto-notified; owner-email=\"%s\"", + smtp_address_encode(owner_email)); + rfc2822_header_write(msg, "Precedence", "bulk"); + + /* Set importance */ + switch ( nact->importance ) { + case 1: + rfc2822_header_write(msg, "X-Priority", "1 (Highest)"); + rfc2822_header_write(msg, "Importance", "High"); + break; + case 3: + rfc2822_header_write(msg, "X-Priority", "5 (Lowest)"); + rfc2822_header_write(msg, "Importance", "Low"); + break; + case 2: + default: + rfc2822_header_write(msg, "X-Priority", "3 (Normal)"); + rfc2822_header_write(msg, "Importance", "Normal"); + break; + } + + /* Add custom headers */ + + headers = array_get(&mtctx->uri->headers, &hcount); + for ( h = 0; h < hcount; h++ ) { + const char *name = rfc2822_header_field_name_sanitize(headers[h].name); + + rfc2822_header_write(msg, name, headers[h].body); + } + + /* Generate message body */ + + rfc2822_header_write(msg, "MIME-Version", "1.0"); + if ( body != NULL ) { + if (_contains_8bit(body)) { + rfc2822_header_write + (msg, "Content-Type", "text/plain; charset=utf-8"); + rfc2822_header_write(msg, "Content-Transfer-Encoding", "8bit"); + } else { + rfc2822_header_write + (msg, "Content-Type", "text/plain; charset=us-ascii"); + rfc2822_header_write(msg, "Content-Transfer-Encoding", "7bit"); + } + str_printfa(msg, "\r\n%s\r\n", body); + + } else { + rfc2822_header_write + (msg, "Content-Type", "text/plain; charset=US-ASCII"); + rfc2822_header_write(msg, "Content-Transfer-Encoding", "7bit"); + + str_append(msg, "\r\nNotification of new message.\r\n"); + } + + sctx = sieve_smtp_start(senv, from_smtp); + + /* Send message to all recipients */ + for ( i = 0; i < count; i++ ) + sieve_smtp_add_rcpt(sctx, recipients[i].address); + + output = sieve_smtp_send(sctx); + o_stream_nsend(output, str_data(msg), str_len(msg)); + + if ( (ret=sieve_smtp_finish(sctx, &error)) <= 0 ) { + if (ret < 0) { + sieve_enotify_global_error(nenv, + "failed to send mail notification to %s: %s (temporary failure)", + str_c(all), str_sanitize(error, 512)); + } else { + sieve_enotify_global_log_error(nenv, + "failed to send mail notification to %s: %s (permanent failure)", + str_c(all), str_sanitize(error, 512)); + } + } else { + struct event_passthrough *e = + sieve_enotify_create_finish_event(nenv)-> + add_str("notify_target", str_c(all)); + + sieve_enotify_event_log(nenv, e->event(), + "sent mail notification to %s", + str_c(all)); + } + + return 0; +} + +static int ntfy_mailto_action_execute +(const struct sieve_enotify_exec_env *nenv, + const struct sieve_enotify_action *nact) +{ + struct sieve_instance *svinst = nenv->svinst; + const struct sieve_script_env *senv = nenv->scriptenv; + struct mail *mail = nenv->msgdata->mail; + const struct smtp_address *owner_email; + const char *const *hdsp; + int ret; + + owner_email = svinst->user_email; + if ( owner_email == NULL && + (nenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0 ) + owner_email = sieve_message_get_final_recipient(nenv->msgctx); + if ( owner_email == NULL ) { + owner_email = sieve_get_postmaster_smtp(senv); + } + i_assert( owner_email != NULL ); + + /* Is the message an automatic reply ? */ + if ( (ret=mail_get_headers(mail, "auto-submitted", &hdsp)) < 0 ) { + sieve_enotify_critical(nenv, + "mailto notification: " + "failed to read `auto-submitted' header field", + "mailto notification: " + "failed to read `auto-submitted' header field: %s", + mailbox_get_last_internal_error(mail->box, NULL)); + return -1; + } + + /* Theoretically multiple headers could exist, so lets make sure */ + if ( ret > 0 ) { + while ( *hdsp != NULL ) { + if ( strcasecmp(*hdsp, "no") != 0 ) { + const struct smtp_address *sender = NULL; + const char *from; + + if ( (nenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0 ) + sender = sieve_message_get_sender(nenv->msgctx); + from = (sender == NULL ? "" : t_strdup_printf + (" from <%s>", smtp_address_encode(sender))); + + sieve_enotify_global_info(nenv, + "not sending notification " + "for auto-submitted message%s", from); + return 0; + } + hdsp++; + } + } + + T_BEGIN { + ret = ntfy_mailto_send(nenv, nact, owner_email); + } T_END; + + return ret; +} + + + + diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/mailto/uri-mailto.c b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/uri-mailto.c new file mode 100644 index 0000000..c5a0953 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/uri-mailto.c @@ -0,0 +1,683 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* FIXME: URI syntax conforms to something somewhere in between RFC 2368 and + draft-duerst-mailto-bis-05.txt. Should fully migrate to new + specification when it matures. This requires modifications to the + address parser (no whitespace allowed within the address itself) and + UTF-8 support will be required in the URL. + */ + +#include "lib.h" +#include "array.h" +#include "str.h" +#include "str-sanitize.h" + +#include "rfc2822.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-address.h" +#include "sieve-message.h" + +#include "uri-mailto.h" + +/* Parser object */ + +struct uri_mailto_parser { + pool_t pool; + const struct uri_mailto_log *log; + + struct uri_mailto *uri; + + const char **reserved_headers; + const char **unique_headers; + + int max_recipients; + int max_headers; +}; + +/* Error handling */ + +#define uri_mailto_error(PARSER, ...) \ + uri_mailto_log((PARSER), LOG_TYPE_ERROR, \ + __FILE__, __LINE__, __VA_ARGS__) +#define uri_mailto_warning(PARSER, ...) \ + uri_mailto_log((PARSER), LOG_TYPE_WARNING, \ + __FILE__, __LINE__, __VA_ARGS__) + +static inline void ATTR_FORMAT(5, 6) +uri_mailto_log(struct uri_mailto_parser *parser, enum log_type log_type, + const char *csrc_filename, unsigned int csrc_linenum, + const char *fmt, ...) +{ + va_list args; + + if (parser->log == NULL || parser->log->logv == NULL) + return; + + va_start(args, fmt); + parser->log->logv(parser->log->context, log_type, + csrc_filename, csrc_linenum, fmt, args); + va_end(args); +} + + +/* + * Error handling + */ + +/* + * Reserved and unique headers + */ + +static inline bool +uri_mailto_header_is_reserved(struct uri_mailto_parser *parser, + const char *field_name) +{ + const char **hdr = parser->reserved_headers; + + if (hdr == NULL) + return FALSE; + + /* Check whether it is reserved */ + while (*hdr != NULL) { + if (strcasecmp(field_name, *hdr) == 0) + return TRUE; + hdr++; + } + return FALSE; +} + +static inline bool +uri_mailto_header_is_unique(struct uri_mailto_parser *parser, + const char *field_name) +{ + const char **hdr = parser->unique_headers; + + if (hdr == NULL) + return FALSE; + + /* Check whether it is supposed to be unique */ + while (*hdr != NULL) { + if (strcasecmp(field_name, *hdr) == 0) + return TRUE; + hdr++; + } + return FALSE; +} + +/* + * Low-level URI parsing. + * + * FIXME: much of this implementation will be common to other URI schemes. This + * should be merged into a common implementation. + */ + +static const char _qchar_lookup[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10 + 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 20 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 30 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, // 50 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, // 70 + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 90 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F0 +}; + +static inline bool _is_qchar(char c) +{ + return ((_qchar_lookup[(unsigned char)c] & 0x01) != 0); +} + +static inline int _decode_hex_digit(unsigned char digit) +{ + switch (digit) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return (int) digit - '0'; + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + return (int) digit - 'a' + 0x0a; + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + return (int) digit - 'A' + 0x0A; + } + return -1; +} + +static bool _parse_hex_value(const char **in, char *out) +{ + int value, digit; + + if ((digit = _decode_hex_digit((unsigned char)**in)) < 0) + return FALSE; + + value = digit << 4; + (*in)++; + + if ((digit = _decode_hex_digit((unsigned char)**in)) < 0) + return FALSE; + + value |= digit; + (*in)++; + + if (value == 0) + return FALSE; + + *out = (char)value; + return TRUE; +} + +/* + * URI recipient parsing + */ + +static bool +uri_mailto_add_valid_recipient(struct uri_mailto_parser *parser, + string_t *recipient, bool cc) +{ + struct uri_mailto *uri = parser->uri; + struct uri_mailto_recipient *new_recipient; + struct uri_mailto_recipient *rcpts; + unsigned int count, i; + const char *error; + const struct smtp_address *address; + + /* Verify recipient */ + if ((address = sieve_address_parse_str(recipient, &error)) == NULL) { + uri_mailto_error(parser, "invalid recipient '%s': %s", + str_sanitize(str_c(recipient), 80), error); + return FALSE; + } + + /* Add recipient to the uri */ + if (uri != NULL) { + /* Get current recipients */ + rcpts = array_get_modifiable(&uri->recipients, &count); + + /* Enforce limits */ + if (parser->max_recipients > 0 && + (int)count >= parser->max_recipients) { + if ((int)count == parser->max_recipients) { + uri_mailto_warning( + parser, + "more than the maximum %u recipients specified; " + "rest is discarded", + parser->max_recipients); + } + return TRUE; + } + + /* Check for duplicate first */ + for (i = 0; i < count; i++) { + if (smtp_address_equals(rcpts[i].address, address)) { + /* Upgrade existing Cc: recipient to a To: + recipient if possible */ + rcpts[i].carbon_copy = + (rcpts[i].carbon_copy && cc); + + uri_mailto_warning( + parser, + "ignored duplicate recipient '%s'", + str_sanitize(str_c(recipient), 80)); + return TRUE; + } + } + + /* Add */ + new_recipient = array_append_space(&uri->recipients); + new_recipient->carbon_copy = cc; + new_recipient->full = p_strdup(parser->pool, str_c(recipient)); + new_recipient->address = + smtp_address_clone(parser->pool, address); + } + + return TRUE; +} + +static bool +uri_mailto_parse_recipients(struct uri_mailto_parser *parser, + const char **uri_p) +{ + string_t *to = t_str_new(128); + const char *p = *uri_p; + + if (*p == '\0' || *p == '?') + return TRUE; + + while (*p != '\0' && *p != '?') { + if (*p == '%') { + /* % encoded character */ + char ch; + + p++; + + /* Parse 2-digit hex value */ + if (!_parse_hex_value(&p, &ch)) { + uri_mailto_error(parser, "invalid %% encoding"); + return FALSE; + } + + /* Check for delimiter */ + if (ch == ',') { + /* Verify and add recipient */ + if (!uri_mailto_add_valid_recipient( + parser, to, FALSE)) + return FALSE; + + /* Reset for next recipient */ + str_truncate(to, 0); + } else { + /* Content character */ + str_append_c(to, ch); + } + } else { + if (*p == ':' || *p == ';' || *p == ',' || + !_is_qchar(*p)) { + uri_mailto_error( + parser, + "invalid character '%c' in 'to' part", *p); + return FALSE; + } + + /* Content character */ + str_append_c(to, *p); + p++; + } + } + + i_assert(*p == '\0' || *p == '?'); + + /* Verify and add recipient */ + if (!uri_mailto_add_valid_recipient(parser, to, FALSE)) + return FALSE; + + *uri_p = p; + return TRUE; +} + +static bool +uri_mailto_parse_header_recipients(struct uri_mailto_parser *parser, + string_t *rcpt_header, bool cc) +{ + string_t *to = t_str_new(128); + const char *p = (const char *)str_data(rcpt_header); + const char *pend = p + str_len(rcpt_header); + + while (p < pend) { + if (*p == ',') { + /* Verify and add recipient */ + if (!uri_mailto_add_valid_recipient(parser, to, cc)) + return FALSE; + + /* Reset for next recipient */ + str_truncate(to, 0); + } else { + /* Content character */ + str_append_c(to, *p); + } + p++; + } + + /* Verify and add recipient */ + if (!uri_mailto_add_valid_recipient(parser, to, cc)) + return FALSE; + + return TRUE; +} + +/* URI header parsing */ + +static bool +uri_mailto_header_is_duplicate(struct uri_mailto_parser *parser, + const char *field_name) +{ + struct uri_mailto *uri = parser->uri; + + if (uri == NULL) + return FALSE; + + if (uri_mailto_header_is_unique(parser, field_name)) { + const struct uri_mailto_header_field *hdrs; + unsigned int count, i; + + hdrs = array_get(&uri->headers, &count); + for (i = 0; i < count; i++) { + if (strcasecmp(hdrs[i].name, field_name) == 0) + return TRUE; + } + } + return FALSE; +} + +static bool +uri_mailto_parse_headers(struct uri_mailto_parser *parser, const char **uri_p) +{ + struct uri_mailto *uri = parser->uri; + unsigned int header_count = 0; + string_t *field = t_str_new(128); + const char *p = *uri_p; + + while (*p != '\0') { + enum { + _HNAME_IGNORED, + _HNAME_GENERIC, + _HNAME_TO, + _HNAME_CC, + _HNAME_SUBJECT, + _HNAME_BODY, + } hname_type = _HNAME_GENERIC; + struct uri_mailto_header_field *hdrf = NULL; + const char *field_name; + + /* Parse field name */ + while (*p != '\0' && *p != '=') { + char ch = *p; + p++; + + if (ch == '%') { + /* Encoded, parse 2-digit hex value */ + if (!_parse_hex_value(&p, &ch)) { + uri_mailto_error(parser, + "invalid %% encoding"); + return FALSE; + } + } else if (ch != '=' && !_is_qchar(ch)) { + uri_mailto_error( + parser, + "invalid character '%c' in header field name part", + ch); + return FALSE; + } + + str_append_c(field, ch); + } + if (*p != '\0') + p++; + + /* Verify field name */ + if (!rfc2822_header_field_name_verify(str_c(field), + str_len(field))) { + uri_mailto_error(parser, "invalid header field name"); + return FALSE; + } + + if (parser->max_headers > -1 && + (int)header_count >= parser->max_headers) { + /* Refuse to accept more headers than allowed by policy + */ + if ((int)header_count == parser->max_headers) { + uri_mailto_warning( + parser, + "more than the maximum %u headers specified; " + "rest is discarded", + parser->max_headers); + } + + hname_type = _HNAME_IGNORED; + } else { + /* Add new header field to array and assign its name */ + + field_name = str_c(field); + if (strcasecmp(field_name, "to") == 0) + hname_type = _HNAME_TO; + else if (strcasecmp(field_name, "cc") == 0) + hname_type = _HNAME_CC; + else if (strcasecmp(field_name, "subject") == 0) + hname_type = _HNAME_SUBJECT; + else if (strcasecmp(field_name, "body") == 0) + hname_type = _HNAME_BODY; + else if (!uri_mailto_header_is_reserved(parser, field_name)) { + if (uri != NULL) { + if (!uri_mailto_header_is_duplicate(parser, field_name)) { + hdrf = array_append_space(&uri->headers); + hdrf->name = p_strdup(parser->pool, field_name); + } else { + uri_mailto_warning( + parser, + "ignored duplicate for unique header field '%s'", + str_sanitize(field_name, 32)); + hname_type = _HNAME_IGNORED; + } + } else { + hname_type = _HNAME_IGNORED; + } + } else { + uri_mailto_warning( + parser, + "ignored reserved header field '%s'", + str_sanitize(field_name, 32)); + hname_type = _HNAME_IGNORED; + } + } + + header_count++; + + /* Reset for field body */ + str_truncate(field, 0); + + /* Parse field body */ + while (*p != '\0' && *p != '&') { + char ch = *p; + p++; + + if (ch == '%') { + /* Encoded, parse 2-digit hex value */ + if (!_parse_hex_value(&p, &ch)) { + uri_mailto_error(parser, + "invalid %% encoding"); + return FALSE; + } + } else if (ch != '=' && !_is_qchar(ch)) { + uri_mailto_error( + parser, + "invalid character '%c' in header field value part", + ch); + return FALSE; + } + str_append_c(field, ch); + } + if (*p != '\0') + p++; + + /* Verify field body */ + if (hname_type == _HNAME_BODY) { + // FIXME: verify body ... + } else { + if (!rfc2822_header_field_body_verify( + str_c(field), str_len(field), FALSE, FALSE)) { + uri_mailto_error(parser, + "invalid header field body"); + return FALSE; + } + } + + /* Assign field body */ + + switch (hname_type) { + case _HNAME_IGNORED: + break; + case _HNAME_TO: + /* Gracefully allow duplicate To fields */ + if (!uri_mailto_parse_header_recipients( + parser, field, FALSE)) + return FALSE; + break; + case _HNAME_CC: + /* Gracefully allow duplicate Cc fields */ + if (!uri_mailto_parse_header_recipients( + parser, field, TRUE)) + return FALSE; + break; + case _HNAME_SUBJECT: + /* Ignore duplicate subject field */ + if (uri != NULL) { + if (uri->subject == NULL) { + uri->subject = + p_strdup(parser->pool, str_c(field)); + } else { + uri_mailto_warning( + parser, + "ignored duplicate subject field"); + } + } + break; + case _HNAME_BODY: + /* Ignore duplicate body field */ + if (uri != NULL) { + if (uri->body == NULL) { + uri->body = p_strdup( + parser->pool, str_c(field)); + } else { + uri_mailto_warning( + parser, "ignored duplicate body field"); + } + } + break; + case _HNAME_GENERIC: + if (uri != NULL && hdrf != NULL) + hdrf->body = p_strdup(parser->pool, str_c(field)); + break; + } + + /* Reset for next name */ + str_truncate(field, 0); + } + + /* Skip '&' */ + if (*p != '\0') + p++; + + *uri_p = p; + return TRUE; +} + +static bool +uri_mailto_parse_uri(struct uri_mailto_parser *parser, const char *uri_body) +{ + const char *p = uri_body; + + /* + * mailtoURI = "mailto:" [ to ] [ hfields ] + * to = [ addr-spec *("%2C" addr-spec ) ] + * hfields = "?" hfield *( "&" hfield ) + * hfield = hfname "=" hfvalue + * hfname = *qchar + * hfvalue = *qchar + * addr-spec = local-part "@" domain + * local-part = dot-atom / quoted-string + * qchar = unreserved / pct-encoded / some-delims + * some-delims = "!" / "$" / "'" / "(" / ")" / "*" + * / "+" / "," / ";" / ":" / "@" + * + * to ~= *tqchar + * tqchar ~= <qchar> without ";" and ":" + * + * Scheme 'mailto:' already parsed, starting parse after colon + */ + + /* First extract to-part by searching for '?' and decoding % items + */ + + if (!uri_mailto_parse_recipients(parser, &p)) + return FALSE; + + if (*p == '\0') + return TRUE; + i_assert(*p == '?'); + p++; + + /* Extract hfield items */ + + while (*p != '\0') { + /* Extract hfield item by searching for '&' and decoding '%' + items */ + if (!uri_mailto_parse_headers(parser, &p)) + return FALSE; + } + return TRUE; +} + +/* + * Validation + */ + +bool uri_mailto_validate(const char *uri_body, + const char **reserved_headers, + const char **unique_headers, int max_recipients, + int max_headers, const struct uri_mailto_log *log) +{ + struct uri_mailto_parser parser; + + i_zero(&parser); + parser.log = log; + parser.max_recipients = max_recipients; + parser.max_headers = max_headers; + parser.reserved_headers = reserved_headers; + parser.unique_headers = unique_headers; + + /* If no errors are reported, we don't need to record any data */ + if (log != NULL) { + parser.pool = pool_datastack_create(); + + parser.uri = p_new(parser.pool, struct uri_mailto, 1); + p_array_init(&parser.uri->recipients, parser.pool, max_recipients); + p_array_init(&parser.uri->headers, parser.pool, max_headers); + } + + if (!uri_mailto_parse_uri(&parser, uri_body)) + return FALSE; + + if (log != NULL) { + if (array_count(&parser.uri->recipients) == 0) { + uri_mailto_warning( + &parser, + "notification URI specifies no recipients"); + } + } + return TRUE; +} + +/* + * Parsing + */ + +struct uri_mailto * +uri_mailto_parse(const char *uri_body, pool_t pool, + const char **reserved_headers, const char **unique_headers, + int max_recipients, int max_headers, + const struct uri_mailto_log *log) +{ + struct uri_mailto_parser parser; + + parser.pool = pool; + parser.log = log; + parser.max_recipients = max_recipients; + parser.max_headers = max_headers; + parser.reserved_headers = reserved_headers; + parser.unique_headers = unique_headers; + + parser.uri = p_new(pool, struct uri_mailto, 1); + p_array_init(&parser.uri->recipients, pool, max_recipients); + p_array_init(&parser.uri->headers, pool, max_headers); + + if (!uri_mailto_parse_uri(&parser, uri_body)) + return NULL; + + if (log != NULL) { + if (array_count(&parser.uri->recipients) == 0) { + uri_mailto_warning( + &parser, + "notification URI specifies no recipients"); + } + } + return parser.uri; +} diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/mailto/uri-mailto.h b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/uri-mailto.h new file mode 100644 index 0000000..8e9e057 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/uri-mailto.h @@ -0,0 +1,49 @@ +#ifndef URI_MAILTO_H +#define URI_MAILTO_H + +/* + * Types + */ + +struct uri_mailto_header_field { + const char *name; + const char *body; +}; + +struct uri_mailto_recipient { + const char *full; + const struct smtp_address *address; + bool carbon_copy; +}; + +ARRAY_DEFINE_TYPE(recipients, struct uri_mailto_recipient); +ARRAY_DEFINE_TYPE(headers, struct uri_mailto_header_field); + +struct uri_mailto_log { + void *context; + + void (*logv)(void *context, enum log_type log_type, + const char *csrc_filename, unsigned int csrc_linenum, + const char *fmt, va_list args) ATTR_FORMAT(5, 0); +}; + +struct uri_mailto { + ARRAY_TYPE(recipients) recipients; + ARRAY_TYPE(headers) headers; + const char *subject; + const char *body; +}; + +bool uri_mailto_validate + (const char *uri_body, const char **reserved_headers, + const char **unique_headers, int max_recipients, int max_headers, + const struct uri_mailto_log *log); + +struct uri_mailto *uri_mailto_parse +(const char *uri_body, pool_t pool, const char **reserved_headers, + const char **unique_headers, int max_recipients, int max_headers, + const struct uri_mailto_log *log); + +#endif + + diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h b/pigeonhole/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h new file mode 100644 index 0000000..fd8b574 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h @@ -0,0 +1,197 @@ +#ifndef SIEVE_EXT_ENOTIFY_H +#define SIEVE_EXT_ENOTIFY_H + +#include "lib.h" +#include "compat.h" +#include <stdarg.h> + +#include "sieve-common.h" +#include "sieve-error.h" + +/* + * Forward declarations + */ + +struct sieve_enotify_method; +struct sieve_enotify_env; +struct sieve_enotify_action; +struct sieve_enotify_print_env; +struct sieve_enotify_exec_env; + +/* + * Notify method definition + */ + +struct sieve_enotify_method_def { + const char *identifier; + + /* Registration */ + bool (*load) + (const struct sieve_enotify_method *nmth, void **context); + void (*unload) + (const struct sieve_enotify_method *nmth); + + /* Validation */ + bool (*compile_check_uri) + (const struct sieve_enotify_env *nenv, const char *uri, + const char *uri_body); + bool (*compile_check_message) + (const struct sieve_enotify_env *nenv, string_t *message); + bool (*compile_check_from) + (const struct sieve_enotify_env *nenv, string_t *from); + bool (*compile_check_option) + (const struct sieve_enotify_env *nenv, const char *option, + const char *value); + + /* Runtime */ + bool (*runtime_check_uri) + (const struct sieve_enotify_env *nenv, const char *uri, + const char *uri_body); + const char *(*runtime_get_method_capability) + (const struct sieve_enotify_env *nenv, const char *uri, + const char *uri_body, const char *capability); + bool (*runtime_check_operands) + (const struct sieve_enotify_env *nenv, const char *uri, + const char *uri_body, string_t *message, string_t *from, + pool_t context_pool, void **method_context); + bool (*runtime_set_option) + (const struct sieve_enotify_env *nenv, void *method_context, + const char *option, const char *value); + + /* Action duplicates */ + int (*action_check_duplicates) + (const struct sieve_enotify_env *nenv, + const struct sieve_enotify_action *nact, + const struct sieve_enotify_action *nact_other); + + /* Action print */ + void (*action_print) + (const struct sieve_enotify_print_env *penv, + const struct sieve_enotify_action *nact); + + /* Action execution + (returns 0 if all is ok and -1 for temporary error) + */ + int (*action_execute) + (const struct sieve_enotify_exec_env *nenv, + const struct sieve_enotify_action *nact); +}; + +/* + * Notify method instance + */ + +struct sieve_enotify_method { + const struct sieve_enotify_method_def *def; + int id; + + struct sieve_instance *svinst; + void *context; +}; + +const struct sieve_enotify_method *sieve_enotify_method_register + (struct sieve_instance *svinst, + const struct sieve_enotify_method_def *nmth_def); +void sieve_enotify_method_unregister + (const struct sieve_enotify_method *nmth); + +/* + * Notify method environment + */ + +struct sieve_enotify_env { + struct sieve_instance *svinst; + + const struct sieve_enotify_method *method; + + struct sieve_error_handler *ehandler; + const char *location; + struct event *event; +}; + +/* + * Notify method printing + */ + +void sieve_enotify_method_printf + (const struct sieve_enotify_print_env *penv, const char *fmt, ...) + ATTR_FORMAT(2, 3); + +/* + * Notify execution environment + */ + +struct sieve_enotify_exec_env { + struct sieve_instance *svinst; + enum sieve_execute_flags flags; + + const struct sieve_enotify_method *method; + + const struct sieve_script_env *scriptenv; + const struct sieve_message_data *msgdata; + struct sieve_message_context *msgctx; + + struct sieve_error_handler *ehandler; + const char *location; + struct event *event; +}; + +struct event_passthrough * +sieve_enotify_create_finish_event(const struct sieve_enotify_exec_env *nenv); + +/* + * Notify action + */ + +struct sieve_enotify_action { + const struct sieve_enotify_method *method; + void *method_context; + + sieve_number_t importance; + const char *message; + const char *from; +}; + +/* + * Error handling + */ + +#define sieve_enotify_error(ENV, ...) \ + sieve_event_log((ENV)->svinst, (ENV)->ehandler, (ENV)->event, \ + LOG_TYPE_ERROR, (ENV)->location, 0, __VA_ARGS__ ) +#define sieve_enotify_warning(ENV, ...) \ + sieve_event_log((ENV)->svinst, (ENV)->ehandler, (ENV)->event, \ + LOG_TYPE_WARNING, \ + (ENV)->location, 0, __VA_ARGS__ ) +#define sieve_enotify_info(ENV, ...) \ + sieve_event_log((ENV)->svinst, (ENV)->ehandler, (ENV)->event, \ + LOG_TYPE_INFO, \ + (ENV)->location, 0, __VA_ARGS__ ) +#define sieve_enotify_critical(ENV, ...) \ + sieve_critical((ENV)->svinst, (ENV)->ehandler, NULL, __VA_ARGS__ ) + +#define sieve_enotify_global_error(ENV, ...) \ + sieve_event_log((ENV)->svinst, (ENV)->ehandler, (ENV)->event, \ + LOG_TYPE_ERROR, (ENV)->location, \ + SIEVE_ERROR_FLAG_GLOBAL, __VA_ARGS__ ) +#define sieve_enotify_global_warning(ENV, ...) \ + sieve_event_log((ENV)->svinst, (ENV)->ehandler, (ENV)->event, \ + LOG_TYPE_WARNING, (ENV)->location, \ + SIEVE_ERROR_FLAG_GLOBAL, __VA_ARGS__ ) +#define sieve_enotify_global_info(ENV, ...) \ + sieve_event_log((ENV)->svinst, (ENV)->ehandler, (ENV)->event, \ + LOG_TYPE_INFO, (ENV)->location, \ + SIEVE_ERROR_FLAG_GLOBAL, __VA_ARGS__ ) + +#define sieve_enotify_event_log(ENV, EVENT, ...) \ + sieve_event_log((ENV)->svinst, (ENV)->ehandler, (EVENT), \ + LOG_TYPE_INFO, (ENV)->location, \ + SIEVE_ERROR_FLAG_GLOBAL, __VA_ARGS__ ) + +#define sieve_enotify_global_log_error(ENV, ...) \ + sieve_event_log((ENV)->svinst, (ENV)->ehandler, (ENV)->event, \ + LOG_TYPE_ERROR, (ENV)->location, \ + (SIEVE_ERROR_FLAG_GLOBAL | \ + SIEVE_ERROR_FLAG_GLOBAL_MAX_INFO), __VA_ARGS__ ) +#endif + diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c b/pigeonhole/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c new file mode 100644 index 0000000..8a6c071 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c @@ -0,0 +1,233 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-enotify-common.h" + +/* + * String test + * + * Syntax: + * notify_method_capability [COMPARATOR] [MATCH-TYPE] + * <notification-uri: string> + * <notification-capability: string> + * <key-list: string-list> + */ + +static bool tst_notifymc_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool tst_notifymc_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_notifymc_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def notify_method_capability_test = { + .identifier = "notify_method_capability", + .type = SCT_TEST, + .positional_args = 3, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_notifymc_registered, + .validate = tst_notifymc_validate, + .generate = tst_notifymc_generate +}; + +/* + * String operation + */ + +static bool tst_notifymc_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_notifymc_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def notify_method_capability_operation = { + .mnemonic = "NOTIFY_METHOD_CAPABILITY", + .ext_def = &enotify_extension, + .code = EXT_ENOTIFY_OPERATION_NOTIFY_METHOD_CAPABILITY, + .dump = tst_notifymc_operation_dump, + .execute = tst_notifymc_operation_execute +}; + +/* + * Optional arguments + */ + +enum tst_notifymc_optional { + OPT_END, + OPT_COMPARATOR, + OPT_MATCH_TYPE +}; + +/* + * Test registration + */ + +static bool tst_notifymc_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag(valdtr, cmd_reg, OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, OPT_MATCH_TYPE); + + return TRUE; +} + +/* + * Test validation + */ + +static bool tst_notifymc_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + const struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "notification-uri", 1, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + arg = sieve_ast_argument_next(arg); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "notification-capability", 2, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + arg = sieve_ast_argument_next(arg); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "key-list", 3, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate + (valdtr, tst, arg, &mcht_default, &cmp_default); +} + +/* + * Test generation + */ + +static bool tst_notifymc_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + sieve_operation_emit + (cgenv->sblock, cmd->ext, ¬ify_method_capability_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool tst_notifymc_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "NOTIFY_METHOD_CAPABILITY"); + sieve_code_descend(denv); + + /* Handle any optional arguments */ + if ( sieve_match_opr_optional_dump(denv, address, NULL) != 0 ) + return FALSE; + + return + sieve_opr_string_dump(denv, address, "notify uri") && + sieve_opr_string_dump(denv, address, "notify capability") && + sieve_opr_stringlist_dump(denv, address, "key list"); +} + +/* + * Code execution + */ + +static int tst_notifymc_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + string_t *notify_uri, *notify_capability; + struct sieve_stringlist *value_list, *key_list; + const char *cap_value; + int match, ret; + + /* + * Read operands + */ + + /* Handle match-type and comparator operands */ + if ( sieve_match_opr_optional_read + (renv, address, NULL, &ret, &cmp, &mcht) < 0 ) + return ret; + + /* Read notify uri */ + if ( (ret=sieve_opr_string_read(renv, address, "notify-uri", ¬ify_uri)) + <= 0 ) + return ret; + + /* Read notify capability */ + if ( (ret=sieve_opr_string_read + (renv, address, "notify-capability", ¬ify_capability)) <= 0 ) + return ret; + + /* Read key-list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0) + return ret; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "notify_method_capability test"); + + cap_value = ext_enotify_runtime_get_method_capability + (renv, notify_uri, str_c(notify_capability)); + + if ( cap_value != NULL ) { + value_list = sieve_single_stringlist_create_cstr(renv, cap_value, TRUE); + + /* Perform match */ + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) + < 0 ) + return ret; + } else { + match = 0; + } + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/tst-valid-notify-method.c b/pigeonhole/src/lib-sieve/plugins/enotify/tst-valid-notify-method.c new file mode 100644 index 0000000..becc41c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/tst-valid-notify-method.c @@ -0,0 +1,144 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-enotify-common.h" + +/* + * Valid_notify_method test + * + * Syntax: + * valid_notify_method <notification-uris: string-list> + */ + +static bool tst_vnotifym_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_vnotifym_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def valid_notify_method_test = { + .identifier = "valid_notify_method", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = tst_vnotifym_validate, + .generate = tst_vnotifym_generate +}; + +/* + * Valid_notify_method operation + */ + +static bool tst_vnotifym_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_vnotifym_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def valid_notify_method_operation = { + .mnemonic = "VALID_NOTIFY_METHOD", + .ext_def = &enotify_extension, + .code = EXT_ENOTIFY_OPERATION_VALID_NOTIFY_METHOD, + .dump = tst_vnotifym_operation_dump, + .execute = tst_vnotifym_operation_execute +}; + +/* + * Test validation + */ + +static bool tst_vnotifym_validate + (struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "notification-uris", 1, SAAT_STRING_LIST) ) { + return FALSE; + } + + return sieve_validator_argument_activate(valdtr, tst, arg, FALSE); +} + +/* + * Test generation + */ + +static bool tst_vnotifym_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &valid_notify_method_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool tst_vnotifym_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "VALID_NOTIFY_METHOD"); + sieve_code_descend(denv); + + return + sieve_opr_stringlist_dump(denv, address, "notify-uris"); +} + +/* + * Code execution + */ + +static int tst_vnotifym_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_stringlist *notify_uris; + string_t *uri_item; + bool all_valid = TRUE; + int ret; + + /* + * Read operands + */ + + /* Read notify uris */ + if ( (ret=sieve_opr_stringlist_read + (renv, address, "notify-uris", ¬ify_uris)) <= 0 ) + return ret; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "valid_notify_method test"); + + uri_item = NULL; + while ( (ret=sieve_stringlist_next_item(notify_uris, &uri_item)) > 0 ) { + if ( !ext_enotify_runtime_method_validate(renv, uri_item) ) { + all_valid = FALSE; + break; + } + } + + if ( ret < 0 ) { + sieve_runtime_trace_error(renv, "invalid method uri item"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + sieve_interpreter_set_test_result(renv->interp, all_valid); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/vmodf-encodeurl.c b/pigeonhole/src/lib-sieve/plugins/enotify/vmodf-encodeurl.c new file mode 100644 index 0000000..801f882 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/vmodf-encodeurl.c @@ -0,0 +1,119 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "unichar.h" +#include "str.h" + +#include "sieve-common.h" +#include "sieve-code.h" + +#include "sieve-ext-variables.h" + +#include "ext-enotify-common.h" + +/* + * Encodeurl modifier + */ + +static bool +mod_encodeurl_modify(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result); + +const struct sieve_variables_modifier_def encodeurl_modifier = { + SIEVE_OBJECT("encodeurl", &encodeurl_operand, 0), + 15, + mod_encodeurl_modify +}; + +/* + * Modifier operand + */ + +static const struct sieve_extension_objects ext_enotify_modifiers = + SIEVE_VARIABLES_DEFINE_MODIFIER(encodeurl_modifier); + +const struct sieve_operand_def encodeurl_operand = { + .name = "modifier", + .ext_def = &enotify_extension, + .class = &sieve_variables_modifier_operand_class, + .interface = &ext_enotify_modifiers +}; + +/* + * Modifier implementation + */ + +static const char _uri_reserved_lookup[256] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 00 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 10 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, // 20 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, // 30 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, // 50 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, // 70 + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // F0 +}; + +static bool +mod_encodeurl_modify(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result) +{ + size_t max_var_size = + sieve_variables_get_max_variable_size(modf->var_ext); + const unsigned char *p, *poff, *pend; + size_t new_size; + + if ( str_len(in) == 0 ) { + *result = in; + return TRUE; + } + + /* allocate new string */ + new_size = str_len(in) + 32; + if (new_size > max_var_size) + new_size = max_var_size; + *result = t_str_new(new_size + 1); + + /* escape string */ + p = str_data(in); + pend = p + str_len(in); + poff = p; + while (p < pend) { + unsigned int i, n = uni_utf8_char_bytes(*p); + + if (n > 1 || (_uri_reserved_lookup[*p] & 0x01) != 0) { + str_append_data(*result, poff, p - poff); + poff = p; + + if (str_len(*result) + 3 * n > max_var_size) + break; + + str_printfa(*result, "%%%02X", *p); + for (i = 1; i < n && p < pend; i++) { + p++; + poff++; + str_printfa(*result, "%%%02X", *p); + } + + poff++; + } else if ((str_len(*result) + (p - poff) + 1) > max_var_size) { + break; + } + p++; + } + + str_append_data(*result, poff, p - poff); + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/environment/Makefile.am b/pigeonhole/src/lib-sieve/plugins/environment/Makefile.am new file mode 100644 index 0000000..916362e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/environment/Makefile.am @@ -0,0 +1,24 @@ +noinst_LTLIBRARIES = libsieve_ext_environment.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-environment.c + +libsieve_ext_environment_la_SOURCES = \ + $(tests) \ + ext-environment-common.c \ + ext-environment.c + +public_headers = \ + sieve-ext-environment.h + +headers = \ + ext-environment-common.h + +pkginc_libdir=$(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) + diff --git a/pigeonhole/src/lib-sieve/plugins/environment/Makefile.in b/pigeonhole/src/lib-sieve/plugins/environment/Makefile.in new file mode 100644 index 0000000..68424f4 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/environment/Makefile.in @@ -0,0 +1,753 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/environment +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(pkginc_lib_HEADERS) $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_environment_la_LIBADD = +am__objects_1 = tst-environment.lo +am_libsieve_ext_environment_la_OBJECTS = $(am__objects_1) \ + ext-environment-common.lo ext-environment.lo +libsieve_ext_environment_la_OBJECTS = \ + $(am_libsieve_ext_environment_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ext-environment-common.Plo \ + ./$(DEPDIR)/ext-environment.Plo \ + ./$(DEPDIR)/tst-environment.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_environment_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_environment_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkginc_libdir)" +HEADERS = $(noinst_HEADERS) $(pkginc_lib_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_environment.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-environment.c + +libsieve_ext_environment_la_SOURCES = \ + $(tests) \ + ext-environment-common.c \ + ext-environment.c + +public_headers = \ + sieve-ext-environment.h + +headers = \ + ext-environment-common.h + +pkginc_libdir = $(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/environment/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/environment/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_environment.la: $(libsieve_ext_environment_la_OBJECTS) $(libsieve_ext_environment_la_DEPENDENCIES) $(EXTRA_libsieve_ext_environment_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_environment_la_OBJECTS) $(libsieve_ext_environment_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-environment-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-environment.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-environment.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkginc_libHEADERS: $(pkginc_lib_HEADERS) + @$(NORMAL_INSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkginc_libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkginc_libdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkginc_libdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkginc_libdir)" || exit $$?; \ + done + +uninstall-pkginc_libHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkginc_libdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(pkginc_libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-environment-common.Plo + -rm -f ./$(DEPDIR)/ext-environment.Plo + -rm -f ./$(DEPDIR)/tst-environment.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pkginc_libHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ext-environment-common.Plo + -rm -f ./$(DEPDIR)/ext-environment.Plo + -rm -f ./$(DEPDIR)/tst-environment.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkginc_libHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-pkginc_libHEADERS install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pkginc_libHEADERS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/environment/ext-environment-common.c b/pigeonhole/src/lib-sieve/plugins/environment/ext-environment-common.c new file mode 100644 index 0000000..28d4251 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/environment/ext-environment-common.c @@ -0,0 +1,339 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "hash.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-interpreter.h" + +#include "ext-environment-common.h" + +struct ext_environment_interpreter_context; + +/* + * Core environment items + */ + +static const struct sieve_environment_item *core_env_items[] = { + &domain_env_item, + &host_env_item, + &location_env_item, + &phase_env_item, + &name_env_item, + &version_env_item +}; + +static unsigned int core_env_items_count = N_ELEMENTS(core_env_items); + +static void +sieve_environment_item_insert(struct ext_environment_interpreter_context *ctx, + const struct sieve_environment_item *item); + +/* + * Validator context + */ + +struct ext_environment_interpreter_context { + HASH_TABLE(const char *, + const struct sieve_environment_item *) name_items; + ARRAY(const struct sieve_environment_item *) prefix_items; + + bool active:1; +}; + +static void +ext_environment_interpreter_extension_free(const struct sieve_extension *ext, + struct sieve_interpreter *interp, + void *context); + +struct sieve_interpreter_extension environment_interpreter_extension = { + .ext_def = &environment_extension, + .free = ext_environment_interpreter_extension_free, +}; + +static struct ext_environment_interpreter_context * +ext_environment_interpreter_context_create( + const struct sieve_extension *this_ext, + struct sieve_interpreter *interp) +{ + pool_t pool = sieve_interpreter_pool(interp); + struct ext_environment_interpreter_context *ctx; + + ctx = p_new(pool, struct ext_environment_interpreter_context, 1); + + hash_table_create(&ctx->name_items, default_pool, 0, str_hash, strcmp); + i_array_init(&ctx->prefix_items, 16); + + sieve_interpreter_extension_register(interp, this_ext, + &environment_interpreter_extension, + (void *)ctx); + return ctx; +} + +static void +ext_environment_interpreter_extension_free( + const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_interpreter *interp ATTR_UNUSED, void *context) +{ + struct ext_environment_interpreter_context *ctx = + (struct ext_environment_interpreter_context *)context; + + hash_table_destroy(&ctx->name_items); + array_free(&ctx->prefix_items); +} + +static struct ext_environment_interpreter_context * +ext_environment_interpreter_context_get(const struct sieve_extension *this_ext, + struct sieve_interpreter *interp) +{ + struct ext_environment_interpreter_context *ctx = + (struct ext_environment_interpreter_context *) + sieve_interpreter_extension_get_context(interp, this_ext); + + if (ctx == NULL) { + ctx = ext_environment_interpreter_context_create( + this_ext, interp); + } + return ctx; +} + +void ext_environment_interpreter_init(const struct sieve_extension *this_ext, + struct sieve_interpreter *interp) +{ + struct ext_environment_interpreter_context *ctx; + unsigned int i; + + /* Create our context */ + ctx = ext_environment_interpreter_context_get(this_ext, interp); + + for (i = 0; i < core_env_items_count; i++) + sieve_environment_item_insert(ctx, core_env_items[i]); + + ctx->active = TRUE; +} + +bool sieve_ext_environment_is_active(const struct sieve_extension *env_ext, + struct sieve_interpreter *interp) +{ + struct ext_environment_interpreter_context *ctx = + ext_environment_interpreter_context_get(env_ext, interp); + + return (ctx != NULL && ctx->active); +} + +/* + * Registration + */ + +static void +sieve_environment_item_insert(struct ext_environment_interpreter_context *ctx, + const struct sieve_environment_item *item) +{ + if (!item->prefix) + hash_table_insert(ctx->name_items, item->name, item); + else + array_append(&ctx->prefix_items, &item, 1); +} + +void sieve_environment_item_register(const struct sieve_extension *env_ext, + struct sieve_interpreter *interp, + const struct sieve_environment_item *item) +{ + struct ext_environment_interpreter_context *ctx; + + i_assert(sieve_extension_is(env_ext, environment_extension)); + ctx = ext_environment_interpreter_context_get(env_ext, interp); + + sieve_environment_item_insert(ctx, item); +} + +/* + * Retrieval + */ + +static const struct sieve_environment_item * +ext_environment_item_lookup(struct ext_environment_interpreter_context *ctx, + const char **_name) +{ + const struct sieve_environment_item *item; + const char *name = *_name; + + item = hash_table_lookup(ctx->name_items, name); + if (item != NULL) + return item; + + array_foreach_elem(&ctx->prefix_items, item) { + size_t prefix_len; + + i_assert(item->prefix); + prefix_len = strlen(item->name); + + if (str_begins(name, item->name)) { + if (name[prefix_len] == '.') { + *_name = &name[prefix_len+1]; + return item; + } else if (name[prefix_len] == '\0') { + *_name = &name[prefix_len+1]; + return item; + } + } + } + return NULL; +} + +const char * +ext_environment_item_get_value(const struct sieve_extension *env_ext, + const struct sieve_runtime_env *renv, + const char *name) +{ + struct ext_environment_interpreter_context *ctx; + const struct sieve_environment_item *item; + + i_assert(sieve_extension_is(env_ext, environment_extension)); + ctx = ext_environment_interpreter_context_get(env_ext, renv->interp); + + item = ext_environment_item_lookup(ctx, &name); + if (item == NULL) + return NULL; + + if (item->value != NULL) + return item->value; + if (item->get_value != NULL) + return item->get_value(renv, name); + return NULL; +} + +/* + * Default environment items + */ + +/* "domain": + + The primary DNS domain associated with the Sieve execution context, usually + but not always a proper suffix of the host name. + */ + +static const char * +envit_domain_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + return eenv->svinst->domainname; +} + +const struct sieve_environment_item domain_env_item = { + .name = "domain", + .get_value = envit_domain_get_value, +}; + +/* "host": + + The fully-qualified domain name of the host where the Sieve script is + executing. + */ + +static const char * +envit_host_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + return eenv->svinst->hostname; +} + +const struct sieve_environment_item host_env_item = { + .name = "host", + .get_value = envit_host_get_value, +}; + +/* "location": + + Sieve evaluation can be performed at various different points as messages + are processed. This item provides additional information about the type of + service that is evaluating the script. Possible values are: + "MTA" - the Sieve script is being evaluated by a Message Transfer Agent + "MDA" - evaluation is being performed by a Mail Delivery Agent + "MUA" - evaluation is being performed by a Mail User Agent (right...) + "MS" - evaluation is being performed by a Message Store + */ + +static const char * +envit_location_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + switch (eenv->svinst->env_location ) { + case SIEVE_ENV_LOCATION_MDA: + return "MDA"; + case SIEVE_ENV_LOCATION_MTA: + return "MTA"; + case SIEVE_ENV_LOCATION_MS: + return "MS"; + default: + break; + } + return NULL; +} + +const struct sieve_environment_item location_env_item = { + .name = "location", + .get_value = envit_location_get_value +}; + +/* "phase": + + The point relative to final delivery where the Sieve script is being + evaluated. Possible values are "pre", "during", and "post", referring + respectively to processing before, during, and after final delivery has + taken place. + */ + +static const char * +envit_phase_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + switch (eenv->svinst->delivery_phase) { + case SIEVE_DELIVERY_PHASE_PRE: + return "pre"; + case SIEVE_DELIVERY_PHASE_DURING: + return "during"; + case SIEVE_DELIVERY_PHASE_POST: + return "post"; + default: + break; + } + return NULL; +} + +const struct sieve_environment_item phase_env_item = { + .name = "phase", + .get_value = envit_phase_get_value +}; + +/* "name": + + The product name associated with the Sieve interpreter. + */ + +const struct sieve_environment_item name_env_item = { + .name = "name", + .value = PIGEONHOLE_NAME" Sieve" +}; + +/* "version": + + The product version associated with the Sieve interpreter. The meaning of the + product version string is product-specific and should always be considered + in the context of the product name given by the "name" item. + */ + +const struct sieve_environment_item version_env_item = { + .name = "version", + .value = PIGEONHOLE_VERSION, +}; diff --git a/pigeonhole/src/lib-sieve/plugins/environment/ext-environment-common.h b/pigeonhole/src/lib-sieve/plugins/environment/ext-environment-common.h new file mode 100644 index 0000000..288b82e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/environment/ext-environment-common.h @@ -0,0 +1,53 @@ +#ifndef EXT_ENVIRONMENT_COMMON_H +#define EXT_ENVIRONMENT_COMMON_H + +#include "lib.h" + +#include "sieve-common.h" + +#include "sieve-ext-environment.h" + +/* + * Extension + */ + +extern const struct sieve_extension_def environment_extension; + +/* + * Commands + */ + +extern const struct sieve_command_def tst_environment; + +/* + * Operations + */ + +extern const struct sieve_operation_def tst_environment_operation; + +/* + * Environment items + */ + +extern const struct sieve_environment_item domain_env_item; +extern const struct sieve_environment_item host_env_item; +extern const struct sieve_environment_item location_env_item; +extern const struct sieve_environment_item phase_env_item; +extern const struct sieve_environment_item name_env_item; +extern const struct sieve_environment_item version_env_item; + +/* + * Initialization + */ + +bool ext_environment_init(const struct sieve_extension *ext, void **context); +void ext_environment_deinit(const struct sieve_extension *ext); + +/* + * Validator context + */ + +void ext_environment_interpreter_init(const struct sieve_extension *this_ext, + struct sieve_interpreter *interp); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/environment/ext-environment.c b/pigeonhole/src/lib-sieve/plugins/environment/ext-environment.c new file mode 100644 index 0000000..c2130a2 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/environment/ext-environment.c @@ -0,0 +1,59 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension variables + * ------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5183 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "str.h" +#include "unichar.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" + +#include "sieve-validator.h" + +#include "ext-environment-common.h" + +/* + * Extension + */ + +static bool ext_environment_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); +static bool ext_environment_interpreter_load +(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_extension_def environment_extension = { + .name = "environment", + .validator_load = ext_environment_validator_load, + .interpreter_load = ext_environment_interpreter_load, + SIEVE_EXT_DEFINE_OPERATION(tst_environment_operation) +}; + +static bool ext_environment_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + sieve_validator_register_command(valdtr, ext, &tst_environment); + return TRUE; +} + +static bool ext_environment_interpreter_load +(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + ext_environment_interpreter_init(ext, renv->interp); + return TRUE; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/environment/sieve-ext-environment.h b/pigeonhole/src/lib-sieve/plugins/environment/sieve-ext-environment.h new file mode 100644 index 0000000..8ae0d18 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/environment/sieve-ext-environment.h @@ -0,0 +1,54 @@ +#ifndef SIEVE_EXT_ENVIRONMENT_H +#define SIEVE_EXT_ENVIRONMENT_H + +#include "sieve-common.h" + +/* + * Environment extension + */ + +/* FIXME: this is not suitable for future plugin support */ + +extern const struct sieve_extension_def environment_extension; + +static inline const struct sieve_extension * +sieve_ext_environment_get_extension +(struct sieve_instance *svinst) +{ + return sieve_extension_register + (svinst, &environment_extension, FALSE); +} + +static inline const struct sieve_extension * +sieve_ext_environment_require_extension +(struct sieve_instance *svinst) +{ + return sieve_extension_require + (svinst, &environment_extension, TRUE); +} + +bool sieve_ext_environment_is_active + (const struct sieve_extension *env_ext, + struct sieve_interpreter *interp); + +/* + * Environment item + */ + +struct sieve_environment_item { + const char *name; + bool prefix; + + const char *value; + const char *(*get_value) + (const struct sieve_runtime_env *renv, const char *name); +}; + +void sieve_environment_item_register + (const struct sieve_extension *env_ext, struct sieve_interpreter *interp, + const struct sieve_environment_item *item); +const char *ext_environment_item_get_value + (const struct sieve_extension *env_ext, + const struct sieve_runtime_env *renv, const char *name); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/environment/tst-environment.c b/pigeonhole/src/lib-sieve/plugins/environment/tst-environment.c new file mode 100644 index 0000000..9eaa099 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/environment/tst-environment.c @@ -0,0 +1,215 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-environment-common.h" + +/* + * Environment test + * + * Syntax: + * environment [COMPARATOR] [MATCH-TYPE] + * <name: string> <key-list: string-list> + */ + +static bool tst_environment_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool tst_environment_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_environment_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + +const struct sieve_command_def tst_environment = { + .identifier = "environment", + .type = SCT_TEST, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_environment_registered, + .validate = tst_environment_validate, + .generate = tst_environment_generate +}; + +/* + * Environment operation + */ + +static bool tst_environment_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_environment_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def tst_environment_operation = { + .mnemonic = "ENVIRONMENT", + .ext_def = &environment_extension, + .dump = tst_environment_operation_dump, + .execute = tst_environment_operation_execute +}; + +/* + * Test registration + */ + +static bool tst_environment_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + + return TRUE; +} + +/* + * Test validation + */ + +static bool tst_environment_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + const struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "name", 1, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + arg = sieve_ast_argument_next(arg); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "key list", 2, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate + (valdtr, tst, arg, &mcht_default, &cmp_default); +} + +/* + * Test generation + */ + +static bool tst_environment_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &tst_environment_operation); + + /* Generate arguments */ + if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) + return FALSE; + + return TRUE; +} + +/* + * Code dump + */ + +static bool tst_environment_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "ENVIRONMENT"); + sieve_code_descend(denv); + + /* Optional operands */ + if ( sieve_match_opr_optional_dump(denv, address, NULL) != 0 ) + return FALSE; + + return + sieve_opr_string_dump(denv, address, "name") && + sieve_opr_stringlist_dump(denv, address, "key list"); +} + +/* + * Code execution + */ + +static int tst_environment_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + string_t *name; + struct sieve_stringlist *value_list, *key_list; + const char *env_item; + int match, ret; + + /* + * Read operands + */ + + /* Handle match-type and comparator operands */ + if ( sieve_match_opr_optional_read + (renv, address, NULL, &ret, &cmp, &mcht) < 0 ) + return ret; + + /* Read source */ + if ( (ret=sieve_opr_string_read(renv, address, "name", &name)) <= 0 ) + return ret; + + /* Read key-list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "environment test"); + + env_item = ext_environment_item_get_value + (this_ext, renv, str_c(name)); + + if ( env_item != NULL ) { + /* Construct value list */ + value_list = sieve_single_stringlist_create_cstr(renv, env_item, FALSE); + + /* Perform match */ + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) + < 0 ) + return ret; + } else { + match = 0; + + sieve_runtime_trace_descend(renv); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "environment item `%s' not found", + str_sanitize(str_c(name), 128)); + } + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/ihave/Makefile.am b/pigeonhole/src/lib-sieve/plugins/ihave/Makefile.am new file mode 100644 index 0000000..1eb0472 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/ihave/Makefile.am @@ -0,0 +1,22 @@ +noinst_LTLIBRARIES = libsieve_ext_ihave.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-ihave.c + +commands = \ + cmd-error.c + +libsieve_ext_ihave_la_SOURCES = \ + $(tests) \ + $(commands) \ + ext-ihave-binary.c \ + ext-ihave-common.c \ + ext-ihave.c + +noinst_HEADERS = \ + ext-ihave-binary.h \ + ext-ihave-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/ihave/Makefile.in b/pigeonhole/src/lib-sieve/plugins/ihave/Makefile.in new file mode 100644 index 0000000..c5b8952 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/ihave/Makefile.in @@ -0,0 +1,707 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/ihave +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_ihave_la_LIBADD = +am__objects_1 = tst-ihave.lo +am__objects_2 = cmd-error.lo +am_libsieve_ext_ihave_la_OBJECTS = $(am__objects_1) $(am__objects_2) \ + ext-ihave-binary.lo ext-ihave-common.lo ext-ihave.lo +libsieve_ext_ihave_la_OBJECTS = $(am_libsieve_ext_ihave_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/cmd-error.Plo \ + ./$(DEPDIR)/ext-ihave-binary.Plo \ + ./$(DEPDIR)/ext-ihave-common.Plo ./$(DEPDIR)/ext-ihave.Plo \ + ./$(DEPDIR)/tst-ihave.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_ihave_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_ihave_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_ihave.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-ihave.c + +commands = \ + cmd-error.c + +libsieve_ext_ihave_la_SOURCES = \ + $(tests) \ + $(commands) \ + ext-ihave-binary.c \ + ext-ihave-common.c \ + ext-ihave.c + +noinst_HEADERS = \ + ext-ihave-binary.h \ + ext-ihave-common.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/ihave/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/ihave/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_ihave.la: $(libsieve_ext_ihave_la_OBJECTS) $(libsieve_ext_ihave_la_DEPENDENCIES) $(EXTRA_libsieve_ext_ihave_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_ihave_la_OBJECTS) $(libsieve_ext_ihave_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-error.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-ihave-binary.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-ihave-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-ihave.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-ihave.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-error.Plo + -rm -f ./$(DEPDIR)/ext-ihave-binary.Plo + -rm -f ./$(DEPDIR)/ext-ihave-common.Plo + -rm -f ./$(DEPDIR)/ext-ihave.Plo + -rm -f ./$(DEPDIR)/tst-ihave.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/cmd-error.Plo + -rm -f ./$(DEPDIR)/ext-ihave-binary.Plo + -rm -f ./$(DEPDIR)/ext-ihave-common.Plo + -rm -f ./$(DEPDIR)/ext-ihave.Plo + -rm -f ./$(DEPDIR)/tst-ihave.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/ihave/cmd-error.c b/pigeonhole/src/lib-sieve/plugins/ihave/cmd-error.c new file mode 100644 index 0000000..6e971bd --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/ihave/cmd-error.c @@ -0,0 +1,131 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-code.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-ihave-common.h" + +/* + * Error command + * + * Syntax + * error <message: string> + */ + +static bool cmd_error_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool cmd_error_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def error_command = { + .identifier = "error", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_error_validate, + .generate = cmd_error_generate +}; + +/* + * Body operation + */ + +static bool cmd_error_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_error_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def cmd_error_operation = { + .mnemonic = "ERROR", + .ext_def = &ihave_extension, + .code = EXT_IHAVE_OPERATION_ERROR, + .dump = cmd_error_operation_dump, + .execute = cmd_error_operation_execute +}; + +/* + * Validation + */ + +static bool cmd_error_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "message", 1, SAAT_STRING) ) { + return FALSE; + } + + return sieve_validator_argument_activate(valdtr, tst, arg, FALSE); +} + +/* + * Code generation + */ + +static bool cmd_error_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + (void)sieve_operation_emit(cgenv->sblock, cmd->ext, &cmd_error_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool cmd_error_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "ERROR"); + sieve_code_descend(denv); + + return sieve_opr_string_dump(denv, address, "message"); +} + +/* + * Interpretation + */ + +static int cmd_error_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + string_t *message; + int ret; + + /* + * Read operands + */ + + /* Read message */ + + if ( (ret=sieve_opr_string_read(renv, address, "message", &message)) <= 0 ) + return ret; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "error \"%s\"", + str_sanitize(str_c(message), 80)); + + sieve_runtime_error(renv, NULL, "%s", str_c(message)); + + return SIEVE_EXEC_FAILURE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-binary.c b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-binary.c new file mode 100644 index 0000000..01b375e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-binary.c @@ -0,0 +1,249 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-error.h" +#include "sieve-script.h" +#include "sieve-binary.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-ihave-common.h" +#include "ext-ihave-binary.h" + +/* + * Forward declarations + */ + +static bool ext_ihave_binary_pre_save + (const struct sieve_extension *ext, struct sieve_binary *sbin, + void *context, enum sieve_error *error_r); +static bool ext_ihave_binary_open + (const struct sieve_extension *ext, struct sieve_binary *sbin, + void *context); +static bool ext_ihave_binary_up_to_date + (const struct sieve_extension *ext, struct sieve_binary *sbin, + void *context, enum sieve_compile_flags cpflags); + +/* + * Binary include extension + */ + +const struct sieve_binary_extension ihave_binary_ext = { + .extension = &ihave_extension, + .binary_pre_save = ext_ihave_binary_pre_save, + .binary_open = ext_ihave_binary_open, + .binary_up_to_date = ext_ihave_binary_up_to_date +}; + +/* + * Binary context management + */ + +struct ext_ihave_binary_context { + struct sieve_binary *binary; + struct sieve_binary_block *block; + + ARRAY(const char *) missing_extensions; +}; + +static struct ext_ihave_binary_context *ext_ihave_binary_create_context +(const struct sieve_extension *this_ext, struct sieve_binary *sbin) +{ + pool_t pool = sieve_binary_pool(sbin); + + struct ext_ihave_binary_context *ctx = + p_new(pool, struct ext_ihave_binary_context, 1); + + ctx->binary = sbin; + p_array_init(&ctx->missing_extensions, pool, 64); + + sieve_binary_extension_set(sbin, this_ext, &ihave_binary_ext, ctx); + return ctx; +} + +struct ext_ihave_binary_context *ext_ihave_binary_get_context +(const struct sieve_extension *this_ext, struct sieve_binary *sbin) +{ + struct ext_ihave_binary_context *ctx = (struct ext_ihave_binary_context *) + sieve_binary_extension_get_context(sbin, this_ext); + + if ( ctx == NULL ) + ctx = ext_ihave_binary_create_context(this_ext, sbin); + + return ctx; +} + +struct ext_ihave_binary_context *ext_ihave_binary_init +(const struct sieve_extension *this_ext, struct sieve_binary *sbin, + struct sieve_ast *ast) +{ + struct ext_ihave_ast_context *ast_ctx = + ext_ihave_get_ast_context(this_ext, ast); + struct ext_ihave_binary_context *binctx; + const char *const *exts; + unsigned int i, count; + + binctx = ext_ihave_binary_get_context(this_ext, sbin); + + exts = array_get(&ast_ctx->missing_extensions, &count); + + if ( count > 0 ) { + pool_t pool = sieve_binary_pool(sbin); + + if ( binctx->block == NULL ) + binctx->block = sieve_binary_extension_create_block(sbin, this_ext); + + for ( i = 0; i < count; i++ ) { + const char *ext_name = p_strdup(pool, exts[i]); + + array_append(&binctx->missing_extensions, &ext_name, 1); + } + } + + return binctx; +} + +/* + * Binary extension + */ + +static bool ext_ihave_binary_pre_save +(const struct sieve_extension *ext, struct sieve_binary *sbin, + void *context, enum sieve_error *error_r ATTR_UNUSED) +{ + struct ext_ihave_binary_context *binctx = + (struct ext_ihave_binary_context *) context; + const char *const *exts; + unsigned int count, i; + + exts = array_get(&binctx->missing_extensions, &count); + + if ( binctx->block != NULL ) + sieve_binary_block_clear(binctx->block); + + if ( count > 0 ) { + if ( binctx->block == NULL ) + binctx->block = sieve_binary_extension_create_block(sbin, ext); + + sieve_binary_emit_unsigned(binctx->block, count); + + for ( i = 0; i < count; i++ ) { + sieve_binary_emit_cstring(binctx->block, exts[i]); + } + } + + return TRUE; +} + +static bool ext_ihave_binary_open +(const struct sieve_extension *ext, struct sieve_binary *sbin, void *context) +{ + struct sieve_instance *svinst = ext->svinst; + struct ext_ihave_binary_context *binctx = + (struct ext_ihave_binary_context *) context; + struct sieve_binary_block *sblock; + unsigned int i, count, block_id; + sieve_size_t offset; + + sblock = sieve_binary_extension_get_block(sbin, ext); + + if ( sblock != NULL ) { + binctx->block = sblock; + block_id = sieve_binary_block_get_id(sblock); + + offset = 0; + + /* Read number of missing extensions to read subsequently */ + if ( !sieve_binary_read_unsigned(sblock, &offset, &count) ) { + e_error(svinst->event, "ihave: " + "failed to read missing extension count " + "from block %d of binary %s", + block_id, sieve_binary_path(sbin)); + return FALSE; + } + + /* Read dependencies */ + for ( i = 0; i < count; i++ ) { + string_t *ext_name; + const char *name; + + if ( !sieve_binary_read_string(sblock, &offset, &ext_name) ) { + /* Binary is corrupt, recompile */ + e_error(svinst->event, "ihave: " + "failed to read missing extension name " + "from block %d of binary %s", + block_id, sieve_binary_path(sbin)); + return FALSE; + } + + name = str_c(ext_name); + array_append(&binctx->missing_extensions, &name, 1); + } + } + + return TRUE; +} + +static bool ext_ihave_binary_up_to_date +(const struct sieve_extension *ext, struct sieve_binary *sbin ATTR_UNUSED, + void *context, enum sieve_compile_flags cpflags) +{ + struct ext_ihave_binary_context *binctx = + (struct ext_ihave_binary_context *) context; + const struct sieve_extension *mext; + const char *const *mexts; + unsigned int count, i; + + mexts = array_get(&binctx->missing_extensions, &count); + for ( i = 0; i < count; i++ ) { + if ( (mext=sieve_extension_get_by_name(ext->svinst, mexts[i])) != NULL && + ((cpflags & SIEVE_COMPILE_FLAG_NOGLOBAL) == 0 || !mext->global) ) + return FALSE; + } + + return TRUE; +} + +/* + * Main extension interface + */ + +bool ext_ihave_binary_load +(const struct sieve_extension *ext, struct sieve_binary *sbin) +{ + (void)ext_ihave_binary_get_context(ext, sbin); + + return TRUE; +} + +bool ext_ihave_binary_dump +(const struct sieve_extension *ext, struct sieve_dumptime_env *denv) +{ + struct sieve_binary *sbin = denv->sbin; + struct ext_ihave_binary_context *binctx = + ext_ihave_binary_get_context(ext, sbin); + const char *const *exts; + unsigned int count, i; + + exts = array_get(&binctx->missing_extensions, &count); + + if ( count > 0 ) { + sieve_binary_dump_sectionf(denv, + "Extensions missing at compile (block: %d)", + sieve_binary_block_get_id(binctx->block)); + + for ( i = 0; i < count; i++ ) { + sieve_binary_dumpf(denv, " - %s\n", exts[i]); + } + } + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-binary.h b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-binary.h new file mode 100644 index 0000000..418f078 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-binary.h @@ -0,0 +1,33 @@ +#ifndef EXT_IHAVE_BINARY_H +#define EXT_IHAVE_BINARY_H + +/* + * Binary context management + */ + +struct ext_ihave_binary_context; + +struct ext_ihave_binary_context *ext_ihave_binary_get_context + (const struct sieve_extension *this_ext, struct sieve_binary *sbin); +struct ext_ihave_binary_context *ext_ihave_binary_init + (const struct sieve_extension *this_ext, struct sieve_binary *sbin, + struct sieve_ast *ast); + +/* + * Registering missing extension + */ + +void ext_ihave_binary_add_missing_extension + (struct ext_ihave_binary_context *binctx, const char *ext_name); + +/* + * Main extension interface + */ + +bool ext_ihave_binary_load + (const struct sieve_extension *ext, struct sieve_binary *sbin); +bool ext_ihave_binary_dump + (const struct sieve_extension *ext, struct sieve_dumptime_env *denv); + +#endif + diff --git a/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-common.c b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-common.c new file mode 100644 index 0000000..1d31238 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-common.c @@ -0,0 +1,52 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-ast.h" + +#include "ext-ihave-common.h" + +/* + * AST context management + */ + +struct ext_ihave_ast_context *ext_ihave_get_ast_context +(const struct sieve_extension *this_ext, struct sieve_ast *ast) +{ + struct ext_ihave_ast_context *actx = (struct ext_ihave_ast_context *) + sieve_ast_extension_get_context(ast, this_ext); + pool_t pool; + + if ( actx != NULL ) + return actx; + + pool = sieve_ast_pool(ast); + actx = p_new(pool, struct ext_ihave_ast_context, 1); + p_array_init(&actx->missing_extensions, pool, 64); + + sieve_ast_extension_set_context(ast, this_ext, (void *) actx); + + return actx; +} + +void ext_ihave_ast_add_missing_extension +(const struct sieve_extension *this_ext, struct sieve_ast *ast, + const char *ext_name) +{ + struct ext_ihave_ast_context *actx = + ext_ihave_get_ast_context(this_ext, ast); + const char *const *exts; + unsigned int i, count; + + exts = array_get(&actx->missing_extensions, &count); + for ( i = 0; i < count; i++ ) { + if ( strcmp(exts[i], ext_name) == 0 ) + return; + } + + array_append(&actx->missing_extensions, &ext_name, 1); +} + diff --git a/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-common.h b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-common.h new file mode 100644 index 0000000..371d03d --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-common.h @@ -0,0 +1,52 @@ +#ifndef EXT_IHAVE_COMMON_H +#define EXT_IHAVE_COMMON_H + +#include "sieve-common.h" + +/* + * Extensions + */ + +extern const struct sieve_extension_def ihave_extension; + +/* + * Tests + */ + +extern const struct sieve_command_def ihave_test; + +/* + * Commands + */ + +extern const struct sieve_command_def error_command; + +/* + * Operations + */ + +enum ext_ihave_opcode { + EXT_IHAVE_OPERATION_IHAVE, + EXT_IHAVE_OPERATION_ERROR +}; + +extern const struct sieve_operation_def tst_ihave_operation; +extern const struct sieve_operation_def cmd_error_operation; + +/* + * AST context + */ + +struct ext_ihave_ast_context { + ARRAY(const char *) missing_extensions; +}; + +struct ext_ihave_ast_context *ext_ihave_get_ast_context + (const struct sieve_extension *this_ext, struct sieve_ast *ast); + +void ext_ihave_ast_add_missing_extension + (const struct sieve_extension *this_ext, struct sieve_ast *ast, + const char *ext_name); + + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave.c b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave.c new file mode 100644 index 0000000..40b70eb --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave.c @@ -0,0 +1,70 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension ihave + * --------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5463 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-validator.h" +#include "sieve-generator.h" + +#include "ext-ihave-common.h" +#include "ext-ihave-binary.h" + +/* + * Operations + */ + +const struct sieve_operation_def *ext_ihave_operations[] = { + &tst_ihave_operation, + &cmd_error_operation +}; + +/* + * Extension + */ + +static bool ext_ihave_validator_load + (const struct sieve_extension *ext, struct sieve_validator *validator); +static bool ext_ihave_generator_load + (const struct sieve_extension *ext, const struct sieve_codegen_env *cgenv); + +const struct sieve_extension_def ihave_extension = { + "ihave", + .version = 1, + .validator_load = ext_ihave_validator_load, + .generator_load = ext_ihave_generator_load, + .binary_load = ext_ihave_binary_load, + .binary_dump = ext_ihave_binary_dump, + SIEVE_EXT_DEFINE_OPERATIONS(ext_ihave_operations) +}; + +static bool ext_ihave_validator_load +(const struct sieve_extension *ext, struct sieve_validator *validator) +{ + sieve_validator_register_command(validator, ext, &ihave_test); + sieve_validator_register_command(validator, ext, &error_command); + + return TRUE; +} + +static bool ext_ihave_generator_load +(const struct sieve_extension *ext, const struct sieve_codegen_env *cgenv) +{ + (void)ext_ihave_binary_init(ext, cgenv->sbin, cgenv->ast); + + return TRUE; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/ihave/tst-ihave.c b/pigeonhole/src/lib-sieve/plugins/ihave/tst-ihave.c new file mode 100644 index 0000000..c6c8e8f --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/ihave/tst-ihave.c @@ -0,0 +1,294 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-extensions.h" +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-ihave-common.h" + +/* + * Ihave test + * + * Syntax: + * ihave <capabilities: string-list> + */ + +static bool +tst_ihave_validate(struct sieve_validator *valdtr, struct sieve_command *tst); +static bool +tst_ihave_validate_const(struct sieve_validator *valdtr, + struct sieve_command *tst, int *const_current, + int const_next); +static bool +tst_ihave_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *tst); + +const struct sieve_command_def ihave_test = { + .identifier = "ihave", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = tst_ihave_validate, + .validate_const = tst_ihave_validate_const, + .generate = tst_ihave_generate +}; + +/* + * Ihave operation + */ + +static bool +tst_ihave_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +tst_ihave_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def tst_ihave_operation = { + .mnemonic = "IHAVE", + .ext_def = &ihave_extension, + .code = EXT_IHAVE_OPERATION_IHAVE, + .dump = tst_ihave_operation_dump, + .execute = tst_ihave_operation_execute +}; + +/* + * Code validation + */ + +static bool +tst_ihave_validate(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct _capability { + const struct sieve_extension *ext; + struct sieve_ast_argument *arg; + }; + struct sieve_ast_argument *arg = tst->first_positional; + struct sieve_ast_argument *stritem; + enum sieve_compile_flags cpflags = + sieve_validator_compile_flags(valdtr); + bool no_global = ((cpflags & SIEVE_COMPILE_FLAG_NOGLOBAL) != 0); + ARRAY(struct _capability) capabilities; + struct _capability capability; + const struct _capability *caps; + unsigned int i, count; + bool all_known = TRUE; + + t_array_init(&capabilities, 64); + + tst->data = (void *)FALSE; + + /* Check stringlist argument */ + if (!sieve_validate_positional_argument(valdtr, tst, arg, + "capabilities", 1, + SAAT_STRING_LIST)) + return FALSE; + + switch (sieve_ast_argument_type(arg)) { + case SAAT_STRING: + /* Single string */ + capability.arg = arg; + capability.ext = sieve_extension_get_by_name( + tst->ext->svinst, sieve_ast_argument_strc(arg)); + + if (capability.ext == NULL || + (no_global && capability.ext->global)) { + all_known = FALSE; + + ext_ihave_ast_add_missing_extension( + tst->ext, tst->ast_node->ast, + sieve_ast_argument_strc(arg)); + } else { + array_append(&capabilities, &capability, 1); + } + + break; + + case SAAT_STRING_LIST: + /* String list */ + stritem = sieve_ast_strlist_first(arg); + + while (stritem != NULL) { + capability.arg = stritem; + capability.ext = sieve_extension_get_by_name( + tst->ext->svinst, + sieve_ast_argument_strc(stritem)); + + if (capability.ext == NULL || + (no_global && capability.ext->global)) { + all_known = FALSE; + + ext_ihave_ast_add_missing_extension( + tst->ext, tst->ast_node->ast, + sieve_ast_argument_strc(stritem)); + } else { + array_append(&capabilities, &capability, 1); + } + stritem = sieve_ast_strlist_next(stritem); + } + + break; + default: + i_unreached(); + } + + if (!all_known) + return TRUE; + + /* RFC 5463, Section 4, page 4: + + The "ihave" extension is designed to be used with other extensions + that add tests, actions, comparators, or arguments. Implementations + MUST NOT allow it to be used with extensions that change the + underlying Sieve grammar, or extensions like encoded-character + [RFC5228], or variables [RFC5229] that change how the content of + Sieve scripts are interpreted. The test MUST fail and the extension + MUST NOT be enabled if such usage is attempted. + + FIXME: current implementation of this restriction is hardcoded and + therefore highly inflexible + */ + caps = array_get(&capabilities, &count); + for (i = 0; i < count; i++) { + if (sieve_extension_name_is(caps[i].ext, "variables") || + sieve_extension_name_is(caps[i].ext, "encoded-character")) + return TRUE; + } + + /* Load all extensions */ + caps = array_get(&capabilities, &count); + for (i = 0; i < count; i++) { + if (!sieve_validator_extension_load(valdtr, tst, caps[i].arg, + caps[i].ext, FALSE)) + return FALSE; + } + + if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) + return FALSE; + + tst->data = (void *)TRUE; + return TRUE; +} + +static bool +tst_ihave_validate_const(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *tst, int *const_current, + int const_next ATTR_UNUSED) +{ + if ((bool)tst->data == TRUE) + *const_current = -1; + else + *const_current = 0; + return TRUE; +} + +/* + * Code generation + */ + +bool tst_ihave_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *tst) +{ + /* Emit opcode */ + sieve_operation_emit(cgenv->sblock, tst->ext, &tst_ihave_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool +tst_ihave_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_code_dumpf(denv, "IHAVE"); + sieve_code_descend(denv); + + return sieve_opr_stringlist_dump(denv, address, "capabilities"); +} + +/* + * Code execution + */ + +static int +tst_ihave_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct sieve_instance *svinst = eenv->svinst; + struct sieve_stringlist *capabilities; + string_t *cap_item; + bool matched; + int ret; + + /* + * Read operands + */ + + /* Read capabilities */ + if ((ret = sieve_opr_stringlist_read(renv, address, "capabilities", + &capabilities)) <= 0) + return ret; + + /* + * Perform test + */ + + /* Perform the test */ + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "ihave test"); + sieve_runtime_trace_descend(renv); + + cap_item = NULL; + matched = TRUE; + while (matched && + (ret = sieve_stringlist_next_item(capabilities, + &cap_item)) > 0) { + const struct sieve_extension *ext; + int sret; + + ext = sieve_extension_get_by_name(svinst, str_c(cap_item)); + if (ext == NULL) { + sieve_runtime_trace_error( + renv, "ihave: invalid extension name"); + return SIEVE_EXEC_BIN_CORRUPT; + } + sret = sieve_interpreter_extension_start(renv->interp, ext); + if (sret == SIEVE_EXEC_FAILURE) { + sieve_runtime_trace( + renv, SIEVE_TRLVL_TESTS, + "extension `%s' not available", + sieve_extension_name(ext)); + matched = FALSE; + } else if (sret == SIEVE_EXEC_OK) { + sieve_runtime_trace( + renv, SIEVE_TRLVL_TESTS, + "extension `%s' available", + sieve_extension_name(ext)); + } else { + return sret; + } + } + if (ret < 0) { + sieve_runtime_trace_error(renv, "invalid capabilities item"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, matched); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/Makefile.am b/pigeonhole/src/lib-sieve/plugins/imap4flags/Makefile.am new file mode 100644 index 0000000..e5390d4 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/Makefile.am @@ -0,0 +1,33 @@ +noinst_LTLIBRARIES = libsieve_ext_imap4flags.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-flag.c + +tests = \ + tst-hasflag.c + +tags = \ + tag-flags.c + +libsieve_ext_imap4flags_la_SOURCES = \ + ext-imap4flags-common.c \ + $(commands) \ + $(tests) \ + $(tags) \ + ext-imap4flags.c \ + ext-imapflags.c + +public_headers = \ + sieve-ext-imap4flags.h + +headers = \ + ext-imap4flags-common.h + +pkginc_libdir=$(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/Makefile.in b/pigeonhole/src/lib-sieve/plugins/imap4flags/Makefile.in new file mode 100644 index 0000000..77f2dc3 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/Makefile.in @@ -0,0 +1,776 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/imap4flags +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(pkginc_lib_HEADERS) $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_imap4flags_la_LIBADD = +am__objects_1 = cmd-flag.lo +am__objects_2 = tst-hasflag.lo +am__objects_3 = tag-flags.lo +am_libsieve_ext_imap4flags_la_OBJECTS = ext-imap4flags-common.lo \ + $(am__objects_1) $(am__objects_2) $(am__objects_3) \ + ext-imap4flags.lo ext-imapflags.lo +libsieve_ext_imap4flags_la_OBJECTS = \ + $(am_libsieve_ext_imap4flags_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/cmd-flag.Plo \ + ./$(DEPDIR)/ext-imap4flags-common.Plo \ + ./$(DEPDIR)/ext-imap4flags.Plo ./$(DEPDIR)/ext-imapflags.Plo \ + ./$(DEPDIR)/tag-flags.Plo ./$(DEPDIR)/tst-hasflag.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_imap4flags_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_imap4flags_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkginc_libdir)" +HEADERS = $(noinst_HEADERS) $(pkginc_lib_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_imap4flags.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-flag.c + +tests = \ + tst-hasflag.c + +tags = \ + tag-flags.c + +libsieve_ext_imap4flags_la_SOURCES = \ + ext-imap4flags-common.c \ + $(commands) \ + $(tests) \ + $(tags) \ + ext-imap4flags.c \ + ext-imapflags.c + +public_headers = \ + sieve-ext-imap4flags.h + +headers = \ + ext-imap4flags-common.h + +pkginc_libdir = $(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/imap4flags/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/imap4flags/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_imap4flags.la: $(libsieve_ext_imap4flags_la_OBJECTS) $(libsieve_ext_imap4flags_la_DEPENDENCIES) $(EXTRA_libsieve_ext_imap4flags_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_imap4flags_la_OBJECTS) $(libsieve_ext_imap4flags_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-flag.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-imap4flags-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-imap4flags.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-imapflags.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tag-flags.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-hasflag.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkginc_libHEADERS: $(pkginc_lib_HEADERS) + @$(NORMAL_INSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkginc_libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkginc_libdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkginc_libdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkginc_libdir)" || exit $$?; \ + done + +uninstall-pkginc_libHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkginc_libdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(pkginc_libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-flag.Plo + -rm -f ./$(DEPDIR)/ext-imap4flags-common.Plo + -rm -f ./$(DEPDIR)/ext-imap4flags.Plo + -rm -f ./$(DEPDIR)/ext-imapflags.Plo + -rm -f ./$(DEPDIR)/tag-flags.Plo + -rm -f ./$(DEPDIR)/tst-hasflag.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pkginc_libHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/cmd-flag.Plo + -rm -f ./$(DEPDIR)/ext-imap4flags-common.Plo + -rm -f ./$(DEPDIR)/ext-imap4flags.Plo + -rm -f ./$(DEPDIR)/ext-imapflags.Plo + -rm -f ./$(DEPDIR)/tag-flags.Plo + -rm -f ./$(DEPDIR)/tst-hasflag.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkginc_libHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-pkginc_libHEADERS install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pkginc_libHEADERS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/cmd-flag.c b/pigeonhole/src/lib-sieve/plugins/imap4flags/cmd-flag.c new file mode 100644 index 0000000..2645669 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/cmd-flag.c @@ -0,0 +1,251 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-code.h" +#include "sieve-stringlist.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-imap4flags-common.h" + +/* + * Commands + */ + +/* Forward declarations */ + +static bool cmd_flag_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +/* Setflag command + * + * Syntax: + * setflag [<variablename: string>] <list-of-flags: string-list> + */ + +const struct sieve_command_def cmd_setflag = { + .identifier = "setflag", + .type = SCT_COMMAND, + .positional_args = -1, /* We check positional arguments ourselves */ + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = ext_imap4flags_command_validate, + .generate = cmd_flag_generate +}; + +/* Addflag command + * + * Syntax: + * addflag [<variablename: string>] <list-of-flags: string-list> + */ + +const struct sieve_command_def cmd_addflag = { + .identifier = "addflag", + .type = SCT_COMMAND, + .positional_args = -1, /* We check positional arguments ourselves */ + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = ext_imap4flags_command_validate, + .generate = cmd_flag_generate +}; + + +/* Removeflag command + * + * Syntax: + * removeflag [<variablename: string>] <list-of-flags: string-list> + */ + +const struct sieve_command_def cmd_removeflag = { + .identifier = "removeflag", + .type = SCT_COMMAND, + .positional_args = -1, /* We check positional arguments ourselves */ + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = ext_imap4flags_command_validate, + .generate = cmd_flag_generate +}; + +/* + * Operations + */ + +/* Forward declarations */ + +bool cmd_flag_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_flag_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +/* Setflag operation */ + +const struct sieve_operation_def setflag_operation = { + .mnemonic = "SETFLAG", + .ext_def = &imap4flags_extension, + .code = EXT_IMAP4FLAGS_OPERATION_SETFLAG, + .dump = cmd_flag_operation_dump, + .execute = cmd_flag_operation_execute +}; + +/* Addflag operation */ + +const struct sieve_operation_def addflag_operation = { + .mnemonic = "ADDFLAG", + .ext_def = &imap4flags_extension, + .code = EXT_IMAP4FLAGS_OPERATION_ADDFLAG, + .dump = cmd_flag_operation_dump, + .execute = cmd_flag_operation_execute +}; + +/* Removeflag operation */ + +const struct sieve_operation_def removeflag_operation = { + .mnemonic = "REMOVEFLAG", + .ext_def = &imap4flags_extension, + .code = EXT_IMAP4FLAGS_OPERATION_REMOVEFLAG, + .dump = cmd_flag_operation_dump, + .execute = cmd_flag_operation_execute +}; + +/* + * Code generation + */ + +static bool cmd_flag_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg1, *arg2; + + /* Emit operation */ + if ( sieve_command_is(cmd, cmd_setflag) ) + sieve_operation_emit(cgenv->sblock, cmd->ext, &setflag_operation); + else if ( sieve_command_is(cmd, cmd_addflag) ) + sieve_operation_emit(cgenv->sblock, cmd->ext, &addflag_operation); + else if ( sieve_command_is(cmd, cmd_removeflag) ) + sieve_operation_emit(cgenv->sblock, cmd->ext, &removeflag_operation); + + arg1 = cmd->first_positional; + arg2 = sieve_ast_argument_next(arg1); + + if ( arg2 == NULL ) { + /* No variable */ + sieve_opr_omitted_emit(cgenv->sblock); + if ( !sieve_generate_argument(cgenv, arg1, cmd) ) + return FALSE; + } else { + /* Full command */ + if ( !sieve_generate_argument(cgenv, arg1, cmd) ) + return FALSE; + if ( !sieve_generate_argument(cgenv, arg2, cmd) ) + return FALSE; + } + return TRUE; +} + +/* + * Code dump + */ + +bool cmd_flag_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + struct sieve_operand oprnd; + + sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(denv->oprtn)); + sieve_code_descend(denv); + + sieve_code_mark(denv); + if ( !sieve_operand_read(denv->sblock, address, NULL, &oprnd) ) { + sieve_code_dumpf(denv, "ERROR: INVALID OPERAND"); + return FALSE; + } + + if ( !sieve_operand_is_omitted(&oprnd) ) { + return + sieve_opr_string_dump_data(denv, &oprnd, address, "variable name") && + sieve_opr_stringlist_dump(denv, address, "list of flags"); + } + + return + sieve_opr_stringlist_dump(denv, address, "list of flags"); +} + +/* + * Code execution + */ + +static int cmd_flag_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_operation *op = renv->oprtn; + struct sieve_operand oprnd; + struct sieve_stringlist *flag_list; + struct sieve_variable_storage *storage; + unsigned int var_index; + ext_imapflag_flag_operation_t flag_op; + int ret; + + /* + * Read operands + */ + + /* Read bare operand (two types possible) */ + if ( (ret=sieve_operand_runtime_read + (renv, address, NULL, &oprnd)) <= 0 ) + return ret; + + /* Variable operand (optional) */ + if ( !sieve_operand_is_omitted(&oprnd) ) { + /* Read the variable operand */ + if ( (ret=sieve_variable_operand_read_data + (renv, &oprnd, address, "variable", &storage, &var_index)) <= 0 ) + return ret; + + /* Read flag list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "flag-list", &flag_list)) + <= 0 ) + return ret; + + /* Flag-list operand */ + } else { + storage = NULL; + var_index = 0; + + /* Read flag list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, + "flag-list", &flag_list)) <= 0 ) + return ret; + } + + /* + * Perform operation + */ + + /* Determine what to do */ + + if ( sieve_operation_is(op, setflag_operation) ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "setflag command"); + flag_op = sieve_ext_imap4flags_set_flags; + } else if ( sieve_operation_is(op, addflag_operation) ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "addflag command"); + flag_op = sieve_ext_imap4flags_add_flags; + } else if ( sieve_operation_is(op, removeflag_operation) ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "removeflag command"); + flag_op = sieve_ext_imap4flags_remove_flags; + } else { + i_unreached(); + } + + sieve_runtime_trace_descend(renv); + + /* Perform requested operation */ + return flag_op(renv, op->ext, storage, var_index, flag_list); +} diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c b/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c new file mode 100644 index 0000000..3c364b8 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c @@ -0,0 +1,733 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" +#include "mail-storage.h" +#include "imap-arg.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-stringlist.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "ext-imap4flags-common.h" + +/* + * Tagged arguments + */ + +extern const struct sieve_argument_def tag_flags; +extern const struct sieve_argument_def tag_flags_implicit; + +/* + * Common command functions + */ + +bool ext_imap4flags_command_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + struct sieve_ast_argument *arg2; + const struct sieve_extension *var_ext; + + /* Check arguments */ + + if ( arg == NULL ) { + sieve_command_validate_error(valdtr, cmd, + "the %s %s expects at least one argument, but none was found", + sieve_command_identifier(cmd), sieve_command_type_name(cmd)); + return FALSE; + } + + if ( sieve_ast_argument_type(arg) != SAAT_STRING && + sieve_ast_argument_type(arg) != SAAT_STRING_LIST ) + { + sieve_argument_validate_error(valdtr, arg, + "the %s %s expects either a string (variable name) or " + "a string-list (list of flags) as first argument, but %s was found", + sieve_command_identifier(cmd), sieve_command_type_name(cmd), + sieve_ast_argument_name(arg)); + return FALSE; + } + + arg2 = sieve_ast_argument_next(arg); + if ( arg2 != NULL ) { + /* First, check syntax sanity */ + + if ( sieve_ast_argument_type(arg) != SAAT_STRING ) + { + if ( sieve_command_is(cmd, tst_hasflag) ) { + if ( sieve_ast_argument_type(arg) != SAAT_STRING_LIST ) { + sieve_argument_validate_error(valdtr, arg, + "if a second argument is specified for the hasflag, the first " + "must be a string-list (variable-list), but %s was found", + sieve_ast_argument_name(arg)); + return FALSE; + } + } else { + sieve_argument_validate_error(valdtr, arg, + "if a second argument is specified for the %s %s, the first " + "must be a string (variable name), but %s was found", + sieve_command_identifier(cmd), sieve_command_type_name(cmd), + sieve_ast_argument_name(arg)); + return FALSE; + } + } + + /* Then, check whether the second argument is permitted */ + + var_ext = sieve_ext_variables_get_extension(cmd->ext->svinst); + + if ( var_ext == NULL || !sieve_ext_variables_is_active(var_ext, valdtr) ) + { + sieve_argument_validate_error(valdtr,arg, + "the %s %s only allows for the specification of a " + "variable name when the variables extension is active", + sieve_command_identifier(cmd), sieve_command_type_name(cmd)); + return FALSE; + } + + if ( !sieve_variable_argument_activate(var_ext, var_ext, + valdtr, cmd, arg, !sieve_command_is(cmd, tst_hasflag) ) ) + return FALSE; + + if ( sieve_ast_argument_type(arg2) != SAAT_STRING && + sieve_ast_argument_type(arg2) != SAAT_STRING_LIST ) + { + sieve_argument_validate_error(valdtr, arg2, + "the %s %s expects a string list (list of flags) as " + "second argument when two arguments are specified, " + "but %s was found", + sieve_command_identifier(cmd), sieve_command_type_name(cmd), + sieve_ast_argument_name(arg2)); + return FALSE; + } + } else + arg2 = arg; + + if ( !sieve_validator_argument_activate(valdtr, cmd, arg2, FALSE) ) + return FALSE; + + if ( !sieve_command_is(cmd, tst_hasflag) && + sieve_argument_is_string_literal(arg2) ) { + struct ext_imap4flags_iter fiter; + const char *flag; + + /* Warn the user about validity of verifiable flags */ + ext_imap4flags_iter_init(&fiter, sieve_ast_argument_str(arg)); + + while ( (flag=ext_imap4flags_iter_get_flag(&fiter)) != NULL ) { + if ( !sieve_ext_imap4flags_flag_is_valid(flag) ) { + sieve_argument_validate_warning(valdtr, arg, + "IMAP flag '%s' specified for the %s command is invalid " + "and will be ignored (only first invalid is reported)", + str_sanitize(flag, 64), sieve_command_identifier(cmd)); + break; + } + } + } + + return TRUE; +} + +/* + * Flags tag registration + */ + +void ext_imap4flags_attach_flags_tag +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + const char *command) +{ + /* Register :flags tag with the command and we don't care whether it is + * registered or even whether it will be registered at all. The validator + * handles either situation gracefully + */ + + /* Tag specified by user */ + sieve_validator_register_external_tag + (valdtr, command, ext, &tag_flags, SIEVE_OPT_SIDE_EFFECT); +} + +void sieve_ext_imap4flags_register_side_effect +(struct sieve_validator *valdtr, const struct sieve_extension *flg_ext, + const char *command) +{ + /* Implicit tag if none is specified */ + sieve_validator_register_persistent_tag + (valdtr, command, flg_ext, &tag_flags_implicit); +} + + +/* + * Result context + */ + +struct ext_imap4flags_result_context { + string_t *internal_flags; +}; + +static void _get_initial_flags +(struct sieve_result *result, string_t *flags) +{ + const struct sieve_message_data *msgdata = + sieve_result_get_message_data(result); + enum mail_flags mail_flags; + const char *const *mail_keywords; + + mail_flags = mail_get_flags(msgdata->mail); + mail_keywords = mail_get_keywords(msgdata->mail); + + if ( (mail_flags & MAIL_FLAGGED) > 0 ) + str_printfa(flags, " \\flagged"); + + if ( (mail_flags & MAIL_ANSWERED) > 0 ) + str_printfa(flags, " \\answered"); + + if ( (mail_flags & MAIL_DELETED) > 0 ) + str_printfa(flags, " \\deleted"); + + if ( (mail_flags & MAIL_SEEN) > 0 ) + str_printfa(flags, " \\seen"); + + if ( (mail_flags & MAIL_DRAFT) > 0 ) + str_printfa(flags, " \\draft"); + + while ( *mail_keywords != NULL ) { + str_printfa(flags, " %s", *mail_keywords); + mail_keywords++; + } +} + +static inline struct ext_imap4flags_result_context *_get_result_context +(const struct sieve_extension *this_ext, struct sieve_result *result) +{ + struct ext_imap4flags_result_context *rctx = + (struct ext_imap4flags_result_context *) + sieve_result_extension_get_context(result, this_ext); + + if ( rctx == NULL ) { + pool_t pool = sieve_result_pool(result); + + rctx =p_new(pool, struct ext_imap4flags_result_context, 1); + rctx->internal_flags = str_new(pool, 32); + _get_initial_flags(result, rctx->internal_flags); + + sieve_result_extension_set_context + (result, this_ext, rctx); + } + + return rctx; +} + +static string_t *_get_flags_string +(const struct sieve_extension *this_ext, struct sieve_result *result) +{ + struct ext_imap4flags_result_context *ctx = + _get_result_context(this_ext, result); + + return ctx->internal_flags; +} + +/* + * Runtime initialization + */ + +static int ext_imap4flags_runtime_init +(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + void *context ATTR_UNUSED, bool deferred ATTR_UNUSED) +{ + sieve_result_add_implicit_side_effect + (renv->result, NULL, TRUE, ext, &flags_side_effect, NULL); + return SIEVE_EXEC_OK; +} + +const struct sieve_interpreter_extension +imap4flags_interpreter_extension = { + .ext_def = &imap4flags_extension, + .run = ext_imap4flags_runtime_init +}; + +/* + * Flag handling + */ + +/* FIXME: This currently accepts a potentially unlimited number of + * flags, making the internal or variable flag list indefinitely long + */ + +bool sieve_ext_imap4flags_flag_is_valid(const char *flag) +{ + if ( *flag == '\0' ) + return FALSE; + + if ( *flag == '\\' ) { + /* System flag */ + const char *atom = t_str_ucase(flag); + + if ( + (strcmp(atom, "\\ANSWERED") != 0) && + (strcmp(atom, "\\FLAGGED") != 0) && + (strcmp(atom, "\\DELETED") != 0) && + (strcmp(atom, "\\SEEN") != 0) && + (strcmp(atom, "\\DRAFT") != 0) ) + { + return FALSE; + } + } else { + const char *p; + + /* Custom keyword: + * + * Syntax (IMAP4rev1, RFC 3501, Section 9. Formal Syntax) : + * flag-keyword = atom + * atom = 1*ATOM-CHAR + */ + p = flag; + while ( *p != '\0' ) { + if ( !IS_ATOM_CHAR(*p) ) + return FALSE; + p++; + } + } + + return TRUE; +} + +/* Flag iterator */ + +static void ext_imap4flags_iter_clear +(struct ext_imap4flags_iter *iter) +{ + i_zero(iter); +} + +void ext_imap4flags_iter_init +(struct ext_imap4flags_iter *iter, string_t *flags_list) +{ + ext_imap4flags_iter_clear(iter); + iter->flags_list = flags_list; +} + +static string_t *ext_imap4flags_iter_get_flag_str +(struct ext_imap4flags_iter *iter) +{ + unsigned int len; + const unsigned char *fp; + const unsigned char *fbegin; + const unsigned char *fstart; + const unsigned char *fend; + + /* Return if not initialized */ + if ( iter->flags_list == NULL ) return NULL; + + /* Return if no more flags are available */ + len = str_len(iter->flags_list); + if ( iter->offset >= len ) return NULL; + + /* Mark string boundries */ + fbegin = str_data(iter->flags_list); + fend = fbegin + len; + + /* Start of this flag */ + fstart = fbegin + iter->offset; + + /* Scan for next flag */ + fp = fstart; + for (;;) { + /* Have we reached the end or a flag boundary? */ + if ( fp >= fend || *fp == ' ' ) { + /* Did we scan more than nothing ? */ + if ( fp > fstart ) { + /* Return flag */ + string_t *flag = t_str_new(fp-fstart+1); + str_append_data(flag, fstart, fp-fstart); + + iter->last = fstart - fbegin; + iter->offset = fp - fbegin; + + return flag; + } + + fstart = fp + 1; + } + + if ( fp >= fend ) break; + + fp++; + } + + iter->last = fstart - fbegin; + iter->offset = fp - fbegin; + return NULL; +} + +const char *ext_imap4flags_iter_get_flag +(struct ext_imap4flags_iter *iter) +{ + string_t *flag = ext_imap4flags_iter_get_flag_str(iter); + + if ( flag == NULL ) return NULL; + + return str_c(flag); +} + +static void ext_imap4flags_iter_delete_last +(struct ext_imap4flags_iter *iter) +{ + iter->offset++; + if ( iter->offset > str_len(iter->flags_list) ) + iter->offset = str_len(iter->flags_list); + if ( iter->offset == str_len(iter->flags_list) && iter->last > 0 ) + iter->last--; + + str_delete(iter->flags_list, iter->last, iter->offset - iter->last); + + iter->offset = iter->last; +} + +/* Flag operations */ + +static string_t *ext_imap4flags_get_flag_variable +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_variable_storage *storage, + unsigned int var_index) + ATTR_NULL(2); + +static bool flags_list_flag_exists +(string_t *flags_list, const char *flag) +{ + const char *flg; + struct ext_imap4flags_iter flit; + + ext_imap4flags_iter_init(&flit, flags_list); + + while ( (flg=ext_imap4flags_iter_get_flag(&flit)) != NULL ) { + if ( strcasecmp(flg, flag) == 0 ) + return TRUE; + } + + return FALSE; +} + +static void flags_list_flag_delete +(string_t *flags_list, const char *flag) +{ + const char *flg; + struct ext_imap4flags_iter flit; + + ext_imap4flags_iter_init(&flit, flags_list); + + while ( (flg=ext_imap4flags_iter_get_flag(&flit)) != NULL ) { + if ( strcasecmp(flg, flag) == 0 ) { + ext_imap4flags_iter_delete_last(&flit); + } + } +} + +static void flags_list_add_flags +(string_t *flags_list, string_t *flags) +{ + const char *flg; + struct ext_imap4flags_iter flit; + + ext_imap4flags_iter_init(&flit, flags); + + while ( (flg=ext_imap4flags_iter_get_flag(&flit)) != NULL ) { + if ( sieve_ext_imap4flags_flag_is_valid(flg) && + !flags_list_flag_exists(flags_list, flg) ) { + if ( str_len(flags_list) != 0 ) + str_append_c(flags_list, ' '); + str_append(flags_list, flg); + } + } +} + +static void flags_list_remove_flags +(string_t *flags_list, string_t *flags) +{ + const char *flg; + struct ext_imap4flags_iter flit; + + ext_imap4flags_iter_init(&flit, flags); + + while ( (flg=ext_imap4flags_iter_get_flag(&flit)) != NULL ) { + flags_list_flag_delete(flags_list, flg); + } +} + +static void flags_list_set_flags +(string_t *flags_list, string_t *flags) +{ + str_truncate(flags_list, 0); + flags_list_add_flags(flags_list, flags); +} + +static void flags_list_clear_flags +(string_t *flags_list) +{ + str_truncate(flags_list, 0); +} + +static string_t *ext_imap4flags_get_flag_variable +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_variable_storage *storage, + unsigned int var_index) +{ + string_t *flags; + + if ( storage != NULL ) { + if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) { + const char *var_name, *var_id; + + (void)sieve_variable_get_identifier(storage, var_index, &var_name); + var_id = sieve_variable_get_varid(storage, var_index); + + sieve_runtime_trace(renv, 0, "update variable `%s' [%s]", + var_name, var_id); + } + + if ( !sieve_variable_get_modifiable(storage, var_index, &flags) ) + return NULL; + } else { + i_assert( sieve_extension_is(flg_ext, imap4flags_extension) ); + flags = _get_flags_string(flg_ext, renv->result); + } + + return flags; +} + +int sieve_ext_imap4flags_set_flags +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_variable_storage *storage, + unsigned int var_index, + struct sieve_stringlist *flags) +{ + string_t *cur_flags = ext_imap4flags_get_flag_variable + (renv, flg_ext, storage, var_index); + + if ( cur_flags != NULL ) { + string_t *flags_item; + int ret; + + flags_list_clear_flags(cur_flags); + while ( (ret=sieve_stringlist_next_item(flags, &flags_item)) > 0 ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "set flags `%s'", str_c(flags_item)); + + flags_list_add_flags(cur_flags, flags_item); + } + + if ( ret < 0 ) return SIEVE_EXEC_BIN_CORRUPT; + + return SIEVE_EXEC_OK; + } + + return SIEVE_EXEC_BIN_CORRUPT; +} + +int sieve_ext_imap4flags_add_flags +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_variable_storage *storage, + unsigned int var_index, + struct sieve_stringlist *flags) +{ + string_t *cur_flags = ext_imap4flags_get_flag_variable + (renv, flg_ext, storage, var_index); + + if ( cur_flags != NULL ) { + string_t *flags_item; + int ret; + + while ( (ret=sieve_stringlist_next_item(flags, &flags_item)) > 0 ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "add flags `%s'", str_c(flags_item)); + + flags_list_add_flags(cur_flags, flags_item); + } + + if ( ret < 0 ) return SIEVE_EXEC_BIN_CORRUPT; + + return SIEVE_EXEC_OK; + } + + return SIEVE_EXEC_BIN_CORRUPT; +} + +int sieve_ext_imap4flags_remove_flags +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_variable_storage *storage, + unsigned int var_index, + struct sieve_stringlist *flags) +{ + string_t *cur_flags = ext_imap4flags_get_flag_variable + (renv, flg_ext, storage, var_index); + + if ( cur_flags != NULL ) { + string_t *flags_item; + int ret; + + while ( (ret=sieve_stringlist_next_item(flags, &flags_item)) > 0 ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "remove flags `%s'", str_c(flags_item)); + + flags_list_remove_flags(cur_flags, flags_item); + } + + if ( ret < 0 ) return SIEVE_EXEC_BIN_CORRUPT; + + return SIEVE_EXEC_OK; + } + + return SIEVE_EXEC_BIN_CORRUPT; +} + +/* Flag stringlist */ + +static int ext_imap4flags_stringlist_next_item + (struct sieve_stringlist *_strlist, string_t **str_r); +static void ext_imap4flags_stringlist_reset + (struct sieve_stringlist *_strlist); + +struct ext_imap4flags_stringlist { + struct sieve_stringlist strlist; + + struct sieve_stringlist *flags_list; + string_t *flags_string; + struct ext_imap4flags_iter flit; + + bool normalize:1; +}; + +static struct sieve_stringlist *ext_imap4flags_stringlist_create +(const struct sieve_runtime_env *renv, struct sieve_stringlist *flags_list, + bool normalize) +{ + struct ext_imap4flags_stringlist *strlist; + + strlist = t_new(struct ext_imap4flags_stringlist, 1); + strlist->strlist.exec_status = SIEVE_EXEC_OK; + strlist->strlist.runenv = renv; + strlist->strlist.next_item = ext_imap4flags_stringlist_next_item; + strlist->strlist.reset = ext_imap4flags_stringlist_reset; + strlist->normalize = normalize; + + strlist->flags_list = flags_list; + + return &strlist->strlist; +} + +static struct sieve_stringlist *ext_imap4flags_stringlist_create_single +(const struct sieve_runtime_env *renv, string_t *flags_string, bool normalize) +{ + struct ext_imap4flags_stringlist *strlist; + + strlist = t_new(struct ext_imap4flags_stringlist, 1); + strlist->strlist.exec_status = SIEVE_EXEC_OK; + strlist->strlist.runenv = renv; + strlist->strlist.next_item = ext_imap4flags_stringlist_next_item; + strlist->strlist.reset = ext_imap4flags_stringlist_reset; + strlist->normalize = normalize; + + if ( normalize ) { + strlist->flags_string = t_str_new(256); + flags_list_set_flags(strlist->flags_string, flags_string); + } else { + strlist->flags_string = flags_string; + } + + ext_imap4flags_iter_init(&strlist->flit, strlist->flags_string); + + return &strlist->strlist; +} + +static int ext_imap4flags_stringlist_next_item +(struct sieve_stringlist *_strlist, string_t **str_r) +{ + struct ext_imap4flags_stringlist *strlist = + (struct ext_imap4flags_stringlist *)_strlist; + + while ( (*str_r=ext_imap4flags_iter_get_flag_str(&strlist->flit)) == NULL ) { + int ret; + + if ( strlist->flags_list == NULL ) + return 0; + + if ( (ret=sieve_stringlist_next_item + (strlist->flags_list, &strlist->flags_string)) <= 0 ) + return ret; + + if ( strlist->flags_string == NULL ) + return -1; + + if ( strlist->normalize ) { + string_t *flags_string = t_str_new(256); + + flags_list_set_flags(flags_string, strlist->flags_string); + strlist->flags_string = flags_string; + } + + ext_imap4flags_iter_init(&strlist->flit, strlist->flags_string); + } + + return 1; +} + +static void ext_imap4flags_stringlist_reset +(struct sieve_stringlist *_strlist) +{ + struct ext_imap4flags_stringlist *strlist = + (struct ext_imap4flags_stringlist *)_strlist; + + if ( strlist->flags_list != NULL ) { + sieve_stringlist_reset(strlist->flags_list); + ext_imap4flags_iter_clear(&strlist->flit); + } else { + ext_imap4flags_iter_init(&strlist->flit, strlist->flags_string); + } +} + +/* Flag access */ + +struct sieve_stringlist *sieve_ext_imap4flags_get_flags +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_stringlist *flags_list) +{ + if ( flags_list == NULL ) { + i_assert( sieve_extension_is(flg_ext, imap4flags_extension) ); + return ext_imap4flags_stringlist_create_single + (renv, _get_flags_string(flg_ext, renv->result), FALSE); + } + + return ext_imap4flags_stringlist_create(renv, flags_list, TRUE); +} + +void ext_imap4flags_get_implicit_flags_init +(struct ext_imap4flags_iter *iter, const struct sieve_extension *this_ext, + struct sieve_result *result) +{ + string_t *cur_flags = _get_flags_string(this_ext, result); + + ext_imap4flags_iter_init(iter, cur_flags); +} + + + + + diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h b/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h new file mode 100644 index 0000000..4bedb85 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h @@ -0,0 +1,97 @@ +#ifndef EXT_IMAP4FLAGS_COMMON_H +#define EXT_IMAP4FLAGS_COMMON_H + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-ext-variables.h" + +#include "sieve-ext-imap4flags.h" + +/* + * Side effect + */ + +extern const struct sieve_side_effect_def flags_side_effect; + +/* + * Operands + */ + +extern const struct sieve_operand_def flags_side_effect_operand; + +/* + * Operations + */ + +enum ext_imap4flags_opcode { + EXT_IMAP4FLAGS_OPERATION_SETFLAG, + EXT_IMAP4FLAGS_OPERATION_ADDFLAG, + EXT_IMAP4FLAGS_OPERATION_REMOVEFLAG, + EXT_IMAP4FLAGS_OPERATION_HASFLAG +}; + +extern const struct sieve_operation_def setflag_operation; +extern const struct sieve_operation_def addflag_operation; +extern const struct sieve_operation_def removeflag_operation; +extern const struct sieve_operation_def hasflag_operation; + +/* + * Commands + */ + +extern const struct sieve_command_def cmd_setflag; +extern const struct sieve_command_def cmd_addflag; +extern const struct sieve_command_def cmd_removeflag; + +extern const struct sieve_command_def tst_hasflag; + +/* + * Common command functions + */ + +bool ext_imap4flags_command_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); + +/* + * Flags tagged argument + */ + +void ext_imap4flags_attach_flags_tag + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + const char *command); + +/* + * Flag management + */ + +struct ext_imap4flags_iter { + string_t *flags_list; + unsigned int offset; + unsigned int last; +}; + +void ext_imap4flags_iter_init + (struct ext_imap4flags_iter *iter, string_t *flags_list); + +const char *ext_imap4flags_iter_get_flag + (struct ext_imap4flags_iter *iter); + +/* Flag operations */ + +typedef int (*ext_imapflag_flag_operation_t) + (const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_variable_storage *storage, + unsigned int var_index, struct sieve_stringlist *flags) + ATTR_NULL(2); + +/* Flags access */ + +void ext_imap4flags_get_implicit_flags_init + (struct ext_imap4flags_iter *iter, const struct sieve_extension *this_ext, + struct sieve_result *result); + + +#endif + diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imap4flags.c b/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imap4flags.c new file mode 100644 index 0000000..23230c1 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imap4flags.c @@ -0,0 +1,96 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension imap4flags + * -------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5232 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "mempool.h" +#include "str.h" + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-imap4flags-common.h" + +/* + * Operations + */ + +const struct sieve_operation_def *imap4flags_operations[] = { + &setflag_operation, + &addflag_operation, + &removeflag_operation, + &hasflag_operation +}; + +/* + * Extension + */ + +static bool ext_imap4flags_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); +static bool ext_imap4flags_interpreter_load + (const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_extension_def imap4flags_extension = { + .name = "imap4flags", + .version = 1, + .validator_load = ext_imap4flags_validator_load, + .interpreter_load = ext_imap4flags_interpreter_load, + SIEVE_EXT_DEFINE_OPERATIONS(imap4flags_operations), + SIEVE_EXT_DEFINE_OPERAND(flags_side_effect_operand) +}; + +static bool ext_imap4flags_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register commands */ + sieve_validator_register_command(valdtr, ext, &cmd_setflag); + sieve_validator_register_command(valdtr, ext, &cmd_addflag); + sieve_validator_register_command(valdtr, ext, &cmd_removeflag); + sieve_validator_register_command(valdtr, ext, &tst_hasflag); + + /* Attach :flags tag to keep and fileinto commands */ + ext_imap4flags_attach_flags_tag(valdtr, ext, "keep"); + ext_imap4flags_attach_flags_tag(valdtr, ext, "fileinto"); + + /* Attach flags side-effect to keep and fileinto actions */ + sieve_ext_imap4flags_register_side_effect(valdtr, ext, "keep"); + sieve_ext_imap4flags_register_side_effect(valdtr, ext, "fileinto"); + + return TRUE; +} + +void sieve_ext_imap4flags_interpreter_load +(const struct sieve_extension *ext, const struct sieve_runtime_env *renv) +{ + sieve_interpreter_extension_register + (renv->interp, ext, &imap4flags_interpreter_extension, NULL); +} + +static bool ext_imap4flags_interpreter_load +(const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + sieve_ext_imap4flags_interpreter_load(ext, renv); + return TRUE; +} + + + diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imapflags.c b/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imapflags.c new file mode 100644 index 0000000..ba99035 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imapflags.c @@ -0,0 +1,213 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension imapflags + * -------------------- + * + * Authors: Stephan Bosch + * Specification: draft-melnikov-sieve-imapflags-03.txt + * Implementation: full, but deprecated; provided for backwards compatibility + * Status: testing + * + */ + +#include "lib.h" +#include "mempool.h" +#include "str.h" + +#include "sieve-common.h" + +#include "sieve-ast.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-imap4flags-common.h" + +/* + * Commands + */ + +static bool cmd_mark_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); + +/* Mark command + * + * Syntax: + * mark + */ + +static const struct sieve_command_def cmd_mark = { + .identifier = "mark", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_mark_validate +}; + +/* Unmark command + * + * Syntax: + * unmark + */ +static const struct sieve_command_def cmd_unmark = { + .identifier = "unmark", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_mark_validate +}; + +/* + * Extension + */ + +static bool ext_imapflags_load + (const struct sieve_extension *ext, void **context); +static bool ext_imapflags_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); +static bool ext_imapflags_interpreter_load + (const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_extension_def imapflags_extension = { + .name = "imapflags", + .load = ext_imapflags_load, + .validator_load = ext_imapflags_validator_load, + .interpreter_load = ext_imapflags_interpreter_load +}; + +static bool ext_imapflags_load +(const struct sieve_extension *ext, void **context) +{ + if ( *context == NULL ) { + /* Make sure real extension is registered, it is needed by the binary */ + *context = (void *) + sieve_extension_require(ext->svinst, &imap4flags_extension, FALSE); + } + + return TRUE; +} + +/* + * Validator + */ + +static bool ext_imapflags_validator_check_conflict + (const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + const struct sieve_extension *other_ext, + bool required); +static bool ext_imapflags_validator_validate + (const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + bool required); + +const struct sieve_validator_extension +imapflags_validator_extension = { + .ext = &imapflags_extension, + .check_conflict = ext_imapflags_validator_check_conflict, + .validate = ext_imapflags_validator_validate +}; + +static bool ext_imapflags_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + sieve_validator_extension_register + (valdtr, ext, &imapflags_validator_extension, NULL); + + return TRUE; +} + +static bool ext_imapflags_validator_check_conflict +(const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg, + const struct sieve_extension *ext_other, + bool required ATTR_UNUSED) +{ + const struct sieve_extension *master_ext = + (const struct sieve_extension *) ext->context; + + if ( ext_other == master_ext ) { + sieve_argument_validate_error(valdtr, require_arg, + "the (deprecated) imapflags extension cannot be used " + "together with the imap4flags extension"); + return FALSE; + } + + return TRUE; +} + +static bool ext_imapflags_validator_validate +(const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg ATTR_UNUSED, + bool required ATTR_UNUSED) +{ + const struct sieve_extension *master_ext = + (const struct sieve_extension *) ext->context; + + /* No conflicts */ + + /* Register commands */ + sieve_validator_register_command(valdtr, master_ext, &cmd_setflag); + sieve_validator_register_command(valdtr, master_ext, &cmd_addflag); + sieve_validator_register_command(valdtr, master_ext, &cmd_removeflag); + + sieve_validator_register_command(valdtr, master_ext, &cmd_mark); + sieve_validator_register_command(valdtr, master_ext, &cmd_unmark); + + /* Attach flags side-effect to keep and fileinto actions */ + sieve_ext_imap4flags_register_side_effect(valdtr, master_ext, "keep"); + sieve_ext_imap4flags_register_side_effect(valdtr, master_ext, "fileinto"); + + return TRUE; +} + +/* + * Interpreter + */ + +static bool ext_imapflags_interpreter_load +(const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + const struct sieve_extension *master_ext = + (const struct sieve_extension *) ext->context; + + sieve_ext_imap4flags_interpreter_load(master_ext, renv); + return TRUE; +} + +/* + * Command validation + */ + +static bool cmd_mark_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + if ( sieve_command_is(cmd, cmd_mark) ) + cmd->def = &cmd_addflag; + else + cmd->def = &cmd_removeflag; + + cmd->first_positional = sieve_ast_argument_cstring_create + (cmd->ast_node, "\\flagged", cmd->ast_node->source_line); + + if ( !sieve_validator_argument_activate + (valdtr, cmd, cmd->first_positional, FALSE) ) + return FALSE; + + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/sieve-ext-imap4flags.h b/pigeonhole/src/lib-sieve/plugins/imap4flags/sieve-ext-imap4flags.h new file mode 100644 index 0000000..b38a3c8 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/sieve-ext-imap4flags.h @@ -0,0 +1,74 @@ +#ifndef SIEVE_EXT_IMAP4FLAGS_H +#define SIEVE_EXT_IMAP4FLAGS_H + +struct sieve_variable_storage; + +/* + * Imap4flags extension + */ + +/* FIXME: this is not suitable for future plugin support */ + +extern const struct sieve_extension_def imap4flags_extension; +extern const struct sieve_interpreter_extension + imap4flags_interpreter_extension; + +static inline const struct sieve_extension * +sieve_ext_imap4flags_require_extension +(struct sieve_instance *svinst) +{ + return sieve_extension_require + (svinst, &imap4flags_extension, TRUE); +} + +void sieve_ext_imap4flags_interpreter_load +(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv); + +/* + * Action side-effect + */ + +void sieve_ext_imap4flags_register_side_effect +(struct sieve_validator *valdtr, const struct sieve_extension *flg_ext, + const char *command); + +/* + * Flag syntax + */ + +bool sieve_ext_imap4flags_flag_is_valid(const char *flag); + +/* + * Flag manipulation + */ + +int sieve_ext_imap4flags_set_flags +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_variable_storage *storage, + unsigned int var_index, + struct sieve_stringlist *flags) ATTR_NULL(3); +int sieve_ext_imap4flags_add_flags +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_variable_storage *storage, + unsigned int var_index, + struct sieve_stringlist *flags) ATTR_NULL(3); +int sieve_ext_imap4flags_remove_flags +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_variable_storage *storage, + unsigned int var_index, + struct sieve_stringlist *flags) ATTR_NULL(3); + +/* + * Flag retrieval + */ + +struct sieve_stringlist *sieve_ext_imap4flags_get_flags +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_stringlist *flags_list); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/tag-flags.c b/pigeonhole/src/lib-sieve/plugins/imap4flags/tag-flags.c new file mode 100644 index 0000000..331063d --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/tag-flags.c @@ -0,0 +1,402 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" +#include "array.h" +#include "mail-storage.h" + +#include "sieve-code.h" +#include "sieve-stringlist.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-result.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-actions.h" +#include "sieve-dump.h" + +#include "ext-imap4flags-common.h" + +#include <ctype.h> + +/* + * Flags tagged argument + */ + +static bool +tag_flags_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, struct sieve_command *cmd); +static bool +tag_flags_validate_persistent(struct sieve_validator *valdtr, + struct sieve_command *cmd, + const struct sieve_extension *ext); +static bool +tag_flags_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, struct sieve_command *cmd); + +const struct sieve_argument_def tag_flags = { + .identifier = "flags", + .validate = tag_flags_validate, + .generate = tag_flags_generate, +}; + +const struct sieve_argument_def tag_flags_implicit = { + .identifier = "flags-implicit", + .validate_persistent = tag_flags_validate_persistent, + .generate = tag_flags_generate, +}; + +/* + * Side effect + */ + +static bool +seff_flags_dump_context(const struct sieve_side_effect *seffect, + const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +seff_flags_read_context(const struct sieve_side_effect *seffect, + const struct sieve_runtime_env *renv, + sieve_size_t *address, void **context); + +static int +seff_flags_merge(const struct sieve_runtime_env *renv, + const struct sieve_action *action, + const struct sieve_side_effect *old_seffect, + const struct sieve_side_effect *new_seffect, + void **old_context); + +static void +seff_flags_print(const struct sieve_side_effect *seffect, + const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep); + +static int +seff_flags_pre_execute(const struct sieve_side_effect *seffect, + const struct sieve_action_exec_env *aenv, + void *tr_context, void **se_tr_context); + +const struct sieve_side_effect_def flags_side_effect = { + SIEVE_OBJECT("flags", &flags_side_effect_operand, 0), + .to_action = &act_store, + .dump_context = seff_flags_dump_context, + .read_context = seff_flags_read_context, + .merge = seff_flags_merge, + .print = seff_flags_print, + .pre_execute = seff_flags_pre_execute, +}; + +/* + * Operand + */ + +static const struct sieve_extension_objects ext_side_effects = + SIEVE_EXT_DEFINE_SIDE_EFFECT(flags_side_effect); + +const struct sieve_operand_def flags_side_effect_operand = { + .name = "flags operand", + .ext_def = &imap4flags_extension, + .class = &sieve_side_effect_operand_class, + .interface = &ext_side_effects, +}; + +/* + * Tag validation + */ + +static bool +tag_flags_validate_persistent(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *cmd, + const struct sieve_extension *ext) +{ + if (sieve_command_find_argument(cmd, &tag_flags) == NULL) + sieve_command_add_dynamic_tag(cmd, ext, &tag_flags_implicit, + -1); + return TRUE; +} + +static bool +tag_flags_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + + /* Detach the tag itself */ + *arg = sieve_ast_argument_next(*arg); + + /* Check syntax: + * :flags <list-of-flags: string-list> + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING_LIST, FALSE)) + return FALSE; + + tag->parameters = *arg; + + /* Detach parameter */ + *arg = sieve_ast_arguments_detach(*arg,1); + return TRUE; +} + +/* + * Code generation + */ + +static bool +tag_flags_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, struct sieve_command *cmd) +{ + struct sieve_ast_argument *param; + + if (sieve_ast_argument_type(arg) != SAAT_TAG) + return FALSE; + + sieve_opr_side_effect_emit(cgenv->sblock, arg->argument->ext, + &flags_side_effect); + + if (sieve_argument_is(arg, tag_flags)) { + /* Explicit :flags tag */ + param = arg->parameters; + + /* Call the generation function for the argument */ + if (param->argument != NULL && param->argument->def != NULL && + param->argument->def->generate != NULL && + !param->argument->def->generate(cgenv, param, cmd)) + return FALSE; + } else if (sieve_argument_is(arg, tag_flags_implicit)) { + /* Implicit flags */ + sieve_opr_omitted_emit(cgenv->sblock); + } else { + /* Something else?! */ + i_unreached(); + } + return TRUE; +} + +/* + * Side effect implementation + */ + +/* Context data */ + +struct seff_flags_context { + ARRAY(const char *) keywords; + enum mail_flags flags; +}; + +/* Context coding */ + +static bool +seff_flags_dump_context(const struct sieve_side_effect *seffect ATTR_UNUSED, + const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + return sieve_opr_stringlist_dump_ex(denv, address, "flags", "INTERNAL"); +} + +static struct seff_flags_context * +seff_flags_get_implicit_context(const struct sieve_extension *this_ext, + struct sieve_result *result) +{ + pool_t pool = sieve_result_pool(result); + struct seff_flags_context *ctx; + const char *flag; + struct ext_imap4flags_iter flit; + + ctx = p_new(pool, struct seff_flags_context, 1); + p_array_init(&ctx->keywords, pool, 2); + + T_BEGIN { + /* Unpack */ + ext_imap4flags_get_implicit_flags_init(&flit, this_ext, result); + while ((flag = ext_imap4flags_iter_get_flag(&flit)) != NULL) { + if (flag != NULL && *flag != '\\') { + /* keyword */ + const char *keyword = p_strdup(pool, flag); + array_append(&ctx->keywords, &keyword, 1); + } else { + /* system flag */ + if (flag == NULL || + strcasecmp(flag, "\\flagged") == 0) + ctx->flags |= MAIL_FLAGGED; + else if (strcasecmp(flag, "\\answered") == 0) + ctx->flags |= MAIL_ANSWERED; + else if (strcasecmp(flag, "\\deleted") == 0) + ctx->flags |= MAIL_DELETED; + else if (strcasecmp(flag, "\\seen") == 0) + ctx->flags |= MAIL_SEEN; + else if (strcasecmp(flag, "\\draft") == 0) + ctx->flags |= MAIL_DRAFT; + } + } + } T_END; + + return ctx; +} + +static int +seff_flags_do_read_context(const struct sieve_side_effect *seffect, + const struct sieve_runtime_env *renv, + sieve_size_t *address, void **se_context) +{ + pool_t pool = sieve_result_pool(renv->result); + struct seff_flags_context *ctx; + string_t *flags_item; + struct sieve_stringlist *flag_list = NULL; + int ret; + + ret = sieve_opr_stringlist_read_ex(renv, address, "flags", TRUE, + &flag_list); + if (ret <= 0) + return ret; + + if (flag_list == NULL) { + /* Flag list is omitted, use current value of internal + * variable to construct side effect context. + */ + *se_context = seff_flags_get_implicit_context( + SIEVE_OBJECT_EXTENSION(seffect), renv->result); + return SIEVE_EXEC_OK; + } + + ctx = p_new(pool, struct seff_flags_context, 1); + p_array_init(&ctx->keywords, pool, 2); + + /* Unpack */ + flags_item = NULL; + while ((ret = sieve_stringlist_next_item(flag_list, &flags_item)) > 0) { + const char *flag; + struct ext_imap4flags_iter flit; + + ext_imap4flags_iter_init(&flit, flags_item); + + while ((flag = ext_imap4flags_iter_get_flag(&flit)) != NULL) { + if (flag != NULL && *flag != '\\') { + /* keyword */ + const char *keyword = p_strdup(pool, flag); + + /* FIXME: should check for duplicates (cannot + trust variables) */ + array_append(&ctx->keywords, &keyword, 1); + } else { + /* system flag */ + if (flag == NULL || + strcasecmp(flag, "\\flagged") == 0) + ctx->flags |= MAIL_FLAGGED; + else if (strcasecmp(flag, "\\answered") == 0) + ctx->flags |= MAIL_ANSWERED; + else if (strcasecmp(flag, "\\deleted") == 0) + ctx->flags |= MAIL_DELETED; + else if (strcasecmp(flag, "\\seen") == 0) + ctx->flags |= MAIL_SEEN; + else if (strcasecmp(flag, "\\draft") == 0) + ctx->flags |= MAIL_DRAFT; + } + } + } + + if (ret < 0) + return flag_list->exec_status; + + *se_context = (void *)ctx; + return SIEVE_EXEC_OK; +} + +static int +seff_flags_read_context(const struct sieve_side_effect *seffect, + const struct sieve_runtime_env *renv, + sieve_size_t *address, void **se_context) +{ + int ret; + + T_BEGIN { + ret = seff_flags_do_read_context(seffect, renv, address, + se_context); + } T_END; + + return ret; +} + +/* Result verification */ + +static int +seff_flags_merge(const struct sieve_runtime_env *renv ATTR_UNUSED, + const struct sieve_action *action ATTR_UNUSED, + const struct sieve_side_effect *old_seffect ATTR_UNUSED, + const struct sieve_side_effect *new_seffect, + void **old_context) +{ + if (new_seffect != NULL) + *old_context = new_seffect->context; + return 1; +} + +/* Result printing */ + +static void +seff_flags_print(const struct sieve_side_effect *seffect, + const struct sieve_action *action ATTR_UNUSED, + const struct sieve_result_print_env *rpenv, + bool *keep ATTR_UNUSED) +{ + struct sieve_result *result = rpenv->result; + struct seff_flags_context *ctx = + (struct seff_flags_context *)seffect->context; + unsigned int i; + + if (ctx == NULL) { + ctx = seff_flags_get_implicit_context( + SIEVE_OBJECT_EXTENSION(seffect), result); + } + + if (ctx->flags != 0 || array_count(&ctx->keywords) > 0) { + T_BEGIN { + string_t *flags = t_str_new(128); + + if ((ctx->flags & MAIL_FLAGGED) > 0) + str_printfa(flags, " \\flagged"); + if ((ctx->flags & MAIL_ANSWERED) > 0) + str_printfa(flags, " \\answered"); + if ((ctx->flags & MAIL_DELETED) > 0) + str_printfa(flags, " \\deleted"); + if ((ctx->flags & MAIL_SEEN) > 0) + str_printfa(flags, " \\seen"); + if ((ctx->flags & MAIL_DRAFT) > 0) + str_printfa(flags, " \\draft"); + + for (i = 0; i < array_count(&ctx->keywords); i++) { + const char *const *keyword = + array_idx(&ctx->keywords, i); + str_printfa(flags, " %s", + str_sanitize(*keyword, 64)); + } + + sieve_result_seffect_printf(rpenv, "add IMAP flags:%s", + str_c(flags)); + } T_END; + } +} + +/* Result execution */ + +static int +seff_flags_pre_execute(const struct sieve_side_effect *seffect, + const struct sieve_action_exec_env *aenv, + void *tr_context, void **se_tr_context ATTR_UNUSED) +{ + struct seff_flags_context *ctx = seffect->context; + const char *const *keywords; + + if (ctx == NULL) { + ctx = seff_flags_get_implicit_context( + SIEVE_OBJECT_EXTENSION(seffect), aenv->result); + } + + (void)array_append_space(&ctx->keywords); + keywords = array_idx(&ctx->keywords, 0); + + sieve_act_store_add_flags(aenv, tr_context, keywords, ctx->flags); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/tst-hasflag.c b/pigeonhole/src/lib-sieve/plugins/imap4flags/tst-hasflag.c new file mode 100644 index 0000000..23f2acc --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/tst-hasflag.c @@ -0,0 +1,248 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-imap4flags-common.h" + +/* + * Hasflag test + * + * Syntax: + * hasflag [MATCH-TYPE] [COMPARATOR] [<variable-list: string-list>] + * <list-of-flags: string-list> + */ + +static bool tst_hasflag_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool tst_hasflag_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_hasflag_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + +const struct sieve_command_def tst_hasflag = { + .identifier = "hasflag", + .type = SCT_TEST, + .positional_args = -1, /* We check positional arguments ourselves */ + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_hasflag_registered, + .validate = tst_hasflag_validate, + .generate = tst_hasflag_generate +}; + +/* + * Hasflag operation + */ + +static bool tst_hasflag_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_hasflag_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def hasflag_operation = { + .mnemonic = "HASFLAG", + .ext_def = &imap4flags_extension, + .code = EXT_IMAP4FLAGS_OPERATION_HASFLAG, + .dump = tst_hasflag_operation_dump, + .execute = tst_hasflag_operation_execute +}; + +/* + * Optional arguments + */ + +enum tst_hasflag_optional { + OPT_VARIABLES = SIEVE_MATCH_OPT_LAST, +}; + +/* + * Tag registration + */ + +static bool tst_hasflag_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + + return TRUE; +} + +/* + * Validation + */ + +static bool tst_hasflag_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *vars = tst->first_positional; + struct sieve_ast_argument *keys = sieve_ast_argument_next(vars); + const struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + + if ( !ext_imap4flags_command_validate(valdtr, tst) ) + return FALSE; + + if ( keys == NULL ) { + keys = vars; + vars = NULL; + } else { + vars->argument->id_code = OPT_VARIABLES; + } + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate + (valdtr, tst, keys, &mcht_default, &cmp_default); +} + +/* + * Code generation + */ + +static bool tst_hasflag_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &hasflag_operation); + + /* Generate arguments */ + if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) + return FALSE; + + return TRUE; +} + +/* + * Code dump + */ + +static bool tst_hasflag_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "HASFLAG"); + sieve_code_descend(denv); + + /* Optional operands */ + + for (;;) { + bool opok = TRUE; + int opt; + + if ( (opt=sieve_match_opr_optional_dump(denv, address, &opt_code)) + < 0 ) + return FALSE; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_VARIABLES: + opok = sieve_opr_stringlist_dump(denv, address, "variables"); + break; + default: + return FALSE; + } + + if ( !opok ) return FALSE; + } + + return + sieve_opr_stringlist_dump(denv, address, "list of flags"); +} + +/* + * Interpretation + */ + +static int tst_hasflag_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_operation *op = renv->oprtn; + int opt_code = 0; + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + struct sieve_stringlist *flag_list, *variables_list, *value_list, *key_list; + int match, ret; + + /* + * Read operands + */ + + /* Optional operands */ + + variables_list = NULL; + for (;;) { + int opt; + + if ( (opt=sieve_match_opr_optional_read + (renv, address, &opt_code, &ret, &cmp, &mcht)) < 0 ) + return ret; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_VARIABLES: + ret = sieve_opr_stringlist_read + (renv, address, "variables-list", &variables_list); + break; + default: + sieve_runtime_trace_error(renv, "invalid optional operand"); + ret = SIEVE_EXEC_BIN_CORRUPT; + } + + if ( ret <= 0 ) return ret; + } + + /* Fixed operands */ + + if ( (ret=sieve_opr_stringlist_read(renv, address, "flag-list", &flag_list)) + <= 0 ) + return ret; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "hasflag test"); + + value_list = sieve_ext_imap4flags_get_flags + (renv, op->ext, variables_list); + + if ( sieve_match_type_is(&mcht, is_match_type) || + sieve_match_type_is(&mcht, contains_match_type) ) { + key_list = sieve_ext_imap4flags_get_flags + (renv, op->ext, flag_list); + } else { + key_list = flag_list; + } + + /* Perform match */ + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/include/Makefile.am b/pigeonhole/src/lib-sieve/plugins/include/Makefile.am new file mode 100644 index 0000000..5ce1599 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/Makefile.am @@ -0,0 +1,24 @@ +noinst_LTLIBRARIES = libsieve_ext_include.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) + +cmds = \ + cmd-include.c \ + cmd-return.c \ + cmd-global.c + +libsieve_ext_include_la_SOURCES = \ + $(cmds) \ + ext-include-common.c \ + ext-include-binary.c \ + ext-include-variables.c \ + ext-include.c + +noinst_HEADERS = \ + ext-include-common.h \ + ext-include-limits.h \ + ext-include-binary.h \ + ext-include-variables.h diff --git a/pigeonhole/src/lib-sieve/plugins/include/Makefile.in b/pigeonhole/src/lib-sieve/plugins/include/Makefile.in new file mode 100644 index 0000000..06f003f --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/Makefile.in @@ -0,0 +1,718 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/include +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_include_la_LIBADD = +am__objects_1 = cmd-include.lo cmd-return.lo cmd-global.lo +am_libsieve_ext_include_la_OBJECTS = $(am__objects_1) \ + ext-include-common.lo ext-include-binary.lo \ + ext-include-variables.lo ext-include.lo +libsieve_ext_include_la_OBJECTS = \ + $(am_libsieve_ext_include_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/cmd-global.Plo \ + ./$(DEPDIR)/cmd-include.Plo ./$(DEPDIR)/cmd-return.Plo \ + ./$(DEPDIR)/ext-include-binary.Plo \ + ./$(DEPDIR)/ext-include-common.Plo \ + ./$(DEPDIR)/ext-include-variables.Plo \ + ./$(DEPDIR)/ext-include.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_include_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_include_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_include.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) + +cmds = \ + cmd-include.c \ + cmd-return.c \ + cmd-global.c + +libsieve_ext_include_la_SOURCES = \ + $(cmds) \ + ext-include-common.c \ + ext-include-binary.c \ + ext-include-variables.c \ + ext-include.c + +noinst_HEADERS = \ + ext-include-common.h \ + ext-include-limits.h \ + ext-include-binary.h \ + ext-include-variables.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/include/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/include/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_include.la: $(libsieve_ext_include_la_OBJECTS) $(libsieve_ext_include_la_DEPENDENCIES) $(EXTRA_libsieve_ext_include_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_include_la_OBJECTS) $(libsieve_ext_include_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-global.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-include.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-return.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-include-binary.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-include-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-include-variables.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-include.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-global.Plo + -rm -f ./$(DEPDIR)/cmd-include.Plo + -rm -f ./$(DEPDIR)/cmd-return.Plo + -rm -f ./$(DEPDIR)/ext-include-binary.Plo + -rm -f ./$(DEPDIR)/ext-include-common.Plo + -rm -f ./$(DEPDIR)/ext-include-variables.Plo + -rm -f ./$(DEPDIR)/ext-include.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/cmd-global.Plo + -rm -f ./$(DEPDIR)/cmd-include.Plo + -rm -f ./$(DEPDIR)/cmd-return.Plo + -rm -f ./$(DEPDIR)/ext-include-binary.Plo + -rm -f ./$(DEPDIR)/ext-include-common.Plo + -rm -f ./$(DEPDIR)/ext-include-variables.Plo + -rm -f ./$(DEPDIR)/ext-include.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/include/cmd-global.c b/pigeonhole/src/lib-sieve/plugins/include/cmd-global.c new file mode 100644 index 0000000..0ef37eb --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/cmd-global.c @@ -0,0 +1,329 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "ext-include-common.h" +#include "ext-include-binary.h" +#include "ext-include-variables.h" + +/* + * Commands + */ + +static bool cmd_global_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_global_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + +const struct sieve_command_def cmd_global = { + .identifier = "global", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_global_validate, + .generate = cmd_global_generate, +}; + +/* DEPRICATED: + */ + +/* Import command + * + * Syntax + * import + */ +const struct sieve_command_def cmd_import = { + .identifier = "import", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_global_validate, + .generate = cmd_global_generate, +}; + +/* Export command + * + * Syntax + * export + */ +const struct sieve_command_def cmd_export = { + .identifier = "export", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_global_validate, + .generate = cmd_global_generate, +}; + +/* + * Operations + */ + +static bool opc_global_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int opc_global_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +/* Global operation */ + +const struct sieve_operation_def global_operation = { + .mnemonic = "GLOBAL", + .ext_def = &include_extension, + .code = EXT_INCLUDE_OPERATION_GLOBAL, + .dump = opc_global_dump, + .execute = opc_global_execute +}; + +/* + * Validation + */ + +static inline struct sieve_argument *_create_variable_argument +(struct sieve_command *cmd, struct sieve_variable *var) +{ + struct sieve_argument *argument = sieve_argument_create + (cmd->ast_node->ast, NULL, cmd->ext, 0); + + argument->data = (void *) var; + + return argument; +} + +static bool cmd_global_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct sieve_ast_argument *arg = cmd->first_positional; + struct sieve_command *prev = sieve_command_prev(cmd); + + /* DEPRECATED: Check valid command placement */ + if ( !sieve_command_is(cmd, cmd_global) ) { + if ( !sieve_command_is_toplevel(cmd) || + ( !sieve_command_is_first(cmd) && prev != NULL && + !sieve_command_is(prev, cmd_require) && + !sieve_command_is(prev, cmd_import) && + !sieve_command_is(prev, cmd_export) ) ) { + sieve_command_validate_error(valdtr, cmd, + "the DEPRECATED %s command can only be placed at top level " + "at the beginning of the file after any require or " + "import/export commands", + sieve_command_identifier(cmd)); + return FALSE; + } + } + + /* Check for use of variables extension */ + if ( !ext_include_validator_have_variables(this_ext, valdtr) ) { + sieve_command_validate_error(valdtr, cmd, + "%s command requires that variables extension is active", + sieve_command_identifier(cmd)); + return FALSE; + } + + /* Register global variable */ + if ( sieve_ast_argument_type(arg) == SAAT_STRING ) { + /* Single string */ + const char *identifier = sieve_ast_argument_strc(arg); + struct sieve_variable *var; + + if ( (var=ext_include_variable_import_global + (valdtr, cmd, identifier)) == NULL ) + return FALSE; + + arg->argument = _create_variable_argument(cmd, var); + + } else if ( sieve_ast_argument_type(arg) == SAAT_STRING_LIST ) { + /* String list */ + struct sieve_ast_argument *stritem = sieve_ast_strlist_first(arg); + + while ( stritem != NULL ) { + const char *identifier = sieve_ast_argument_strc(stritem); + struct sieve_variable *var; + + if ( (var=ext_include_variable_import_global + (valdtr, cmd, identifier)) == NULL ) + return FALSE; + + stritem->argument = _create_variable_argument(cmd, var); + + stritem = sieve_ast_strlist_next(stritem); + } + } else { + /* Something else */ + sieve_argument_validate_error(valdtr, arg, + "the %s command accepts a single string or string list argument, " + "but %s was found", sieve_command_identifier(cmd), + sieve_ast_argument_name(arg)); + return FALSE; + } + + /* Join global commands with predecessors if possible */ + if ( sieve_commands_equal(prev, cmd) ) { + /* Join this command's string list with the previous one */ + prev->first_positional = sieve_ast_stringlist_join + (prev->first_positional, cmd->first_positional); + + if ( prev->first_positional == NULL ) { + /* Not going to happen unless MAXINT stringlist items are specified */ + sieve_command_validate_error(valdtr, cmd, + "compiler reached AST limit (script too complex)"); + return FALSE; + } + + /* Detach this command node */ + sieve_ast_node_detach(cmd->ast_node); + } + + return TRUE; +} + +/* + * Code generation + */ + +static bool cmd_global_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + sieve_operation_emit(cgenv->sblock, cmd->ext, &global_operation); + + if ( sieve_ast_argument_type(arg) == SAAT_STRING ) { + /* Single string */ + struct sieve_variable *var = (struct sieve_variable *) arg->argument->data; + + (void)sieve_binary_emit_unsigned(cgenv->sblock, 1); + (void)sieve_binary_emit_unsigned(cgenv->sblock, var->index); + + } else if ( sieve_ast_argument_type(arg) == SAAT_STRING_LIST ) { + /* String list */ + struct sieve_ast_argument *stritem = sieve_ast_strlist_first(arg); + + (void)sieve_binary_emit_unsigned + (cgenv->sblock, sieve_ast_strlist_count(arg)); + + while ( stritem != NULL ) { + struct sieve_variable *var = + (struct sieve_variable *) stritem->argument->data; + + (void)sieve_binary_emit_unsigned(cgenv->sblock, var->index); + + stritem = sieve_ast_strlist_next(stritem); + } + } else { + i_unreached(); + } + + return TRUE; +} + +/* + * Code dump + */ + +static bool opc_global_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + const struct sieve_extension *this_ext = denv->oprtn->ext; + unsigned int count, i, var_count; + struct sieve_variable_scope_binary *global_vars; + struct sieve_variable_scope *global_scope; + struct sieve_variable * const *vars; + + if ( !sieve_binary_read_unsigned(denv->sblock, address, &count) ) + return FALSE; + + sieve_code_dumpf(denv, "GLOBAL (count: %u):", count); + + global_vars = ext_include_binary_get_global_scope(this_ext, denv->sbin); + global_scope = sieve_variable_scope_binary_get(global_vars); + vars = sieve_variable_scope_get_variables(global_scope, &var_count); + + sieve_code_descend(denv); + + for ( i = 0; i < count; i++ ) { + unsigned int index; + + sieve_code_mark(denv); + if ( !sieve_binary_read_unsigned(denv->sblock, address, &index) || + index >= var_count ) + return FALSE; + + sieve_code_dumpf(denv, "%d: VAR[%d]: '%s'", i, index, vars[index]->identifier); + } + + return TRUE; +} + +/* + * Execution + */ + +static int opc_global_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct sieve_variable_scope_binary *global_vars; + struct sieve_variable_scope *global_scope; + struct sieve_variable_storage *storage; + struct sieve_variable * const *vars; + unsigned int var_count, count, i; + + if ( !sieve_binary_read_unsigned(renv->sblock, address, &count) ) { + sieve_runtime_trace_error(renv, + "global: count operand invalid"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + global_vars = ext_include_binary_get_global_scope(this_ext, renv->sbin); + global_scope = sieve_variable_scope_binary_get(global_vars); + vars = sieve_variable_scope_get_variables(global_scope, &var_count); + storage = ext_include_interpreter_get_global_variables + (this_ext, renv->interp); + + for ( i = 0; i < count; i++ ) { + unsigned int index; + + if ( !sieve_binary_read_unsigned(renv->sblock, address, &index) ) { + sieve_runtime_trace_error(renv, + "global: variable index operand invalid"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( index >= var_count ) { + sieve_runtime_trace_error(renv, + "global: variable index %u is invalid in global storage (> %u)", + index, var_count); + return SIEVE_EXEC_BIN_CORRUPT; + } + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "global: exporting variable '%s' [gvid: %u, vid: %u]", + vars[index]->identifier, i, index); + + /* Make sure variable is initialized (export) */ + (void)sieve_variable_get_modifiable(storage, index, NULL); + } + + return SIEVE_EXEC_OK; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/include/cmd-include.c b/pigeonhole/src/lib-sieve/plugins/include/cmd-include.c new file mode 100644 index 0000000..92aefb4 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/cmd-include.c @@ -0,0 +1,406 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-script.h" +#include "sieve-storage.h" +#include "sieve-ast.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-binary.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-include-common.h" +#include "ext-include-binary.h" + +/* + * Include command + * + * Syntax: + * include [LOCATION] [":once"] [":optional"] <value: string> + * + * [LOCATION]: + * ":personal" / ":global" + */ + +static bool cmd_include_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool cmd_include_pre_validate + (struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command *cmd); +static bool cmd_include_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_include_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def cmd_include = { + .identifier = "include", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_include_registered, + .pre_validate = cmd_include_pre_validate, + .validate = cmd_include_validate, + .generate = cmd_include_generate +}; + +/* + * Include operation + */ + +static bool opc_include_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int opc_include_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def include_operation = { + .mnemonic = "include", + .ext_def = &include_extension, + .code = EXT_INCLUDE_OPERATION_INCLUDE, + .dump = opc_include_dump, + .execute = opc_include_execute +}; + +/* + * Context structures + */ + +struct cmd_include_context_data { + enum ext_include_script_location location; + + struct sieve_script *script; + enum ext_include_flags flags; + + bool location_assigned:1; +}; + +/* + * Tagged arguments + */ + +static bool cmd_include_validate_location_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +static const struct sieve_argument_def include_personal_tag = { + .identifier = "personal", + .validate = cmd_include_validate_location_tag +}; + +static const struct sieve_argument_def include_global_tag = { + .identifier = "global", + .validate = cmd_include_validate_location_tag +}; + +static bool cmd_include_validate_boolean_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +static const struct sieve_argument_def include_once_tag = { + .identifier = "once", + .validate = cmd_include_validate_boolean_tag +}; + +static const struct sieve_argument_def include_optional_tag = { + .identifier = "optional", + .validate = cmd_include_validate_boolean_tag +}; + +/* + * Tag validation + */ + +static bool cmd_include_validate_location_tag +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct cmd_include_context_data *ctx_data = + (struct cmd_include_context_data *) cmd->data; + + if ( ctx_data->location_assigned) { + sieve_argument_validate_error(valdtr, *arg, + "include: cannot use location tags ':personal' and ':global' " + "multiple times"); + return FALSE; + } + + if ( sieve_argument_is(*arg, include_personal_tag) ) + ctx_data->location = EXT_INCLUDE_LOCATION_PERSONAL; + else if ( sieve_argument_is(*arg, include_global_tag) ) + ctx_data->location = EXT_INCLUDE_LOCATION_GLOBAL; + else + return FALSE; + + ctx_data->location_assigned = TRUE; + + /* Delete this tag (for now) */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + return TRUE; +} + +static bool cmd_include_validate_boolean_tag +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct cmd_include_context_data *ctx_data = + (struct cmd_include_context_data *) cmd->data; + + if ( sieve_argument_is(*arg, include_once_tag) ) + ctx_data->flags |= EXT_INCLUDE_FLAG_ONCE; + else + ctx_data->flags |= EXT_INCLUDE_FLAG_OPTIONAL; + + /* Delete this tag (for now) */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + return TRUE; +} + +/* + * Command registration + */ + +static bool cmd_include_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag(valdtr, cmd_reg, ext, &include_personal_tag, 0); + sieve_validator_register_tag(valdtr, cmd_reg, ext, &include_global_tag, 0); + sieve_validator_register_tag(valdtr, cmd_reg, ext, &include_once_tag, 0); + sieve_validator_register_tag(valdtr, cmd_reg, ext, &include_optional_tag, 0); + + return TRUE; +} + +/* + * Command validation + */ + +static bool cmd_include_pre_validate +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command *cmd) +{ + struct cmd_include_context_data *ctx_data; + + /* Assign context */ + ctx_data = p_new(sieve_command_pool(cmd), struct cmd_include_context_data, 1); + ctx_data->location = EXT_INCLUDE_LOCATION_PERSONAL; + cmd->data = ctx_data; + + return TRUE; +} + +static bool cmd_include_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct sieve_ast_argument *arg = cmd->first_positional; + struct cmd_include_context_data *ctx_data = + (struct cmd_include_context_data *) cmd->data; + struct sieve_storage *storage; + struct sieve_script *script; + const char *script_name; + enum sieve_error error = SIEVE_ERROR_NONE; + int ret; + + /* Check argument */ + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "value", 1, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) ) + return FALSE; + + /* + * Variables are not allowed. + */ + if ( !sieve_argument_is_string_literal(arg) ) { + sieve_argument_validate_error(valdtr, arg, + "the include command requires a constant string for its value argument"); + return FALSE; + } + + /* Find the script */ + + script_name = sieve_ast_argument_strc(arg); + + if ( !sieve_script_name_is_valid(script_name) ) { + sieve_argument_validate_error(valdtr, arg, + "include: invalid script name '%s'", + str_sanitize(script_name, 80)); + return FALSE; + } + + storage = ext_include_get_script_storage + (this_ext, ctx_data->location, script_name, &error); + if ( storage == NULL ) { + // FIXME: handle ':optional' in this case + if (error == SIEVE_ERROR_NOT_FOUND) { + sieve_argument_validate_error(valdtr, arg, + "include: %s location for included script `%s' is unavailable " + "(contact system administrator for more information)", + ext_include_script_location_name(ctx_data->location), + str_sanitize(script_name, 80)); + } else { + sieve_argument_validate_error(valdtr, arg, + "include: failed to access %s location for included script `%s' " + "(contact system administrator for more information)", + ext_include_script_location_name(ctx_data->location), + str_sanitize(script_name, 80)); + } + return FALSE; + } + + /* Create script object */ + script = sieve_storage_get_script + (storage, script_name, &error); + if ( script == NULL ) + return FALSE; + + ret = sieve_script_open(script, &error); + if ( ret < 0 ) { + if ( error != SIEVE_ERROR_NOT_FOUND ) { + sieve_argument_validate_error(valdtr, arg, + "failed to access included %s script '%s': %s", + ext_include_script_location_name(ctx_data->location), + str_sanitize(script_name, 80), + sieve_script_get_last_error_lcase(script)); + sieve_script_unref(&script); + return FALSE; + + /* Not found */ + } else { + enum sieve_compile_flags cpflags = + sieve_validator_compile_flags(valdtr); + + if ( (ctx_data->flags & EXT_INCLUDE_FLAG_OPTIONAL) != 0 ) { + /* :optional */ + + } else if ( (cpflags & SIEVE_COMPILE_FLAG_UPLOADED) != 0 ) { + /* Script is being uploaded */ + sieve_argument_validate_warning(valdtr, arg, + "included %s script '%s' does not exist (ignored during upload)", + ext_include_script_location_name(ctx_data->location), + str_sanitize(script_name, 80)); + ctx_data->flags |= EXT_INCLUDE_FLAG_MISSING_AT_UPLOAD; + + } else { + /* Should have existed */ + sieve_argument_validate_error(valdtr, arg, + "included %s script '%s' does not exist", + ext_include_script_location_name(ctx_data->location), + str_sanitize(script_name, 80)); + sieve_script_unref(&script); + return FALSE; + } + } + } + + ext_include_ast_link_included_script(cmd->ext, cmd->ast_node->ast, script); + ctx_data->script = script; + + (void)sieve_ast_arguments_detach(arg, 1); + return TRUE; +} + +/* + * Code Generation + */ + +static bool cmd_include_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + struct cmd_include_context_data *ctx_data = + (struct cmd_include_context_data *) cmd->data; + const struct ext_include_script_info *included; + int ret; + + /* Compile (if necessary) and include the script into the binary. + * This yields the id of the binary block containing the compiled byte code. + */ + if ( (ret=ext_include_generate_include + (cgenv, cmd, ctx_data->location, ctx_data->flags, ctx_data->script, + &included)) < 0 ) + return FALSE; + + if ( ret > 0 ) { + (void)sieve_operation_emit(cgenv->sblock, cmd->ext, &include_operation); + (void)sieve_binary_emit_unsigned(cgenv->sblock, included->id); + (void)sieve_binary_emit_byte(cgenv->sblock, ctx_data->flags); + } + + return TRUE; +} + +/* + * Code dump + */ + +static bool opc_include_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + const struct ext_include_script_info *included; + struct ext_include_binary_context *binctx; + unsigned int include_id, flags; + + sieve_code_dumpf(denv, "INCLUDE:"); + + sieve_code_mark(denv); + if ( !sieve_binary_read_unsigned(denv->sblock, address, &include_id) ) + return FALSE; + + if ( !sieve_binary_read_byte(denv->sblock, address, &flags) ) + return FALSE; + + binctx = ext_include_binary_get_context(denv->oprtn->ext, denv->sbin); + included = ext_include_binary_script_get_included(binctx, include_id); + if ( included == NULL ) + return FALSE; + + sieve_code_descend(denv); + sieve_code_dumpf(denv, "script: `%s' from %s %s%s[ID: %d, BLOCK: %d]", + sieve_script_name(included->script), sieve_script_location(included->script), + ((flags & EXT_INCLUDE_FLAG_ONCE) != 0 ? "(once) " : ""), + ((flags & EXT_INCLUDE_FLAG_OPTIONAL) != 0 ? "(optional) " : ""), + include_id, sieve_binary_block_get_id(included->block)); + + return TRUE; +} + +/* + * Execution + */ + +static int opc_include_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + unsigned int include_id, flags; + + if ( !sieve_binary_read_unsigned(renv->sblock, address, &include_id) ) { + sieve_runtime_trace_error(renv, "invalid include-id operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( !sieve_binary_read_unsigned(renv->sblock, address, &flags) ) { + sieve_runtime_trace_error(renv, "invalid flags operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + return ext_include_execute_include + (renv, include_id, (enum ext_include_flags)flags); +} + + + + + diff --git a/pigeonhole/src/lib-sieve/plugins/include/cmd-return.c b/pigeonhole/src/lib-sieve/plugins/include/cmd-return.c new file mode 100644 index 0000000..65a156d --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/cmd-return.c @@ -0,0 +1,71 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-include-common.h" + +/* + * Return command + * + * Syntax + * return + */ + +static bool cmd_return_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + +const struct sieve_command_def cmd_return = { + .identifier = "return", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .generate = cmd_return_generate +}; + +/* + * Return operation + */ + +static int opc_return_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def return_operation = { + .mnemonic = "RETURN", + .ext_def = &include_extension, + .code = EXT_INCLUDE_OPERATION_RETURN, + .execute = opc_return_execute +}; + +/* + * Code generation + */ + +static bool cmd_return_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &return_operation); + + return TRUE; +} + +/* + * Execution + */ + +static int opc_return_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED) +{ + ext_include_execute_return(renv); + return SIEVE_EXEC_OK; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/include/ext-include-binary.c b/pigeonhole/src/lib-sieve/plugins/include/ext-include-binary.c new file mode 100644 index 0000000..3711c30 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/ext-include-binary.c @@ -0,0 +1,492 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-script.h" +#include "sieve-storage.h" +#include "sieve-binary.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "ext-include-common.h" +#include "ext-include-limits.h" +#include "ext-include-variables.h" +#include "ext-include-binary.h" + +/* + * Forward declarations + */ + +static bool ext_include_binary_pre_save + (const struct sieve_extension *ext, struct sieve_binary *sbin, + void *context, enum sieve_error *error_r); +static bool ext_include_binary_open + (const struct sieve_extension *ext, struct sieve_binary *sbin, + void *context); +static bool ext_include_binary_up_to_date + (const struct sieve_extension *ext, struct sieve_binary *sbin, + void *context, enum sieve_compile_flags cpflags); +static void ext_include_binary_free + (const struct sieve_extension *ext, struct sieve_binary *sbin, + void *context); + +/* + * Binary include extension + */ + +const struct sieve_binary_extension include_binary_ext = { + .extension = &include_extension, + .binary_pre_save = ext_include_binary_pre_save, + .binary_open = ext_include_binary_open, + .binary_free = ext_include_binary_free, + .binary_up_to_date = ext_include_binary_up_to_date +}; + +/* + * Binary context management + */ + +struct ext_include_binary_context { + struct sieve_binary *binary; + struct sieve_binary_block *dependency_block; + + HASH_TABLE(struct sieve_script *, + struct ext_include_script_info *) included_scripts; + ARRAY(struct ext_include_script_info *) include_index; + + struct sieve_variable_scope_binary *global_vars; + + bool outdated:1; +}; + +static struct ext_include_binary_context *ext_include_binary_create_context +(const struct sieve_extension *this_ext, struct sieve_binary *sbin) +{ + pool_t pool = sieve_binary_pool(sbin); + + struct ext_include_binary_context *ctx = + p_new(pool, struct ext_include_binary_context, 1); + + ctx->binary = sbin; + hash_table_create(&ctx->included_scripts, pool, 0, + sieve_script_hash, sieve_script_cmp); + p_array_init(&ctx->include_index, pool, 128); + + sieve_binary_extension_set(sbin, this_ext, &include_binary_ext, ctx); + + return ctx; +} + +struct ext_include_binary_context *ext_include_binary_get_context +(const struct sieve_extension *this_ext, struct sieve_binary *sbin) +{ + struct ext_include_binary_context *ctx = (struct ext_include_binary_context *) + sieve_binary_extension_get_context(sbin, this_ext); + + if ( ctx == NULL ) + ctx = ext_include_binary_create_context(this_ext, sbin); + + return ctx; +} + +struct ext_include_binary_context *ext_include_binary_init +(const struct sieve_extension *this_ext, struct sieve_binary *sbin, + struct sieve_ast *ast) +{ + struct ext_include_ast_context *ast_ctx = + ext_include_get_ast_context(this_ext, ast); + struct ext_include_binary_context *ctx; + + /* Get/create our context from the binary we are working on */ + ctx = ext_include_binary_get_context(this_ext, sbin); + + /* Create dependency block */ + if ( ctx->dependency_block == 0 ) + ctx->dependency_block = + sieve_binary_extension_create_block(sbin, this_ext); + + if ( ctx->global_vars == NULL ) { + ctx->global_vars = + sieve_variable_scope_binary_create(ast_ctx->global_vars); + sieve_variable_scope_binary_ref(ctx->global_vars); + } + + return ctx; +} + +/* + * Script inclusion + */ + +struct ext_include_script_info *ext_include_binary_script_include +(struct ext_include_binary_context *binctx, + enum ext_include_script_location location, enum ext_include_flags flags, + struct sieve_script *script, struct sieve_binary_block *inc_block) +{ + pool_t pool = sieve_binary_pool(binctx->binary); + struct ext_include_script_info *incscript; + + incscript = p_new(pool, struct ext_include_script_info, 1); + incscript->id = array_count(&binctx->include_index)+1; + incscript->location = location; + incscript->flags = flags; + incscript->script = script; + incscript->block = inc_block; + + /* Unreferenced on binary_free */ + sieve_script_ref(script); + + hash_table_insert(binctx->included_scripts, script, incscript); + array_append(&binctx->include_index, &incscript, 1); + + return incscript; +} + +struct ext_include_script_info *ext_include_binary_script_get_include_info +(struct ext_include_binary_context *binctx, struct sieve_script *script) +{ + struct ext_include_script_info *incscript = + hash_table_lookup(binctx->included_scripts, script); + + return incscript; +} + +const struct ext_include_script_info *ext_include_binary_script_get_included +(struct ext_include_binary_context *binctx, unsigned int include_id) +{ + if ( include_id > 0 && + (include_id - 1) < array_count(&binctx->include_index) ) { + struct ext_include_script_info *const *sinfo = + array_idx(&binctx->include_index, include_id - 1); + + return *sinfo; + } + + return NULL; +} + +const struct ext_include_script_info *ext_include_binary_script_get +(struct ext_include_binary_context *binctx, struct sieve_script *script) +{ + return hash_table_lookup(binctx->included_scripts, script); +} + +unsigned int ext_include_binary_script_get_count +(struct ext_include_binary_context *binctx) +{ + return array_count(&binctx->include_index); +} + +/* + * Variables + */ + +struct sieve_variable_scope_binary *ext_include_binary_get_global_scope +(const struct sieve_extension *this_ext, struct sieve_binary *sbin) +{ + struct ext_include_binary_context *binctx = + ext_include_binary_get_context(this_ext, sbin); + + return binctx->global_vars; +} + +/* + * Binary extension + */ + +static bool ext_include_binary_pre_save +(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_binary *sbin ATTR_UNUSED, void *context, + enum sieve_error *error_r) +{ + struct ext_include_binary_context *binctx = + (struct ext_include_binary_context *) context; + struct ext_include_script_info *const *scripts; + struct sieve_binary_block *sblock = binctx->dependency_block; + unsigned int script_count, i; + bool result = TRUE; + + sieve_binary_block_clear(sblock); + + scripts = array_get(&binctx->include_index, &script_count); + + sieve_binary_emit_unsigned(sblock, script_count); + + for ( i = 0; i < script_count; i++ ) { + struct ext_include_script_info *incscript = scripts[i]; + + if ( incscript->block != NULL ) { + sieve_binary_emit_unsigned + (sblock, sieve_binary_block_get_id(incscript->block)); + } else { + sieve_binary_emit_unsigned(sblock, 0); + } + sieve_binary_emit_byte(sblock, incscript->location); + sieve_binary_emit_cstring(sblock, sieve_script_name(incscript->script)); + sieve_binary_emit_byte(sblock, incscript->flags); + sieve_script_binary_write_metadata(incscript->script, sblock); + } + + result = ext_include_variables_save(sblock, binctx->global_vars, error_r); + + return result; +} + +static bool ext_include_binary_open +(const struct sieve_extension *ext, struct sieve_binary *sbin, void *context) +{ + struct sieve_instance *svinst = ext->svinst; + struct ext_include_context *ext_ctx = + (struct ext_include_context *)ext->context; + struct ext_include_binary_context *binctx = + (struct ext_include_binary_context *) context; + struct sieve_binary_block *sblock; + unsigned int depcount, i, block_id; + sieve_size_t offset; + + sblock = sieve_binary_extension_get_block(sbin, ext); + block_id = sieve_binary_block_get_id(sblock); + + offset = 0; + + if ( !sieve_binary_read_unsigned(sblock, &offset, &depcount) ) { + e_error(svinst->event, + "include: failed to read include count " + "for dependency block %d of binary %s", block_id, + sieve_binary_path(sbin)); + return FALSE; + } + + /* Check include limit */ + if ( depcount > ext_ctx->max_includes ) { + e_error(svinst->event, + "include: binary %s includes too many scripts (%u > %u)", + sieve_binary_path(sbin), depcount, ext_ctx->max_includes); + return FALSE; + } + + /* Read dependencies */ + for ( i = 0; i < depcount; i++ ) { + unsigned int inc_block_id; + struct sieve_binary_block *inc_block = NULL; + unsigned int location, flags; + string_t *script_name; + struct sieve_storage *storage; + struct sieve_script *script; + enum sieve_error error; + int ret; + + if ( + !sieve_binary_read_unsigned(sblock, &offset, &inc_block_id) || + !sieve_binary_read_byte(sblock, &offset, &location) || + !sieve_binary_read_string(sblock, &offset, &script_name) || + !sieve_binary_read_byte(sblock, &offset, &flags) ) { + /* Binary is corrupt, recompile */ + e_error(svinst->event, + "include: failed to read included script " + "from dependency block %d of binary %s", + block_id, sieve_binary_path(sbin)); + return FALSE; + } + + if ( inc_block_id != 0 && + (inc_block=sieve_binary_block_get(sbin, inc_block_id)) == NULL ) { + e_error(svinst->event, + "include: failed to find block %d for included script " + "from dependency block %d of binary %s", + inc_block_id, block_id, + sieve_binary_path(sbin)); + return FALSE; + } + + if ( location >= EXT_INCLUDE_LOCATION_INVALID ) { + /* Binary is corrupt, recompile */ + e_error(svinst->event, + "include: dependency block %d of binary %s " + "uses invalid script location (id %d)", + block_id, sieve_binary_path(sbin), location); + return FALSE; + } + + /* Can we find the script dependency ? */ + storage = ext_include_get_script_storage + (ext, location, str_c(script_name), &error); + if ( storage == NULL ) { + /* No, recompile */ + // FIXME: handle ':optional' in this case + return FALSE; + } + + /* Can we open the script dependency ? */ + script = sieve_storage_get_script + (storage, str_c(script_name), &error); + if ( script == NULL ) { + /* No, recompile */ + return FALSE; + } + if ( sieve_script_open(script, &error) < 0 ) { + if ( error != SIEVE_ERROR_NOT_FOUND ) { + /* No, recompile */ + return FALSE; + } + + if ( (flags & EXT_INCLUDE_FLAG_OPTIONAL) == 0 ) { + /* Not supposed to be missing, recompile */ + if ( svinst->debug ) { + e_debug(svinst->event, "include: " + "script '%s' included in binary %s is missing, " + "so recompile", + str_c(script_name), + sieve_binary_path(sbin)); + } + return FALSE; + } + + } else if (inc_block == NULL) { + /* Script exists, but it is missing from the binary, recompile no matter + * what. + */ + if ( svinst->debug ) { + e_debug(svinst->event, "include: " + "script '%s' is missing in binary %s, but is now available, " + "so recompile", str_c(script_name), sieve_binary_path(sbin)); + } + sieve_script_unref(&script); + return FALSE; + } + + /* Can we read script metadata ? */ + if ( (ret=sieve_script_binary_read_metadata + (script, sblock, &offset)) < 0 ) { + /* Binary is corrupt, recompile */ + e_error(svinst->event, "include: " + "dependency block %d of binary %s " + "contains invalid script metadata for script %s", + block_id, sieve_binary_path(sbin), + sieve_script_location(script)); + sieve_script_unref(&script); + return FALSE; + } + + if ( ret == 0 ) + binctx->outdated = TRUE; + + (void)ext_include_binary_script_include + (binctx, location, flags, script, inc_block); + + sieve_script_unref(&script); + } + + if ( !ext_include_variables_load + (ext, sblock, &offset, &binctx->global_vars) ) + return FALSE; + + return TRUE; +} + +static bool ext_include_binary_up_to_date +(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_binary *sbin ATTR_UNUSED, void *context, + enum sieve_compile_flags cpflags ATTR_UNUSED) +{ + struct ext_include_binary_context *binctx = + (struct ext_include_binary_context *) context; + + return !binctx->outdated; +} + +static void ext_include_binary_free +(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_binary *sbin ATTR_UNUSED, void *context) +{ + struct ext_include_binary_context *binctx = + (struct ext_include_binary_context *) context; + struct hash_iterate_context *hctx; + struct sieve_script *script; + struct ext_include_script_info *incscript; + + /* Release references to all included script objects */ + hctx = hash_table_iterate_init(binctx->included_scripts); + while ( hash_table_iterate + (hctx, binctx->included_scripts, &script, &incscript) ) + sieve_script_unref(&incscript->script); + hash_table_iterate_deinit(&hctx); + + hash_table_destroy(&binctx->included_scripts); + + if ( binctx->global_vars != NULL ) + sieve_variable_scope_binary_unref(&binctx->global_vars); +} + +/* + * Dumping the binary + */ + +bool ext_include_binary_dump +(const struct sieve_extension *ext, struct sieve_dumptime_env *denv) +{ + struct sieve_binary *sbin = denv->sbin; + struct ext_include_binary_context *binctx = + ext_include_binary_get_context(ext, sbin); + struct hash_iterate_context *hctx; + struct sieve_script *script; + struct ext_include_script_info *incscript; + + if ( !ext_include_variables_dump(denv, binctx->global_vars) ) + return FALSE; + + hctx = hash_table_iterate_init(binctx->included_scripts); + while ( hash_table_iterate + (hctx, binctx->included_scripts, &script, &incscript) ) { + + if ( incscript->block == NULL ) { + sieve_binary_dump_sectionf(denv, "Included %s script '%s' (MISSING)", + ext_include_script_location_name(incscript->location), + sieve_script_name(incscript->script)); + + } else { + unsigned int block_id = sieve_binary_block_get_id(incscript->block); + + sieve_binary_dump_sectionf(denv, "Included %s script '%s' (block: %d)", + ext_include_script_location_name(incscript->location), + sieve_script_name(incscript->script), block_id); + + denv->sblock = incscript->block; + denv->cdumper = sieve_code_dumper_create(denv); + + if ( denv->cdumper == NULL ) + return FALSE; + + sieve_code_dumper_run(denv->cdumper); + sieve_code_dumper_free(&(denv->cdumper)); + } + } + hash_table_iterate_deinit(&hctx); + + return TRUE; +} + +bool ext_include_code_dump +(const struct sieve_extension *ext, const struct sieve_dumptime_env *denv, + sieve_size_t *address ATTR_UNUSED) +{ + struct sieve_binary *sbin = denv->sbin; + struct ext_include_binary_context *binctx = + ext_include_binary_get_context(ext, sbin); + struct ext_include_context *ectx = ext_include_get_context(ext); + + sieve_ext_variables_dump_set_scope + (ectx->var_ext, denv, ext, + sieve_variable_scope_binary_get(binctx->global_vars)); + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/include/ext-include-binary.h b/pigeonhole/src/lib-sieve/plugins/include/ext-include-binary.h new file mode 100644 index 0000000..066df2f --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/ext-include-binary.h @@ -0,0 +1,64 @@ +#ifndef EXT_INCLUDE_BINARY_H +#define EXT_INCLUDE_BINARY_H + +#include "sieve-common.h" + +/* + * Binary context management + */ + +struct ext_include_binary_context; + +struct ext_include_binary_context *ext_include_binary_init + (const struct sieve_extension *this_ext, struct sieve_binary *sbin, + struct sieve_ast *ast); +struct ext_include_binary_context *ext_include_binary_get_context + (const struct sieve_extension *this_ext, struct sieve_binary *sbin); + +/* + * Variables + */ + +struct sieve_variable_scope_binary *ext_include_binary_get_global_scope + (const struct sieve_extension *this_ext, struct sieve_binary *sbin); + +/* + * Including scripts + */ + +struct ext_include_script_info { + unsigned int id; + + struct sieve_script *script; + enum ext_include_flags flags; + enum ext_include_script_location location; + + struct sieve_binary_block *block; +}; + +struct ext_include_script_info *ext_include_binary_script_include + (struct ext_include_binary_context *binctx, + enum ext_include_script_location location, enum ext_include_flags flags, + struct sieve_script *script, struct sieve_binary_block *inc_block); +struct ext_include_script_info *ext_include_binary_script_get_include_info + (struct ext_include_binary_context *binctx, struct sieve_script *script); + +const struct ext_include_script_info *ext_include_binary_script_get_included + (struct ext_include_binary_context *binctx, unsigned int include_id); +const struct ext_include_script_info *ext_include_binary_script_get + (struct ext_include_binary_context *binctx, struct sieve_script *script); +unsigned int ext_include_binary_script_get_count + (struct ext_include_binary_context *binctx); + +/* + * Dumping the binary + */ + +bool ext_include_binary_dump + (const struct sieve_extension *ext, struct sieve_dumptime_env *denv); +bool ext_include_code_dump + (const struct sieve_extension *ext, const struct sieve_dumptime_env *denv, + sieve_size_t *address ATTR_UNUSED); + +#endif + diff --git a/pigeonhole/src/lib-sieve/plugins/include/ext-include-common.c b/pigeonhole/src/lib-sieve/plugins/include/ext-include-common.c new file mode 100644 index 0000000..7af3f00 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/ext-include-common.c @@ -0,0 +1,892 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "str-sanitize.h" +#include "home-expand.h" + +#include "sieve-common.h" +#include "sieve-settings.h" +#include "sieve-error.h" +#include "sieve-script.h" +#include "sieve-storage.h" +#include "sieve-ast.h" +#include "sieve-binary.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-include-common.h" +#include "ext-include-limits.h" +#include "ext-include-binary.h" +#include "ext-include-variables.h" + + +/* + * Forward declarations + */ + +/* Generator context */ + +struct ext_include_generator_context { + unsigned int nesting_depth; + struct sieve_script *script; + struct ext_include_generator_context *parent; +}; + +static inline struct ext_include_generator_context * +ext_include_get_generator_context(const struct sieve_extension *ext_this, + struct sieve_generator *gentr); + +/* Interpreter context */ + +struct ext_include_interpreter_global { + ARRAY(struct sieve_script *) included_scripts; + + struct sieve_variable_scope_binary *var_scope; + struct sieve_variable_storage *var_storage; +}; + +struct ext_include_interpreter_context { + struct ext_include_interpreter_context *parent; + struct ext_include_interpreter_global *global; + + struct sieve_interpreter *interp; + pool_t pool; + + unsigned int nesting_depth; + + struct sieve_script *script; + const struct ext_include_script_info *script_info; + + const struct ext_include_script_info *include; + bool returned; +}; + +/* + * Extension configuration + */ + +/* Extension hooks */ + +bool ext_include_load(const struct sieve_extension *ext, void **context) +{ + struct sieve_instance *svinst = ext->svinst; + struct ext_include_context *ctx; + const char *location; + unsigned long long int uint_setting; + + if (*context != NULL) + ext_include_unload(ext); + + ctx = i_new(struct ext_include_context, 1); + + /* Get location for :global scripts */ + location = sieve_setting_get(svinst, "sieve_global"); + if (location == NULL) + location = sieve_setting_get(svinst, "sieve_global_dir"); + + if (location == NULL) { + e_debug(svinst->event, "include: " + "sieve_global is not set; " + "it is currently not possible to include `:global' scripts."); + } + + ctx->global_location = i_strdup(location); + + /* Get limits */ + ctx->max_nesting_depth = EXT_INCLUDE_DEFAULT_MAX_NESTING_DEPTH; + ctx->max_includes = EXT_INCLUDE_DEFAULT_MAX_INCLUDES; + + if (sieve_setting_get_uint_value( + svinst, "sieve_include_max_nesting_depth", &uint_setting)) + ctx->max_nesting_depth = (unsigned int)uint_setting; + if (sieve_setting_get_uint_value( + svinst, "sieve_include_max_includes", &uint_setting)) + ctx->max_includes = (unsigned int)uint_setting; + + /* Extension dependencies */ + ctx->var_ext = sieve_ext_variables_get_extension(ext->svinst); + + *context = (void *)ctx; + return TRUE; +} + +void ext_include_unload(const struct sieve_extension *ext) +{ + struct ext_include_context *ctx = + (struct ext_include_context *)ext->context; + + if (ctx->global_storage != NULL) + sieve_storage_unref(&ctx->global_storage); + if (ctx->personal_storage != NULL) + sieve_storage_unref(&ctx->personal_storage); + + i_free(ctx->global_location); + i_free(ctx); +} + +/* + * Script access + */ + +struct sieve_storage * +ext_include_get_script_storage(const struct sieve_extension *ext, + enum ext_include_script_location location, + const char *script_name, + enum sieve_error *error_r) +{ + struct sieve_instance *svinst = ext->svinst; + struct ext_include_context *ctx = + (struct ext_include_context *)ext->context; + + switch (location) { + case EXT_INCLUDE_LOCATION_PERSONAL: + if (ctx->personal_storage == NULL) { + ctx->personal_storage = + sieve_storage_create_main(svinst, NULL, 0, + error_r); + } + return ctx->personal_storage; + case EXT_INCLUDE_LOCATION_GLOBAL: + if (ctx->global_location == NULL) { + e_info(svinst->event, "include: " + "sieve_global is unconfigured; " + "include of `:global' script `%s' is therefore not possible", + str_sanitize(script_name, 80)); + if (error_r != NULL) + *error_r = SIEVE_ERROR_NOT_FOUND; + return NULL; + } + if (ctx->global_storage == NULL) { + ctx->global_storage = sieve_storage_create( + svinst, ctx->global_location, 0, error_r); + } + return ctx->global_storage; + default: + break; + } + + i_unreached(); + return NULL; +} + +/* + * AST context management + */ + +static void +ext_include_ast_free(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_ast *ast ATTR_UNUSED, void *context) +{ + struct ext_include_ast_context *actx = + (struct ext_include_ast_context *)context; + struct sieve_script **scripts; + unsigned int count, i; + + /* Unreference included scripts */ + scripts = array_get_modifiable(&actx->included_scripts, &count); + for (i = 0; i < count; i++) { + sieve_script_unref(&scripts[i]); + } + + /* Unreference variable scopes */ + if (actx->global_vars != NULL) + sieve_variable_scope_unref(&actx->global_vars); +} + +static const struct sieve_ast_extension include_ast_extension = { + &include_extension, + ext_include_ast_free +}; + +struct ext_include_ast_context * +ext_include_create_ast_context(const struct sieve_extension *this_ext, + struct sieve_ast *ast, struct sieve_ast *parent) +{ + struct ext_include_ast_context *actx; + + pool_t pool = sieve_ast_pool(ast); + actx = p_new(pool, struct ext_include_ast_context, 1); + p_array_init(&actx->included_scripts, pool, 32); + + if (parent != NULL) { + struct ext_include_ast_context *parent_ctx = + (struct ext_include_ast_context *) + sieve_ast_extension_get_context(parent, this_ext); + + actx->global_vars = parent_ctx->global_vars; + i_assert(actx->global_vars != NULL); + + sieve_variable_scope_ref(actx->global_vars); + } else { + struct ext_include_context *ectx = + ext_include_get_context(this_ext); + + actx->global_vars = sieve_variable_scope_create( + this_ext->svinst, ectx->var_ext, this_ext); + } + + sieve_ast_extension_register(ast, this_ext, &include_ast_extension, + (void *)actx); + return actx; +} + +struct ext_include_ast_context * +ext_include_get_ast_context(const struct sieve_extension *this_ext, + struct sieve_ast *ast) +{ + struct ext_include_ast_context *actx = + (struct ext_include_ast_context *) + sieve_ast_extension_get_context(ast, this_ext); + + if (actx != NULL) + return actx; + return ext_include_create_ast_context(this_ext, ast, NULL); +} + +void ext_include_ast_link_included_script( + const struct sieve_extension *this_ext, struct sieve_ast *ast, + struct sieve_script *script) +{ + struct ext_include_ast_context *actx = + ext_include_get_ast_context(this_ext, ast); + + array_append(&actx->included_scripts, &script, 1); +} + +bool ext_include_validator_have_variables( + const struct sieve_extension *this_ext, struct sieve_validator *valdtr) +{ + struct ext_include_context *ectx = ext_include_get_context(this_ext); + + return sieve_ext_variables_is_active(ectx->var_ext, valdtr); +} + +/* + * Generator context management + */ + +static struct ext_include_generator_context * +ext_include_create_generator_context( + struct sieve_generator *gentr, + struct ext_include_generator_context *parent, + struct sieve_script *script) +{ + struct ext_include_generator_context *ctx; + + pool_t pool = sieve_generator_pool(gentr); + ctx = p_new(pool, struct ext_include_generator_context, 1); + ctx->parent = parent; + ctx->script = script; + if (parent == NULL) + ctx->nesting_depth = 0; + else + ctx->nesting_depth = parent->nesting_depth + 1; + + return ctx; +} + +static inline struct ext_include_generator_context * +ext_include_get_generator_context(const struct sieve_extension *this_ext, + struct sieve_generator *gentr) +{ + return (struct ext_include_generator_context *) + sieve_generator_extension_get_context(gentr, this_ext); +} + +static inline void +ext_include_initialize_generator_context( + const struct sieve_extension *this_ext, struct sieve_generator *gentr, + struct ext_include_generator_context *parent, + struct sieve_script *script) +{ + sieve_generator_extension_set_context( + gentr, this_ext, + ext_include_create_generator_context(gentr, parent, script)); +} + +void ext_include_register_generator_context( + const struct sieve_extension *this_ext, + const struct sieve_codegen_env *cgenv) +{ + struct ext_include_generator_context *ctx = + ext_include_get_generator_context(this_ext, cgenv->gentr); + + /* Initialize generator context if necessary */ + if (ctx == NULL) { + ctx = ext_include_create_generator_context( + cgenv->gentr, NULL, cgenv->script); + + sieve_generator_extension_set_context( + cgenv->gentr, this_ext, (void *)ctx); + } + + /* Initialize ast context if necessary */ + (void)ext_include_get_ast_context(this_ext, cgenv->ast); + (void)ext_include_binary_init(this_ext, cgenv->sbin, cgenv->ast); +} + +/* + * Runtime initialization + */ + +static int +ext_include_runtime_init(const struct sieve_extension *this_ext, + const struct sieve_runtime_env *renv, + void *context, bool deferred ATTR_UNUSED) +{ + struct ext_include_interpreter_context *ctx = + (struct ext_include_interpreter_context *)context; + struct ext_include_context *ectx = ext_include_get_context(this_ext); + + if (ctx->parent == NULL) { + ctx->global = p_new(ctx->pool, + struct ext_include_interpreter_global, 1); + p_array_init(&ctx->global->included_scripts, ctx->pool, 10); + + ctx->global->var_scope = + ext_include_binary_get_global_scope( + this_ext, renv->sbin); + ctx->global->var_storage = + sieve_variable_storage_create(ectx->var_ext, ctx->pool, + ctx->global->var_scope); + } else { + ctx->global = ctx->parent->global; + } + + sieve_ext_variables_runtime_set_storage(ectx->var_ext, renv, this_ext, + ctx->global->var_storage); + return SIEVE_EXEC_OK; +} + +static struct sieve_interpreter_extension include_interpreter_extension = { + .ext_def = &include_extension, + .run = ext_include_runtime_init +}; + +/* + * Interpreter context management + */ + +static struct ext_include_interpreter_context * +ext_include_interpreter_context_create( + struct sieve_interpreter *interp, + struct ext_include_interpreter_context *parent, + struct sieve_script *script, + const struct ext_include_script_info *sinfo) +{ + struct ext_include_interpreter_context *ctx; + + pool_t pool = sieve_interpreter_pool(interp); + ctx = p_new(pool, struct ext_include_interpreter_context, 1); + ctx->pool = pool; + ctx->parent = parent; + ctx->interp = interp; + ctx->script = script; + ctx->script_info = sinfo; + + if (parent == NULL) + ctx->nesting_depth = 0; + else + ctx->nesting_depth = parent->nesting_depth + 1; + return ctx; +} + +static inline struct ext_include_interpreter_context * +ext_include_get_interpreter_context(const struct sieve_extension *this_ext, + struct sieve_interpreter *interp) +{ + return (struct ext_include_interpreter_context *) + sieve_interpreter_extension_get_context(interp, this_ext); +} + +static inline struct ext_include_interpreter_context * +ext_include_interpreter_context_init_child( + const struct sieve_extension *this_ext, + struct sieve_interpreter *interp, + struct ext_include_interpreter_context *parent, + struct sieve_script *script, + const struct ext_include_script_info *sinfo) +{ + struct ext_include_interpreter_context *ctx = + ext_include_interpreter_context_create(interp, parent, + script, sinfo); + + sieve_interpreter_extension_register(interp, this_ext, + &include_interpreter_extension, + ctx); + return ctx; +} + +void ext_include_interpreter_context_init( + const struct sieve_extension *this_ext, + struct sieve_interpreter *interp) +{ + struct ext_include_interpreter_context *ctx = + ext_include_get_interpreter_context(this_ext, interp); + + /* Is this is the top-level interpreter ? */ + if (ctx == NULL) { + struct sieve_script *script; + + /* Initialize top context */ + script = sieve_interpreter_script(interp); + ctx = ext_include_interpreter_context_create(interp, NULL, + script, NULL); + + sieve_interpreter_extension_register( + interp, this_ext, &include_interpreter_extension, + (void *)ctx); + } +} + +struct sieve_variable_storage * +ext_include_interpreter_get_global_variables( + const struct sieve_extension *this_ext, + struct sieve_interpreter *interp) +{ + struct ext_include_interpreter_context *ctx = + ext_include_get_interpreter_context(this_ext, interp); + + return ctx->global->var_storage; +} + +/* + * Including a script during code generation + */ + +int ext_include_generate_include( + const struct sieve_codegen_env *cgenv, struct sieve_command *cmd, + enum ext_include_script_location location, enum ext_include_flags flags, + struct sieve_script *script, + const struct ext_include_script_info **included_r) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct ext_include_context *ext_ctx = + (struct ext_include_context *)this_ext->context; + int result = 1; + struct sieve_ast *ast; + struct sieve_binary *sbin = cgenv->sbin; + struct sieve_generator *gentr = cgenv->gentr; + struct ext_include_binary_context *binctx; + struct sieve_generator *subgentr; + struct ext_include_generator_context *ctx = + ext_include_get_generator_context(this_ext, gentr); + struct ext_include_generator_context *pctx; + struct sieve_error_handler *ehandler = + sieve_generator_error_handler(gentr); + struct ext_include_script_info *included; + + *included_r = NULL; + + /* Just to be sure: do not include more scripts when errors have occured + already. + */ + if (sieve_get_errors(ehandler) > 0) + return -1; + + /* Limit nesting level */ + if (ctx->nesting_depth >= ext_ctx->max_nesting_depth) { + sieve_command_generate_error( + gentr, cmd, + "cannot nest includes deeper than %d levels", + ext_ctx->max_nesting_depth); + return -1; + } + + /* Check for circular include */ + if ((flags & EXT_INCLUDE_FLAG_ONCE) == 0) { + pctx = ctx; + while (pctx != NULL) { + if (sieve_script_equals(pctx->script, script)) { + /* Just drop circular include when uploading + inactive script; not an error + */ + if ((cgenv->flags & SIEVE_COMPILE_FLAG_UPLOADED) != 0 && + (cgenv->flags & SIEVE_COMPILE_FLAG_ACTIVATED) == 0) { + sieve_command_generate_warning( + gentr, cmd, + "circular include (ignored during upload)"); + return 0; + } + + sieve_command_generate_error(gentr, cmd, + "circular include"); + return -1; + } + + pctx = pctx->parent; + } + } + + /* Get binary context */ + binctx = ext_include_binary_init(this_ext, sbin, cgenv->ast); + + /* Is the script already compiled into the current binary? */ + included = ext_include_binary_script_get_include_info(binctx, script); + if (included != NULL) { + /* Yes, only update flags */ + if ((flags & EXT_INCLUDE_FLAG_OPTIONAL) == 0) + included->flags &= ENUM_NEGATE(EXT_INCLUDE_FLAG_OPTIONAL); + if ((flags & EXT_INCLUDE_FLAG_ONCE) == 0) + included->flags &= ENUM_NEGATE(EXT_INCLUDE_FLAG_ONCE); + } else { + const char *script_name = sieve_script_name(script); + enum sieve_compile_flags cpflags = cgenv->flags; + + /* No, include new script */ + + /* Check whether include limit is exceeded */ + if (ext_include_binary_script_get_count(binctx) >= + ext_ctx->max_includes) { + sieve_command_generate_error( + gentr, cmd, "failed to include script '%s': " + "no more than %u includes allowed", + str_sanitize(script_name, 80), + ext_ctx->max_includes); + return -1; + } + + /* Allocate a new block in the binary and mark the script as + included. */ + if (!sieve_script_is_open(script)) { + /* Just making an empty entry to mark a missing script + */ + i_assert((flags & EXT_INCLUDE_FLAG_MISSING_AT_UPLOAD) != 0 || + (flags & EXT_INCLUDE_FLAG_OPTIONAL) != 0); + included = ext_include_binary_script_include( + binctx, location, flags, script, NULL); + result = 0; + + } else { + struct sieve_binary_block *inc_block = + sieve_binary_block_create(sbin); + + /* Real include */ + included = ext_include_binary_script_include( + binctx, location, flags, script, inc_block); + + /* Parse */ + if ((ast = sieve_parse(script, ehandler, + NULL)) == NULL) { + sieve_command_generate_error( + gentr, cmd, + "failed to parse included script '%s'", + str_sanitize(script_name, 80)); + return -1; + } + + /* Included scripts inherit global variable scope */ + (void)ext_include_create_ast_context( + this_ext, ast, cmd->ast_node->ast); + + if (location == EXT_INCLUDE_LOCATION_GLOBAL) { + cpflags &= + ENUM_NEGATE(SIEVE_EXECUTE_FLAG_NOGLOBAL); + } else { + cpflags |= SIEVE_EXECUTE_FLAG_NOGLOBAL; + } + + /* Validate */ + if (!sieve_validate(ast, ehandler, cpflags, NULL)) { + sieve_command_generate_error( + gentr, cmd, + "failed to validate included script '%s'", + str_sanitize(script_name, 80)); + sieve_ast_unref(&ast); + return -1; + } + + /* Generate + + FIXME: It might not be a good idea to recurse code + generation for included scripts. + */ + subgentr = sieve_generator_create(ast, ehandler, cpflags); + ext_include_initialize_generator_context( + cmd->ext, subgentr, ctx, script); + + if (sieve_generator_run(subgentr, &inc_block) == NULL) { + sieve_command_generate_error( + gentr, cmd, + "failed to generate code for included script '%s'", + str_sanitize(script_name, 80)); + result = -1; + } + + sieve_generator_free(&subgentr); + + /* Cleanup */ + sieve_ast_unref(&ast); + } + } + + if (result > 0) + *included_r = included; + return result; +} + +/* + * Executing an included script during interpretation + */ + +static bool +ext_include_runtime_check_circular( + struct ext_include_interpreter_context *ctx, + const struct ext_include_script_info *include) +{ + struct ext_include_interpreter_context *pctx; + + pctx = ctx; + while (pctx != NULL) { + + if (sieve_script_equals(include->script, pctx->script)) + return TRUE; + + pctx = pctx->parent; + } + + return FALSE; +} + +static bool +ext_include_runtime_include_mark(struct ext_include_interpreter_context *ctx, + const struct ext_include_script_info *include, + bool once) +{ + struct sieve_script *const *includes; + unsigned int count, i; + + includes = array_get(&ctx->global->included_scripts, &count); + for (i = 0; i < count; i++) { + if (sieve_script_equals(include->script, includes[i])) + return (!once); + } + + array_append(&ctx->global->included_scripts, &include->script, 1); + return TRUE; +} + +int ext_include_execute_include(const struct sieve_runtime_env *renv, + unsigned int include_id, + enum ext_include_flags flags) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_extension *this_ext = renv->oprtn->ext; + int result = SIEVE_EXEC_OK; + struct ext_include_interpreter_context *ctx; + const struct ext_include_script_info *included; + struct ext_include_binary_context *binctx = + ext_include_binary_get_context(this_ext, renv->sbin); + bool once = ((flags & EXT_INCLUDE_FLAG_ONCE) != 0); + unsigned int block_id; + + /* Check for invalid include id (== corrupt binary) */ + included = ext_include_binary_script_get_included(binctx, include_id); + if (included == NULL) { + sieve_runtime_trace_error( + renv, "include: include id %d is invalid", include_id); + return SIEVE_EXEC_BIN_CORRUPT; + } + + ctx = ext_include_get_interpreter_context(this_ext, renv->interp); + block_id = sieve_binary_block_get_id(included->block); + + /* If :once modifier is specified, check for duplicate include */ + if (ext_include_runtime_include_mark(ctx, included, once)) { + sieve_runtime_trace( + renv, SIEVE_TRLVL_NONE, + "include: start script '%s' [inc id: %d, block: %d]", + sieve_script_name(included->script), + include_id, block_id); + } else { + /* skip */ + sieve_runtime_trace( + renv, SIEVE_TRLVL_NONE, + "include: skipped include for script '%s' " + "[inc id: %d, block: %d]; already run once", + sieve_script_name(included->script), + include_id, block_id); + return result; + } + + /* Check circular include during interpretation as well. + * Let's not trust binaries. + */ + if (ext_include_runtime_check_circular(ctx, included)) { + sieve_runtime_trace_error(renv, + "include: circular include of script '%s' " + "[inc id: %d, block: %d]", + sieve_script_name(included->script), + include_id, block_id); + + /* Situation has no valid way to emerge at runtime */ + return SIEVE_EXEC_BIN_CORRUPT; + } + + if (ctx->parent == NULL) { + struct ext_include_interpreter_context *curctx = NULL; + struct sieve_error_handler *ehandler = renv->ehandler; + struct sieve_interpreter *subinterp; + bool interrupted = FALSE; + + /* We are the top-level interpreter instance */ + if (result == SIEVE_EXEC_OK) { + struct sieve_execute_env eenv_new = *eenv; + + if (included->location != EXT_INCLUDE_LOCATION_GLOBAL) + eenv_new.flags |= SIEVE_EXECUTE_FLAG_NOGLOBAL; + else { + eenv_new.flags &= + ENUM_NEGATE(SIEVE_EXECUTE_FLAG_NOGLOBAL); + } + + /* Create interpreter for top-level included script + (first sub-interpreter) + */ + subinterp = sieve_interpreter_create_for_block( + included->block, included->script, renv->interp, + &eenv_new, ehandler); + if (subinterp != NULL) { + curctx = ext_include_interpreter_context_init_child( + this_ext, subinterp, ctx, included->script, + included); + + /* Activate and start the top-level included script */ + result = sieve_interpreter_start( + subinterp, renv->result, &interrupted); + } else { + result = SIEVE_EXEC_BIN_CORRUPT; + } + } + + /* Included scripts can have includes of their own. This is not + implemented recursively. Rather, the sub-interpreter + interrupts and defers the include to the top-level + interpreter, which is here. */ + if (result == SIEVE_EXEC_OK && interrupted && + !curctx->returned) { + while (result == SIEVE_EXEC_OK) { + if (((interrupted && curctx->returned) || + (!interrupted)) && + curctx->parent != NULL) { + const struct ext_include_script_info *ended_script = + curctx->script_info; + + /* Sub-interpreter ended or executed + return */ + + /* Ascend interpreter stack */ + curctx = curctx->parent; + sieve_interpreter_free(&subinterp); + + sieve_runtime_trace(renv, SIEVE_TRLVL_NONE, + "include: script '%s' ended " + "[inc id: %d, block: %d]", + sieve_script_name(ended_script->script), + ended_script->id, + sieve_binary_block_get_id(ended_script->block)); + + /* This is the top-most sub-interpreter, + bail out */ + if (curctx->parent == NULL) + break; + + subinterp = curctx->interp; + + /* Continue parent */ + curctx->include = NULL; + curctx->returned = FALSE; + + result = sieve_interpreter_continue( + subinterp, &interrupted); + } else { + if (curctx->include != NULL) { + /* Sub-include requested */ + + if (result == SIEVE_EXEC_OK) { + struct sieve_execute_env eenv_new = *eenv; + + if (curctx->include->location != EXT_INCLUDE_LOCATION_GLOBAL) + eenv_new.flags |= SIEVE_EXECUTE_FLAG_NOGLOBAL; + else { + eenv_new.flags &= + ENUM_NEGATE(SIEVE_EXECUTE_FLAG_NOGLOBAL); + } + + /* Create sub-interpreter */ + subinterp = sieve_interpreter_create_for_block( + curctx->include->block, curctx->include->script, + curctx->interp, &eenv_new, ehandler); + if (subinterp != NULL) { + curctx = ext_include_interpreter_context_init_child( + this_ext, subinterp, curctx, + curctx->include->script, curctx->include); + + /* Start the sub-include's interpreter */ + curctx->include = NULL; + curctx->returned = FALSE; + result = sieve_interpreter_start( + subinterp, renv->result, &interrupted); + } else { + result = SIEVE_EXEC_BIN_CORRUPT; + } + } + } else { + /* Sub-interpreter was interrupted outside + this extension, probably stop command was + executed. Generate an interrupt ourselves, + ending all script execution. */ + sieve_interpreter_interrupt(renv->interp); + break; + } + } + } + } + + /* Free any sub-interpreters that might still be active */ + while (curctx != NULL && curctx->parent != NULL) { + struct ext_include_interpreter_context *nextctx = + curctx->parent; + struct sieve_interpreter *killed_interp = curctx->interp; + const struct ext_include_script_info *ended_script = + curctx->script_info; + + /* This kills curctx too */ + sieve_interpreter_free(&killed_interp); + + sieve_runtime_trace( + renv, SIEVE_TRLVL_NONE, + "include: script '%s' ended [id: %d, block: %d]", + sieve_script_name(ended_script->script), + ended_script->id, + sieve_binary_block_get_id(ended_script->block)); + + /* Luckily we recorded the parent earlier */ + curctx = nextctx; + } + + } else { + /* We are an included script already, defer inclusion to main + interpreter */ + ctx->include = included; + sieve_interpreter_interrupt(renv->interp); + } + + return result; +} + +void ext_include_execute_return(const struct sieve_runtime_env *renv) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct ext_include_interpreter_context *ctx = + ext_include_get_interpreter_context(this_ext, renv->interp); + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "return: exiting included script"); + ctx->returned = TRUE; + sieve_interpreter_interrupt(renv->interp); +} diff --git a/pigeonhole/src/lib-sieve/plugins/include/ext-include-common.h b/pigeonhole/src/lib-sieve/plugins/include/ext-include-common.h new file mode 100644 index 0000000..44bfe9a --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/ext-include-common.h @@ -0,0 +1,170 @@ +#ifndef EXT_INCLUDE_COMMON_H +#define EXT_INCLUDE_COMMON_H + +#include "lib.h" +#include "hash.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" + +/* + * Forward declarations + */ + +struct ext_include_script_info; +struct ext_include_binary_context; + +/* + * Types + */ + +enum ext_include_flags { // stored in one byte + EXT_INCLUDE_FLAG_ONCE = 0x01, + EXT_INCLUDE_FLAG_OPTIONAL = 0x02, + EXT_INCLUDE_FLAG_MISSING_AT_UPLOAD = 0x04 +}; + +enum ext_include_script_location { + EXT_INCLUDE_LOCATION_PERSONAL, + EXT_INCLUDE_LOCATION_GLOBAL, + EXT_INCLUDE_LOCATION_INVALID +}; + +static inline const char * +ext_include_script_location_name(enum ext_include_script_location location) +{ + switch (location) { + case EXT_INCLUDE_LOCATION_PERSONAL: + return "personal"; + case EXT_INCLUDE_LOCATION_GLOBAL: + return "global"; + default: + break; + } + + return "[INVALID LOCATION]"; +} + + +/* + * Extension + */ + +extern const struct sieve_extension_def include_extension; +extern const struct sieve_binary_extension include_binary_ext; + +bool ext_include_load(const struct sieve_extension *ext, void **context); +void ext_include_unload(const struct sieve_extension *ext); + +/* + * Commands + */ + +extern const struct sieve_command_def cmd_include; +extern const struct sieve_command_def cmd_return; +extern const struct sieve_command_def cmd_global; + +/* DEPRICATED */ +extern const struct sieve_command_def cmd_import; +extern const struct sieve_command_def cmd_export; + +/* + * Operations + */ + +enum ext_include_opcode { + EXT_INCLUDE_OPERATION_INCLUDE, + EXT_INCLUDE_OPERATION_RETURN, + EXT_INCLUDE_OPERATION_GLOBAL +}; + +extern const struct sieve_operation_def include_operation; +extern const struct sieve_operation_def return_operation; +extern const struct sieve_operation_def global_operation; + +/* + * Script access + */ + +struct sieve_storage * +ext_include_get_script_storage(const struct sieve_extension *ext, + enum ext_include_script_location location, + const char *script_name, + enum sieve_error *error_r); +/* + * Context + */ + +/* Extension context */ + +struct ext_include_context { + /* Extension dependencies */ + const struct sieve_extension *var_ext; + + /* Configuration */ + char *global_location; + + struct sieve_storage *global_storage; + struct sieve_storage *personal_storage; + + unsigned int max_nesting_depth; + unsigned int max_includes; +}; + +static inline struct ext_include_context * +ext_include_get_context(const struct sieve_extension *ext) +{ + return (struct ext_include_context *) ext->context; +} + +/* AST Context */ + +struct ext_include_ast_context { + struct sieve_variable_scope *global_vars; + + ARRAY(struct sieve_script *) included_scripts; +}; + +struct ext_include_ast_context * +ext_include_create_ast_context(const struct sieve_extension *this_ext, + struct sieve_ast *ast, struct sieve_ast *parent); +struct ext_include_ast_context * +ext_include_get_ast_context(const struct sieve_extension *this_ext, + struct sieve_ast *ast); + +void ext_include_ast_link_included_script( + const struct sieve_extension *this_ext, struct sieve_ast *ast, + struct sieve_script *script); + +bool ext_include_validator_have_variables( + const struct sieve_extension *this_ext, struct sieve_validator *valdtr); + +/* Generator context */ + +void ext_include_register_generator_context( + const struct sieve_extension *this_ext, + const struct sieve_codegen_env *cgenv); + +int ext_include_generate_include( + const struct sieve_codegen_env *cgenv, struct sieve_command *cmd, + enum ext_include_script_location location, enum ext_include_flags flags, + struct sieve_script *script, + const struct ext_include_script_info **included_r); + +/* Interpreter context */ + +void ext_include_interpreter_context_init( + const struct sieve_extension *this_ext, + struct sieve_interpreter *interp); + +int ext_include_execute_include(const struct sieve_runtime_env *renv, + unsigned int block_id, + enum ext_include_flags flags); +void ext_include_execute_return(const struct sieve_runtime_env *renv); + +struct sieve_variable_storage * +ext_include_interpreter_get_global_variables( + const struct sieve_extension *this_ext, + struct sieve_interpreter *interp); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/include/ext-include-limits.h b/pigeonhole/src/lib-sieve/plugins/include/ext-include-limits.h new file mode 100644 index 0000000..37246c0 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/ext-include-limits.h @@ -0,0 +1,9 @@ +#ifndef EXT_INCLUDE_LIMITS_H +#define EXT_INCLUDE_LIMITS_H + +#include "sieve-common.h" + +#define EXT_INCLUDE_DEFAULT_MAX_NESTING_DEPTH 10 +#define EXT_INCLUDE_DEFAULT_MAX_INCLUDES 255 + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.c b/pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.c new file mode 100644 index 0000000..28cd803 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.c @@ -0,0 +1,254 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-script.h" +#include "sieve-ast.h" +#include "sieve-binary.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "ext-include-common.h" +#include "ext-include-binary.h" +#include "ext-include-variables.h" + +/* + * Variable import-export + */ + +struct sieve_variable *ext_include_variable_import_global +(struct sieve_validator *valdtr, struct sieve_command *cmd, + const char *variable) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct sieve_ast *ast = cmd->ast_node->ast; + struct ext_include_ast_context *ctx = + ext_include_get_ast_context(this_ext, ast); + struct ext_include_context *ectx = ext_include_get_context(this_ext); + struct sieve_variable_scope *local_scope; + struct sieve_variable_scope *global_scope = ctx->global_vars; + struct sieve_variable *global_var = NULL, *local_var; + + /* Sanity safeguard */ + i_assert ( ctx->global_vars != NULL ); + + if ( !sieve_variable_identifier_is_valid(variable) ) { + sieve_command_validate_error(valdtr, cmd, + "invalid variable identifier '%s'", str_sanitize(variable,80)); + return NULL; + } + + /* Get/Declare the variable in the global scope */ + global_var = sieve_variable_scope_declare(global_scope, variable); + + /* Check whether scope is over its size limit */ + if ( global_var == NULL ) { + sieve_command_validate_error(valdtr, cmd, + "declaration of new global variable '%s' exceeds the limit " + "(max variables: %u)", variable, + sieve_variables_get_max_scope_size(ectx->var_ext)); + return NULL; + } + + /* Import the global variable into the local script scope */ + local_scope = sieve_ext_variables_get_local_scope(ectx->var_ext, valdtr); + + local_var = sieve_variable_scope_get_variable(local_scope, variable); + if ( local_var != NULL && local_var->ext != this_ext ) { + /* FIXME: indicate location of conflicting set statement */ + sieve_command_validate_error(valdtr, cmd, + "declaration of new global variable '%s' conflicts with earlier local " + "use", variable); + return NULL; + } + + return sieve_variable_scope_import(local_scope, global_var); +} + +/* + * Binary symbol table + */ + +bool ext_include_variables_save +(struct sieve_binary_block *sblock, + struct sieve_variable_scope_binary *global_vars, + enum sieve_error *error_r ATTR_UNUSED) +{ + struct sieve_variable_scope *global_scope = + sieve_variable_scope_binary_get(global_vars); + unsigned int count = sieve_variable_scope_size(global_scope); + sieve_size_t jump; + + sieve_binary_emit_unsigned(sblock, count); + + jump = sieve_binary_emit_offset(sblock, 0); + + if ( count > 0 ) { + unsigned int size, i; + struct sieve_variable *const *vars = + sieve_variable_scope_get_variables(global_scope, &size); + + for ( i = 0; i < size; i++ ) { + sieve_binary_emit_cstring(sblock, vars[i]->identifier); + } + } + + sieve_binary_resolve_offset(sblock, jump); + + return TRUE; +} + +bool ext_include_variables_load +(const struct sieve_extension *this_ext, struct sieve_binary_block *sblock, + sieve_size_t *offset, struct sieve_variable_scope_binary **global_vars_r) +{ + struct ext_include_context *ectx = + ext_include_get_context(this_ext); + + /* Sanity assert */ + i_assert( *global_vars_r == NULL ); + + *global_vars_r = sieve_variable_scope_binary_read + (this_ext->svinst, ectx->var_ext, this_ext, sblock, offset); + + return ( *global_vars_r != NULL ); +} + +bool ext_include_variables_dump +(struct sieve_dumptime_env *denv, + struct sieve_variable_scope_binary *global_vars) +{ + struct sieve_variable_scope *global_scope = + sieve_variable_scope_binary_get(global_vars); + unsigned int size; + struct sieve_variable *const *vars; + + i_assert(global_scope != NULL); + + vars = sieve_variable_scope_get_variables(global_scope, &size); + + if ( size > 0 ) { + unsigned int i; + + sieve_binary_dump_sectionf(denv, "Global variables"); + + for ( i = 0; i < size; i++ ) { + sieve_binary_dumpf(denv, "%3d: '%s' \n", i, vars[i]->identifier); + } + } + + return TRUE; +} + +/* + * Global variables namespace + */ + +bool vnspc_global_variables_validate + (struct sieve_validator *valdtr, const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg, struct sieve_command *cmd, + ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, + bool assignment); +bool vnspc_global_variables_generate + (const struct sieve_codegen_env *cgenv, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg, struct sieve_command *cmd, void *var_data); + +static const struct sieve_variables_namespace_def +global_variables_namespace = { + SIEVE_OBJECT("global", NULL, 0), + .validate = vnspc_global_variables_validate, + .generate = vnspc_global_variables_generate +}; + +bool vnspc_global_variables_validate +(struct sieve_validator *valdtr, + const struct sieve_variables_namespace *nspc, struct sieve_ast_argument *arg, + struct sieve_command *cmd ATTR_UNUSED, + ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, + bool assignment ATTR_UNUSED) +{ + const struct sieve_extension *this_ext = SIEVE_OBJECT_EXTENSION(nspc); + struct sieve_ast *ast = arg->ast; + struct ext_include_context *ectx = + ext_include_get_context(this_ext); + struct ext_include_ast_context *ctx = + ext_include_get_ast_context(this_ext, ast); + struct sieve_variable *var = NULL; + const struct sieve_variable_name *name_element; + const char *variable; + + /* Sanity safeguard */ + i_assert ( ctx->global_vars != NULL ); + + /* Check variable name */ + + if ( array_count(var_name) != 2 ) { + sieve_argument_validate_error(valdtr, arg, + "invalid variable name within global namespace: " + "encountered sub-namespace"); + return FALSE; + } + + name_element = array_idx(var_name, 1); + if ( name_element->num_variable >= 0 ) { + sieve_argument_validate_error(valdtr, arg, + "invalid variable name within global namespace: " + "encountered numeric variable name"); + return FALSE; + } + + variable = str_c(name_element->identifier); + + /* Get/Declare the variable in the global scope */ + + var = sieve_variable_scope_declare(ctx->global_vars, variable); + + if ( var == NULL ) { + sieve_argument_validate_error(valdtr, arg, + "(implicit) declaration of new global variable '%s' exceeds the limit " + "(max variables: %u)", variable, + sieve_variables_get_max_scope_size(ectx->var_ext)); + return FALSE; + } + + *var_data = (void *) var; + + return TRUE; +} + +bool vnspc_global_variables_generate +(const struct sieve_codegen_env *cgenv, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg ATTR_UNUSED, + struct sieve_command *cmd ATTR_UNUSED, void *var_data) +{ + const struct sieve_extension *this_ext = SIEVE_OBJECT_EXTENSION(nspc); + struct ext_include_context *ectx = ext_include_get_context(this_ext); + struct sieve_variable *var = (struct sieve_variable *) var_data; + + sieve_variables_opr_variable_emit(cgenv->sblock, ectx->var_ext, var); + + return TRUE; +} + +void ext_include_variables_global_namespace_init +(const struct sieve_extension *this_ext, struct sieve_validator *valdtr) +{ + struct ext_include_context *ectx = ext_include_get_context(this_ext); + + sieve_variables_namespace_register + (ectx->var_ext, valdtr, this_ext, &global_variables_namespace); +} + + + diff --git a/pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.h b/pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.h new file mode 100644 index 0000000..d5927b2 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.h @@ -0,0 +1,41 @@ +#ifndef EXT_INCLUDE_VARIABLES_H +#define EXT_INCLUDE_VARIABLES_H + +#include "sieve-common.h" + +#include "sieve-ext-variables.h" + +#include "ext-include-common.h" + +/* + * Variable import-export + */ + +struct sieve_variable *ext_include_variable_import_global + (struct sieve_validator *valdtr, struct sieve_command *cmd, + const char *variable); + +/* + * Binary symbol table + */ + +bool ext_include_variables_save + (struct sieve_binary_block *sblock, + struct sieve_variable_scope_binary *global_vars, + enum sieve_error *error_r); +bool ext_include_variables_load + (const struct sieve_extension *this_ext, struct sieve_binary_block *sblock, + sieve_size_t *offset, struct sieve_variable_scope_binary **global_vars_r); +bool ext_include_variables_dump + (struct sieve_dumptime_env *denv, + struct sieve_variable_scope_binary *global_vars); + +/* + * Validation + */ + +void ext_include_variables_global_namespace_init + (const struct sieve_extension *this_ext, struct sieve_validator *valdtr); + +#endif + diff --git a/pigeonhole/src/lib-sieve/plugins/include/ext-include.c b/pigeonhole/src/lib-sieve/plugins/include/ext-include.c new file mode 100644 index 0000000..0a38687 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/ext-include.c @@ -0,0 +1,121 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension include + * ----------------- + * + * Authors: Stephan Bosch + * Specification: RFC 6609 + * Implementation: full + * Status: testing + * + */ + +/* FIXME: Current include implementation does not allow for parts of the script + * to be located in external binaries; all included scripts are recompiled and + * the resulting byte code is imported into the main binary in separate blocks. + */ + +#include "lib.h" + +#include "sieve-common.h" + +#include "sieve-extensions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-binary.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "ext-include-common.h" +#include "ext-include-binary.h" +#include "ext-include-variables.h" + +/* + * Operations + */ + +static const struct sieve_operation_def *ext_include_operations[] = { + &include_operation, + &return_operation, + &global_operation +}; + +/* + * Extension + */ + +/* Forward declaration */ + +static bool ext_include_validator_load + (const struct sieve_extension *ext, struct sieve_validator *validator); +static bool ext_include_generator_load + (const struct sieve_extension *ext, const struct sieve_codegen_env *cgenv); +static bool ext_include_interpreter_load + (const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address); +static bool ext_include_binary_load + (const struct sieve_extension *ext, struct sieve_binary *binary); + +/* Extension objects */ + +const struct sieve_extension_def include_extension = { + .name = "include", + .version = 1, + + .load = ext_include_load, + .unload = ext_include_unload, + .validator_load = ext_include_validator_load, + .generator_load = ext_include_generator_load, + .interpreter_load = ext_include_interpreter_load, + .binary_load = ext_include_binary_load, + .binary_dump = ext_include_binary_dump, + .code_dump = ext_include_code_dump, + + SIEVE_EXT_DEFINE_OPERATIONS(ext_include_operations) +}; + +static bool ext_include_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register new commands */ + sieve_validator_register_command(valdtr, ext, &cmd_include); + sieve_validator_register_command(valdtr, ext, &cmd_return); + sieve_validator_register_command(valdtr, ext, &cmd_global); + + /* DEPRICATED */ + sieve_validator_register_command(valdtr, ext, &cmd_import); + sieve_validator_register_command(valdtr, ext, &cmd_export); + + /* Initialize global variables namespace */ + ext_include_variables_global_namespace_init(ext, valdtr); + + return TRUE; +} + +static bool ext_include_generator_load +(const struct sieve_extension *ext, const struct sieve_codegen_env *cgenv) +{ + ext_include_register_generator_context(ext, cgenv); + + return TRUE; +} + +static bool ext_include_interpreter_load +(const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + ext_include_interpreter_context_init(ext, renv->interp); + + return TRUE; +} + +static bool ext_include_binary_load +(const struct sieve_extension *ext, struct sieve_binary *sbin) +{ + (void)ext_include_binary_get_context(ext, sbin); + + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/index/Makefile.am b/pigeonhole/src/lib-sieve/plugins/index/Makefile.am new file mode 100644 index 0000000..434ca1c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/index/Makefile.am @@ -0,0 +1,13 @@ +noinst_LTLIBRARIES = libsieve_ext_index.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_index_la_SOURCES = \ + ext-index-common.c \ + ext-index.c \ + tag-index.c + +noinst_HEADERS = \ + ext-index-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/index/Makefile.in b/pigeonhole/src/lib-sieve/plugins/index/Makefile.in new file mode 100644 index 0000000..852316c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/index/Makefile.in @@ -0,0 +1,688 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/index +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_index_la_LIBADD = +am_libsieve_ext_index_la_OBJECTS = ext-index-common.lo ext-index.lo \ + tag-index.lo +libsieve_ext_index_la_OBJECTS = $(am_libsieve_ext_index_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ext-index-common.Plo \ + ./$(DEPDIR)/ext-index.Plo ./$(DEPDIR)/tag-index.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_index_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_index_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_index.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_index_la_SOURCES = \ + ext-index-common.c \ + ext-index.c \ + tag-index.c + +noinst_HEADERS = \ + ext-index-common.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/index/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/index/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_index.la: $(libsieve_ext_index_la_OBJECTS) $(libsieve_ext_index_la_DEPENDENCIES) $(EXTRA_libsieve_ext_index_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_index_la_OBJECTS) $(libsieve_ext_index_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-index-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-index.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tag-index.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-index-common.Plo + -rm -f ./$(DEPDIR)/ext-index.Plo + -rm -f ./$(DEPDIR)/tag-index.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ext-index-common.Plo + -rm -f ./$(DEPDIR)/ext-index.Plo + -rm -f ./$(DEPDIR)/tag-index.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/index/ext-index-common.c b/pigeonhole/src/lib-sieve/plugins/index/ext-index-common.c new file mode 100644 index 0000000..26fb706 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/index/ext-index-common.c @@ -0,0 +1,15 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "utc-offset.h" +#include "str.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-interpreter.h" +#include "sieve-message.h" + +#include "ext-index-common.h" + diff --git a/pigeonhole/src/lib-sieve/plugins/index/ext-index-common.h b/pigeonhole/src/lib-sieve/plugins/index/ext-index-common.h new file mode 100644 index 0000000..7ce3244 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/index/ext-index-common.h @@ -0,0 +1,29 @@ +#ifndef EXT_INDEX_COMMON_H +#define EXT_INDEX_COMMON_H + +#include "sieve-common.h" + +#include <time.h> + +#define SIEVE_EXT_INDEX_HDR_OVERRIDE_SEQUENCE 100 + +/* + * Tagged arguments + */ + +extern const struct sieve_argument_def index_tag; +extern const struct sieve_argument_def last_tag; + +/* + * Operands + */ + +extern const struct sieve_operand_def index_operand; + +/* + * Extension + */ + +extern const struct sieve_extension_def index_extension; + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/index/ext-index.c b/pigeonhole/src/lib-sieve/plugins/index/ext-index.c new file mode 100644 index 0000000..33e7771 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/index/ext-index.c @@ -0,0 +1,69 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension index + * ------------------ + * + * Authors: Stephan Bosch + * Specification: RFC 5260 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-message.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-index-common.h" + +/* + * Extension + */ + +static bool ext_index_validator_load +(const struct sieve_extension *ext, struct sieve_validator *validator); + +const struct sieve_extension_def index_extension = { + .name = "index", + .validator_load = ext_index_validator_load, + SIEVE_EXT_DEFINE_OPERAND(index_operand) +}; + +static bool ext_index_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register :index and :last tags with header, address and date test commands + * and we don't care whether these command are registered or even whether + * these will be registered at all. The validator handles either situation + * gracefully. + */ + sieve_validator_register_external_tag + (valdtr, "header", ext, &index_tag, SIEVE_OPT_MESSAGE_OVERRIDE); + sieve_validator_register_external_tag + (valdtr, "header", ext, &last_tag, 0); + + sieve_validator_register_external_tag + (valdtr, "address", ext, &index_tag, SIEVE_OPT_MESSAGE_OVERRIDE); + sieve_validator_register_external_tag + (valdtr, "address", ext, &last_tag, 0); + + sieve_validator_register_external_tag + (valdtr, "date", ext, &index_tag, SIEVE_OPT_MESSAGE_OVERRIDE); + sieve_validator_register_external_tag + (valdtr, "date", ext, &last_tag, 0); + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/index/tag-index.c b/pigeonhole/src/lib-sieve/plugins/index/tag-index.c new file mode 100644 index 0000000..d8938a5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/index/tag-index.c @@ -0,0 +1,278 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "mail-storage.h" +#include "mail-namespace.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-result.h" +#include "sieve-validator.h" +#include "sieve-generator.h" + +#include "ext-index-common.h" + +/* + * Tagged argument + */ + +static bool +tag_index_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, struct sieve_command *cmd); +static bool +tag_index_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, + struct sieve_command *context); + +const struct sieve_argument_def index_tag = { + .identifier = "index", + .validate = tag_index_validate, + .generate = tag_index_generate +}; + +static bool +tag_last_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, struct sieve_command *cmd); + +const struct sieve_argument_def last_tag = { + .identifier = "last", + .validate = tag_last_validate, +}; + +/* + * Header override + */ + +static bool +svmo_index_dump_context(const struct sieve_message_override *svmo, + const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +svmo_index_read_context(const struct sieve_message_override *svmo, + const struct sieve_runtime_env *renv, + sieve_size_t *address, void **ho_context); +static int +svmo_index_header_override(const struct sieve_message_override *svmo, + const struct sieve_runtime_env *renv, + bool mime_decode, struct sieve_stringlist **headers); + +const struct sieve_message_override_def index_header_override = { + SIEVE_OBJECT("index", &index_operand, 0), + .sequence = SIEVE_EXT_INDEX_HDR_OVERRIDE_SEQUENCE, + .dump_context = svmo_index_dump_context, + .read_context = svmo_index_read_context, + .header_override = svmo_index_header_override +}; + +/* + * Operand + */ + +static const struct sieve_extension_objects ext_header_overrides = + SIEVE_EXT_DEFINE_MESSAGE_OVERRIDE(index_header_override); + +const struct sieve_operand_def index_operand = { + .name = "index operand", + .ext_def = &index_extension, + .class = &sieve_message_override_operand_class, + .interface = &ext_header_overrides +}; + +/* + * Tag data + */ + +struct tag_index_data { + sieve_number_t fieldno; + bool last:1; +}; + +/* + * Tag validation + */ + +static bool +tag_index_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_ast_argument **arg, struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct tag_index_data *data; + + /* Skip the tag itself */ + *arg = sieve_ast_argument_next(*arg); + + /* Check syntax: + * ":index" <fieldno: number> + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_NUMBER, FALSE)) + return FALSE; + + if (tag->argument->data == NULL) { + data = p_new(sieve_command_pool(cmd), struct tag_index_data, 1); + tag->argument->data = (void *)data; + } else { + data = (struct tag_index_data *)tag->argument->data; + } + + data->fieldno = sieve_ast_argument_number(*arg); + if (data->fieldno == 0) { + sieve_argument_validate_error(valdtr, *arg, + "the :index tag for the %s %s cannot be zero", + sieve_command_identifier(cmd), + sieve_command_type_name(cmd)); + return FALSE; + } + + /* Detach parameter */ + *arg = sieve_ast_arguments_detach(*arg,1); + return TRUE; +} + +static bool +tag_last_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_ast_argument **arg, struct sieve_command *cmd) +{ + struct sieve_ast_argument *index_arg; + struct tag_index_data *data; + + index_arg = sieve_command_find_argument(cmd, &index_tag); + if (index_arg == NULL) { + sieve_argument_validate_error( + valdtr, *arg, + "the :last tag for the %s %s cannot be specified " + "without the :index tag", + sieve_command_identifier(cmd), + sieve_command_type_name(cmd)); + return FALSE; + } + + /* Set :last flag */ + if (index_arg->argument->data == NULL) { + data = p_new(sieve_command_pool(cmd), struct tag_index_data, 1); + index_arg->argument->data = (void*)data; + } else { + data = (struct tag_index_data *)index_arg->argument->data; + } + data->last = TRUE; + + /* Detach */ + *arg = sieve_ast_arguments_detach(*arg, 1); + return TRUE; +} + +/* + * Code generation + */ + +static bool +tag_index_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + struct tag_index_data *data = + (struct tag_index_data *)arg->argument->data; + + if (sieve_ast_argument_type(arg) != SAAT_TAG) + return FALSE; + + sieve_opr_message_override_emit(cgenv->sblock, arg->argument->ext, + &index_header_override); + + (void)sieve_binary_emit_integer (cgenv->sblock, data->fieldno); + (void)sieve_binary_emit_byte(cgenv->sblock, (data->last ? 1 : 0)); + return TRUE; +} + +/* + * Header override implementation + */ + +/* Context data */ + +struct svmo_index_context { + unsigned int fieldno; + bool last:1; +}; + +/* Context coding */ + +static bool +svmo_index_dump_context(const struct sieve_message_override *svmo ATTR_UNUSED, + const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_number_t fieldno = 0; + unsigned int last; + + if (!sieve_binary_read_integer(denv->sblock, address, &fieldno) || + fieldno == 0) + return FALSE; + + sieve_code_dumpf(denv, "fieldno: %llu", (unsigned long long) fieldno); + + if (!sieve_binary_read_byte(denv->sblock, address, &last)) + return FALSE; + + if (last > 0) + sieve_code_dumpf(denv, "last"); + return TRUE; +} + +static int +svmo_index_read_context(const struct sieve_message_override *svmo ATTR_UNUSED, + const struct sieve_runtime_env *renv, + sieve_size_t *address, void **ho_context) +{ + pool_t pool = sieve_result_pool(renv->result); + struct svmo_index_context *ctx; + sieve_number_t fieldno; + unsigned int last = 0; + + if (!sieve_binary_read_integer(renv->sblock, address, &fieldno)) { + sieve_runtime_trace_error(renv, "fieldno: invalid number"); + return SIEVE_EXEC_BIN_CORRUPT; + } + if (fieldno == 0) { + sieve_runtime_trace_error(renv, "fieldno: index is zero"); + return SIEVE_EXEC_BIN_CORRUPT; + } + if (!sieve_binary_read_byte(renv->sblock, address, &last)) { + sieve_runtime_trace_error(renv, "last: invalid byte"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + ctx = p_new(pool, struct svmo_index_context, 1); + ctx->fieldno = fieldno; + ctx->last = (last == 0 ? FALSE : TRUE); + + *ho_context = (void *) ctx; + return SIEVE_EXEC_OK; +} + +/* Override */ + +static int +svmo_index_header_override(const struct sieve_message_override *svmo, + const struct sieve_runtime_env *renv, + bool mime_decode ATTR_UNUSED, + struct sieve_stringlist **headers) +{ + struct svmo_index_context *ctx = + (struct svmo_index_context *)svmo->context; + + sieve_runtime_trace( + renv, SIEVE_TRLVL_MATCHING, + "header index override: only returning index %d%s", + ctx->fieldno, (ctx->last ? " (from last)" : "")); + + *headers = sieve_index_stringlist_create( + renv, *headers, (int)ctx->fieldno * (ctx->last ? -1 : 1)); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/mailbox/Makefile.am b/pigeonhole/src/lib-sieve/plugins/mailbox/Makefile.am new file mode 100644 index 0000000..b627735 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mailbox/Makefile.am @@ -0,0 +1,26 @@ +noinst_LTLIBRARIES = libsieve_ext_mailbox.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tags = \ + tag-mailbox-create.c + +tests = \ + tst-mailboxexists.c + +libsieve_ext_mailbox_la_SOURCES = \ + $(tags) \ + $(tests) \ + ext-mailbox.c + +public_headers = \ + sieve-ext-mailbox.h + +headers = \ + ext-mailbox-common.h + +pkginc_libdir=$(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) diff --git a/pigeonhole/src/lib-sieve/plugins/mailbox/Makefile.in b/pigeonhole/src/lib-sieve/plugins/mailbox/Makefile.in new file mode 100644 index 0000000..6d5ed09 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mailbox/Makefile.in @@ -0,0 +1,757 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/mailbox +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(pkginc_lib_HEADERS) $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_mailbox_la_LIBADD = +am__objects_1 = tag-mailbox-create.lo +am__objects_2 = tst-mailboxexists.lo +am_libsieve_ext_mailbox_la_OBJECTS = $(am__objects_1) $(am__objects_2) \ + ext-mailbox.lo +libsieve_ext_mailbox_la_OBJECTS = \ + $(am_libsieve_ext_mailbox_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ext-mailbox.Plo \ + ./$(DEPDIR)/tag-mailbox-create.Plo \ + ./$(DEPDIR)/tst-mailboxexists.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_mailbox_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_mailbox_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkginc_libdir)" +HEADERS = $(noinst_HEADERS) $(pkginc_lib_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_mailbox.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tags = \ + tag-mailbox-create.c + +tests = \ + tst-mailboxexists.c + +libsieve_ext_mailbox_la_SOURCES = \ + $(tags) \ + $(tests) \ + ext-mailbox.c + +public_headers = \ + sieve-ext-mailbox.h + +headers = \ + ext-mailbox-common.h + +pkginc_libdir = $(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/mailbox/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/mailbox/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_mailbox.la: $(libsieve_ext_mailbox_la_OBJECTS) $(libsieve_ext_mailbox_la_DEPENDENCIES) $(EXTRA_libsieve_ext_mailbox_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_mailbox_la_OBJECTS) $(libsieve_ext_mailbox_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-mailbox.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tag-mailbox-create.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-mailboxexists.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkginc_libHEADERS: $(pkginc_lib_HEADERS) + @$(NORMAL_INSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkginc_libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkginc_libdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkginc_libdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkginc_libdir)" || exit $$?; \ + done + +uninstall-pkginc_libHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkginc_libdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(pkginc_libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-mailbox.Plo + -rm -f ./$(DEPDIR)/tag-mailbox-create.Plo + -rm -f ./$(DEPDIR)/tst-mailboxexists.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pkginc_libHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ext-mailbox.Plo + -rm -f ./$(DEPDIR)/tag-mailbox-create.Plo + -rm -f ./$(DEPDIR)/tst-mailboxexists.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkginc_libHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-pkginc_libHEADERS install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pkginc_libHEADERS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/mailbox/ext-mailbox-common.h b/pigeonhole/src/lib-sieve/plugins/mailbox/ext-mailbox-common.h new file mode 100644 index 0000000..96cff39 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mailbox/ext-mailbox-common.h @@ -0,0 +1,39 @@ +#ifndef EXT_MAILBOX_COMMON_H +#define EXT_MAILBOX_COMMON_H + +#include "sieve-common.h" + +#include "sieve-ext-mailbox.h" + +/* + * Tagged arguments + */ + +extern const struct sieve_argument_def mailbox_create_tag; + +/* + * Commands + */ + +extern const struct sieve_command_def mailboxexists_test; + +/* + * Operands + */ + +extern const struct sieve_operand_def mailbox_create_operand; + +/* + * Operations + */ + +extern const struct sieve_operation_def mailboxexists_operation; + +/* + * Extension + */ + +extern const struct sieve_extension_def mailbox_extension; + +#endif + diff --git a/pigeonhole/src/lib-sieve/plugins/mailbox/ext-mailbox.c b/pigeonhole/src/lib-sieve/plugins/mailbox/ext-mailbox.c new file mode 100644 index 0000000..a2dcd88 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mailbox/ext-mailbox.c @@ -0,0 +1,72 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension mailbox + * ------------------ + * + * Authors: Stephan Bosch + * Specification: RFC 5490 + * Implementation: full + * Status: testing + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "ext-mailbox-common.h" + +/* + * Tag registration + */ + +void sieve_ext_mailbox_register_create_tag +(struct sieve_validator *valdtr, const struct sieve_extension *mailbox_ext, + const char *command) +{ + if ( sieve_validator_extension_loaded(valdtr, mailbox_ext) ) { + sieve_validator_register_external_tag(valdtr, command, + mailbox_ext, &mailbox_create_tag, SIEVE_OPT_SIDE_EFFECT); + } +} + + +/* + * Extension + */ + +static bool ext_mailbox_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def mailbox_extension = { + .name = "mailbox", + .validator_load = ext_mailbox_validator_load, + SIEVE_EXT_DEFINE_OPERATION(mailboxexists_operation), + SIEVE_EXT_DEFINE_OPERAND(mailbox_create_operand) +}; + +static bool ext_mailbox_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register :create tag with fileinto command and we don't care whether this + * command is registered or even whether it will be registered at all. The + * validator handles either situation gracefully + */ + sieve_validator_register_external_tag + (valdtr, "fileinto", ext, &mailbox_create_tag, SIEVE_OPT_SIDE_EFFECT); + + /* Register new test */ + sieve_validator_register_command(valdtr, ext, &mailboxexists_test); + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/mailbox/sieve-ext-mailbox.h b/pigeonhole/src/lib-sieve/plugins/mailbox/sieve-ext-mailbox.h new file mode 100644 index 0000000..f7fa4cf --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mailbox/sieve-ext-mailbox.h @@ -0,0 +1,21 @@ +#ifndef SIEVE_EXT_MAILBOX_H +#define SIEVE_EXT_MAILBOX_H + +/* sieve_ext_mailbox_get_extension(): + * Get the extension struct for the mailbox extension. + */ +static inline const struct sieve_extension *sieve_ext_mailbox_get_extension +(struct sieve_instance *svinst) +{ + return sieve_extension_get_by_name(svinst, "mailbox"); +} + +/* sieve_ext_mailbox_register_create_tag(): + * Register the :create tagged argument for a command other than fileinto and + * redirect. + */ +void sieve_ext_mailbox_register_create_tag + (struct sieve_validator *valdtr, const struct sieve_extension *mailbox_ext, + const char *command); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/mailbox/tag-mailbox-create.c b/pigeonhole/src/lib-sieve/plugins/mailbox/tag-mailbox-create.c new file mode 100644 index 0000000..f3c64cf --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mailbox/tag-mailbox-create.c @@ -0,0 +1,186 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "mail-storage.h" +#include "mail-namespace.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-code.h" +#include "sieve-actions.h" +#include "sieve-result.h" +#include "sieve-generator.h" + +#include "ext-mailbox-common.h" + +/* + * Tagged argument + */ + +static bool +tag_mailbox_create_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +tag_mailbox_create_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, + struct sieve_command *context); + +const struct sieve_argument_def mailbox_create_tag = { + .identifier = "create", + .validate = tag_mailbox_create_validate, + .generate = tag_mailbox_create_generate +}; + +/* + * Side effect + */ + +static void +seff_mailbox_create_print(const struct sieve_side_effect *seffect, + const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, + bool *keep); +static int +seff_mailbox_create_pre_execute(const struct sieve_side_effect *seffect, + const struct sieve_action_exec_env *aenv, + void *tr_context, + void **se_tr_context ATTR_UNUSED); + +const struct sieve_side_effect_def mailbox_create_side_effect = { + SIEVE_OBJECT("create", &mailbox_create_operand, 0), + .precedence = 100, + .to_action = &act_store, + .print = seff_mailbox_create_print, + .pre_execute = seff_mailbox_create_pre_execute +}; + +/* + * Operand + */ + +static const struct sieve_extension_objects ext_side_effects = + SIEVE_EXT_DEFINE_SIDE_EFFECT(mailbox_create_side_effect); + +const struct sieve_operand_def mailbox_create_operand = { + .name = "create operand", + .ext_def = &mailbox_extension, + .class = &sieve_side_effect_operand_class, + .interface = &ext_side_effects +}; + +/* + * Tag validation + */ + +static bool +tag_mailbox_create_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_ast_argument **arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Code generation + */ + +static bool +tag_mailbox_create_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, + struct sieve_command *context ATTR_UNUSED) +{ + if (sieve_ast_argument_type(arg) != SAAT_TAG) + return FALSE; + + sieve_opr_side_effect_emit(cgenv->sblock, arg->argument->ext, + &mailbox_create_side_effect); + return TRUE; +} + +/* + * Side effect implementation + */ + +static void +seff_mailbox_create_print(const struct sieve_side_effect *seffect ATTR_UNUSED, + const struct sieve_action *action ATTR_UNUSED, + const struct sieve_result_print_env *rpenv, + bool *keep ATTR_UNUSED) +{ + sieve_result_seffect_printf( + rpenv, "create mailbox if it does not exist"); +} + +static int +seff_mailbox_create_pre_execute( + const struct sieve_side_effect *seffect ATTR_UNUSED, + const struct sieve_action_exec_env *aenv, void *tr_context, + void **se_tr_context ATTR_UNUSED) +{ + struct act_store_transaction *trans = tr_context; + const struct sieve_execute_env *eenv = aenv->exec_env; + struct mailbox *box = trans->box; + + /* Check whether creation is necessary */ + if (box == NULL || trans->disabled) + return SIEVE_EXEC_OK; + + eenv->exec_status->last_storage = mailbox_get_storage(box); + + /* Open the mailbox (may already be open) */ + if (trans->error_code == MAIL_ERROR_NONE) { + if (mailbox_open(box) < 0) + sieve_act_store_get_storage_error(aenv, trans); + } + + /* Check whether creation has a chance of working */ + switch (trans->error_code) { + case MAIL_ERROR_NONE: + return SIEVE_EXEC_OK; + case MAIL_ERROR_NOTFOUND: + break; + case MAIL_ERROR_TEMP: + return SIEVE_EXEC_TEMP_FAILURE; + default: + return SIEVE_EXEC_FAILURE; + } + + trans->error = NULL; + trans->error_code = MAIL_ERROR_NONE; + + /* Create mailbox */ + if (mailbox_create(box, NULL, FALSE) < 0) { + sieve_act_store_get_storage_error(aenv, trans); + if (trans->error_code == MAIL_ERROR_EXISTS) { + trans->error = NULL; + trans->error_code = MAIL_ERROR_NONE; + } else { + return (trans->error_code == MAIL_ERROR_TEMP ? + SIEVE_EXEC_TEMP_FAILURE : SIEVE_EXEC_FAILURE); + } + } + + /* Subscribe to it if necessary */ + if (eenv->scriptenv->mailbox_autosubscribe) { + (void)mailbox_list_set_subscribed( + mailbox_get_namespace(box)->list, + mailbox_get_name(box), TRUE); + } + + /* Try opening again */ + if (mailbox_open(box) < 0) { + /* Failed definitively */ + sieve_act_store_get_storage_error(aenv, trans); + return (trans->error_code == MAIL_ERROR_TEMP ? + SIEVE_EXEC_TEMP_FAILURE : SIEVE_EXEC_FAILURE); + } + return SIEVE_EXEC_OK; +} + + + diff --git a/pigeonhole/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c b/pigeonhole/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c new file mode 100644 index 0000000..e0fd33d --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c @@ -0,0 +1,284 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" +#include "mail-storage.h" +#include "mail-namespace.h" + +#include "sieve-common.h" +#include "sieve-actions.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-mailbox-common.h" + +/* + * Mailboxexists command + * + * Syntax: + * mailboxexists <mailbox-names: string-list> + */ + +static bool +tst_mailboxexists_validate(struct sieve_validator *valdtr, + struct sieve_command *tst); +static bool +tst_mailboxexists_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def mailboxexists_test = { + .identifier = "mailboxexists", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = tst_mailboxexists_validate, + .generate = tst_mailboxexists_generate, +}; + +/* + * Mailboxexists operation + */ + +static bool +tst_mailboxexists_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +tst_mailboxexists_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def mailboxexists_operation = { + .mnemonic = "MAILBOXEXISTS", + .ext_def = &mailbox_extension, + .dump = tst_mailboxexists_operation_dump, + .execute = tst_mailboxexists_operation_execute, +}; + +/* + * Test validation + */ + +struct _validate_context { + struct sieve_validator *valdtr; + struct sieve_command *tst; +}; + +static int +tst_mailboxexists_mailbox_validate(void *context, + struct sieve_ast_argument *arg) +{ + struct _validate_context *valctx = + (struct _validate_context *)context; + + if (sieve_argument_is_string_literal(arg)) { + const char *mailbox = sieve_ast_argument_strc(arg), *error; + + if (!sieve_mailbox_check_name(mailbox, &error)) { + sieve_argument_validate_warning( + valctx->valdtr, arg, "%s test: " + "invalid mailbox name `%s' specified: %s", + sieve_command_identifier(valctx->tst), + str_sanitize(mailbox, 256), error); + } + } + + return 1; +} + +static bool +tst_mailboxexists_validate(struct sieve_validator *valdtr, + struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + struct sieve_ast_argument *aarg; + struct _validate_context valctx; + + if (!sieve_validate_positional_argument( + valdtr, tst, arg, "mailbox-names", 1, SAAT_STRING_LIST)) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) + return FALSE; + + aarg = arg; + i_zero(&valctx); + valctx.valdtr = valdtr; + valctx.tst = tst; + + return (sieve_ast_stringlist_map( + &aarg, (void*)&valctx, + tst_mailboxexists_mailbox_validate) >= 0); +} + +/* + * Test generation + */ + +static bool +tst_mailboxexists_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *tst) +{ + sieve_operation_emit(cgenv->sblock, tst->ext, &mailboxexists_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool +tst_mailboxexists_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_code_dumpf(denv, "MAILBOXEXISTS"); + sieve_code_descend(denv); + + return sieve_opr_stringlist_dump(denv, address, "mailbox-names"); +} + +/* + * Code execution + */ + +static int +tst_mailboxexists_test_mailbox(const struct sieve_runtime_env *renv, + const char *mailbox, bool trace, + bool *all_exist_r) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct mailbox *box; + const char *error; + + /* Check validity of mailbox name */ + if (!sieve_mailbox_check_name(mailbox, &error)) { + sieve_runtime_warning( + renv, NULL, "mailboxexists test: " + "invalid mailbox name `%s' specified: %s", + str_sanitize(mailbox, 256), error); + *all_exist_r = FALSE; + return SIEVE_EXEC_OK; + } + + /* Open the box */ + box = mailbox_alloc_for_user(eenv->scriptenv->user, + mailbox, + MAILBOX_FLAG_POST_SESSION); + + if (mailbox_open(box) < 0) { + if (trace) { + sieve_runtime_trace( + renv, 0, + "mailbox `%s' cannot be opened", + str_sanitize(mailbox, 80)); + } + mailbox_free(&box); + *all_exist_r = FALSE; + return SIEVE_EXEC_OK; + } + + /* Also fail when it is readonly */ + if (mailbox_is_readonly(box)) { + if (trace) { + sieve_runtime_trace( + renv, 0, + "mailbox `%s' is read-only", + str_sanitize(mailbox, 80)); + } + mailbox_free(&box); + *all_exist_r = FALSE; + return SIEVE_EXEC_OK; + } + + /* FIXME: check acl for 'p' or 'i' ACL permissions as + required by RFC */ + + if (trace) { + sieve_runtime_trace( + renv, 0, "mailbox `%s' exists", + str_sanitize(mailbox, 80)); + } + + /* Close mailbox */ + mailbox_free(&box); + return SIEVE_EXEC_OK; +} + +static int +tst_mailboxexists_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct sieve_stringlist *mailbox_names; + string_t *mailbox_item; + bool trace = FALSE; + bool all_exist = TRUE; + int ret; + + /* + * Read operands + */ + + /* Read notify uris */ + ret = sieve_opr_stringlist_read(renv, address, "mailbox-names", + &mailbox_names); + if (ret <= 0) + return ret; + + /* + * Perform operation + */ + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_TESTS)) { + sieve_runtime_trace(renv, 0, "mailboxexists test"); + sieve_runtime_trace_descend(renv); + + trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); + } + + if (eenv->scriptenv->user == NULL) { + sieve_runtime_trace(renv, 0, "no mail user; yield true"); + sieve_interpreter_set_test_result(renv->interp, TRUE); + return SIEVE_EXEC_OK; + } + + mailbox_item = NULL; + while (all_exist && + (ret = sieve_stringlist_next_item(mailbox_names, + &mailbox_item)) > 0) { + const char *mailbox = str_c(mailbox_item); + + ret = tst_mailboxexists_test_mailbox(renv, mailbox, + trace, &all_exist); + if (ret <= 0) + return ret; + } + + if (ret < 0) { + sieve_runtime_trace_error( + renv, "invalid mailbox name item"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if (trace) { + if (all_exist) { + sieve_runtime_trace(renv, 0, + "all mailboxes are available"); + } else { + sieve_runtime_trace(renv, 0, + "some mailboxes are unavailable"); + } + } + + sieve_interpreter_set_test_result(renv->interp, all_exist); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/metadata/Makefile.am b/pigeonhole/src/lib-sieve/plugins/metadata/Makefile.am new file mode 100644 index 0000000..6d69ba8 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/metadata/Makefile.am @@ -0,0 +1,24 @@ +noinst_LTLIBRARIES = libsieve_ext_metadata.la + +libsieve_ext_metadata_la_LDFLAGS = -module -avoid-version + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_STORAGE_INCLUDE) + +tests = \ + tst-metadata.c \ + tst-metadataexists.c + +extensions = \ + ext-metadata.c + +libsieve_ext_metadata_la_SOURCES = \ + $(tests) \ + $(extensions) + +noinst_HEADERS = \ + ext-metadata-common.h + diff --git a/pigeonhole/src/lib-sieve/plugins/metadata/Makefile.in b/pigeonhole/src/lib-sieve/plugins/metadata/Makefile.in new file mode 100644 index 0000000..0b95819 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/metadata/Makefile.in @@ -0,0 +1,705 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/metadata +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_metadata_la_LIBADD = +am__objects_1 = tst-metadata.lo tst-metadataexists.lo +am__objects_2 = ext-metadata.lo +am_libsieve_ext_metadata_la_OBJECTS = $(am__objects_1) \ + $(am__objects_2) +libsieve_ext_metadata_la_OBJECTS = \ + $(am_libsieve_ext_metadata_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libsieve_ext_metadata_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libsieve_ext_metadata_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ext-metadata.Plo \ + ./$(DEPDIR)/tst-metadata.Plo \ + ./$(DEPDIR)/tst-metadataexists.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_metadata_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_metadata_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_metadata.la +libsieve_ext_metadata_la_LDFLAGS = -module -avoid-version +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_STORAGE_INCLUDE) + +tests = \ + tst-metadata.c \ + tst-metadataexists.c + +extensions = \ + ext-metadata.c + +libsieve_ext_metadata_la_SOURCES = \ + $(tests) \ + $(extensions) + +noinst_HEADERS = \ + ext-metadata-common.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/metadata/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/metadata/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_metadata.la: $(libsieve_ext_metadata_la_OBJECTS) $(libsieve_ext_metadata_la_DEPENDENCIES) $(EXTRA_libsieve_ext_metadata_la_DEPENDENCIES) + $(AM_V_CCLD)$(libsieve_ext_metadata_la_LINK) $(libsieve_ext_metadata_la_OBJECTS) $(libsieve_ext_metadata_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-metadata.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-metadata.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-metadataexists.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-metadata.Plo + -rm -f ./$(DEPDIR)/tst-metadata.Plo + -rm -f ./$(DEPDIR)/tst-metadataexists.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ext-metadata.Plo + -rm -f ./$(DEPDIR)/tst-metadata.Plo + -rm -f ./$(DEPDIR)/tst-metadataexists.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/metadata/ext-metadata-common.h b/pigeonhole/src/lib-sieve/plugins/metadata/ext-metadata-common.h new file mode 100644 index 0000000..a4b25a0 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/metadata/ext-metadata-common.h @@ -0,0 +1,40 @@ +#ifndef EXT_METADATA_COMMON_H +#define EXT_METADATA_COMMON_H + +#include "lib.h" +#include "mail-storage.h" +#include "imap-metadata.h" + +#include "sieve-common.h" + +/* + * Extension + */ + +extern const struct sieve_extension_def mboxmetadata_extension; +extern const struct sieve_extension_def servermetadata_extension; + +/* + * Commands + */ + +extern const struct sieve_command_def metadata_test; +extern const struct sieve_command_def servermetadata_test; +extern const struct sieve_command_def metadataexists_test; +extern const struct sieve_command_def servermetadataexists_test; + +/* + * Operations + */ + +enum ext_metadata_opcode { + EXT_METADATA_OPERATION_METADATA, + EXT_METADATA_OPERATION_METADATAEXISTS +}; + +extern const struct sieve_operation_def metadata_operation; +extern const struct sieve_operation_def servermetadata_operation; +extern const struct sieve_operation_def metadataexists_operation; +extern const struct sieve_operation_def servermetadataexists_operation; + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/metadata/ext-metadata.c b/pigeonhole/src/lib-sieve/plugins/metadata/ext-metadata.c new file mode 100644 index 0000000..882116b --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/metadata/ext-metadata.c @@ -0,0 +1,83 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-binary.h" + +#include "sieve-validator.h" +#include "sieve-interpreter.h" + +#include "ext-metadata-common.h" + +/* + * Extension mboxmetadata + * ----------------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5490; Section 3 + * Implementation: skeleton + * Status: development + * + */ + +const struct sieve_operation_def *mboxmetadata_operations[] = { + &metadata_operation, + &metadataexists_operation, +}; + +static bool ext_mboxmetadata_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def mboxmetadata_extension = { + .name = "mboxmetadata", + .validator_load = ext_mboxmetadata_validator_load, + SIEVE_EXT_DEFINE_OPERATIONS(mboxmetadata_operations) +}; + +static bool ext_mboxmetadata_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + sieve_validator_register_command(valdtr, ext, &metadata_test); + sieve_validator_register_command(valdtr, ext, &metadataexists_test); + + return TRUE; +} + +/* + * Extension servermetadata + * ----------------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5490; Section 4 + * Implementation: skeleton + * Status: development + * + */ + +const struct sieve_operation_def *servermetadata_operations[] = { + &servermetadata_operation, + &servermetadataexists_operation, +}; + +static bool ext_servermetadata_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def servermetadata_extension = { + .name = "servermetadata", + .validator_load = ext_servermetadata_validator_load, + SIEVE_EXT_DEFINE_OPERATIONS(servermetadata_operations) +}; + +static bool ext_servermetadata_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + sieve_validator_register_command(valdtr, ext, &servermetadata_test); + sieve_validator_register_command(valdtr, ext, &servermetadataexists_test); + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/metadata/tst-metadata.c b/pigeonhole/src/lib-sieve/plugins/metadata/tst-metadata.c new file mode 100644 index 0000000..2e14535 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/metadata/tst-metadata.c @@ -0,0 +1,433 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" +#include "istream.h" + +#include "sieve-common.h" +#include "sieve-limits.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-metadata-common.h" + +#define TST_METADATA_MAX_MATCH_SIZE SIEVE_MAX_STRING_LEN + +/* + * Test definitions + */ + +/* Forward declarations */ + +static bool +tst_metadata_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool +tst_metadata_validate(struct sieve_validator *valdtr, + struct sieve_command *tst); +static bool +tst_metadata_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd); + +/* Metadata test + * + * Syntax: + * metadata [MATCH-TYPE] [COMPARATOR] + * <mailbox: string> + * <annotation-name: string> <key-list: string-list> + */ + +const struct sieve_command_def metadata_test = { + .identifier = "metadata", + .type = SCT_TEST, + .positional_args = 3, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_metadata_registered, + .validate = tst_metadata_validate, + .generate = tst_metadata_generate, +}; + +/* Servermetadata test + * + * Syntax: + * servermetadata [MATCH-TYPE] [COMPARATOR] + * <annotation-name: string> <key-list: string-list> + */ + +const struct sieve_command_def servermetadata_test = { + .identifier = "servermetadata", + .type = SCT_TEST, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_metadata_registered, + .validate = tst_metadata_validate, + .generate = tst_metadata_generate, +}; + +/* + * Opcode definitions + */ + +static bool +tst_metadata_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +tst_metadata_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +/* Metadata operation */ + +const struct sieve_operation_def metadata_operation = { + .mnemonic = "METADATA", + .ext_def = &mboxmetadata_extension, + .code = EXT_METADATA_OPERATION_METADATA, + .dump = tst_metadata_operation_dump, + .execute = tst_metadata_operation_execute, +}; + +/* Servermetadata operation */ + +const struct sieve_operation_def servermetadata_operation = { + .mnemonic = "SERVERMETADATA", + .ext_def = &servermetadata_extension, + .code = EXT_METADATA_OPERATION_METADATA, + .dump = tst_metadata_operation_dump, + .execute = tst_metadata_operation_execute, +}; + +/* + * Test registration + */ + +static bool +tst_metadata_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag(valdtr, cmd_reg, + SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, + SIEVE_MATCH_OPT_MATCH_TYPE); + return TRUE; +} + +/* + * Test validation + */ + +static bool +tst_metadata_validate(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + const struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + unsigned int arg_index = 1; + const char *error; + + /* mailbox */ + if (sieve_command_is(tst, metadata_test)) { + if (!sieve_validate_positional_argument( + valdtr, tst, arg, "mailbox", arg_index++, + SAAT_STRING)) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) + return FALSE; + + /* Check name validity when mailbox argument is not a variable + */ + if (sieve_argument_is_string_literal(arg)) { + const char *mailbox = sieve_ast_argument_strc(arg); + const char *error; + + if (!sieve_mailbox_check_name(mailbox, &error)) { + sieve_argument_validate_warning( + valdtr, arg, "%s test: " + "invalid mailbox name `%s' specified: %s", + sieve_command_identifier(tst), + str_sanitize(mailbox, 256), error); + } + } + arg = sieve_ast_argument_next(arg); + } + + /* annotation-name */ + if (!sieve_validate_positional_argument(valdtr, tst, arg, + "annotation-name", arg_index++, + SAAT_STRING)) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) + return FALSE; + + if (sieve_argument_is_string_literal(arg)) { + string_t *aname = sieve_ast_argument_str(arg); + + if (!imap_metadata_verify_entry_name(str_c(aname), &error)) { + sieve_argument_validate_warning( + valdtr, arg, "%s test: " + "specified annotation name `%s' is invalid: %s", + sieve_command_identifier(tst), + str_sanitize(str_c(aname), 256), + sieve_error_from_external(error)); + } + } + + arg = sieve_ast_argument_next(arg); + + /* key-list */ + if (!sieve_validate_positional_argument(valdtr, tst, arg, + "key-list", arg_index++, + SAAT_STRING_LIST)) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate(valdtr, tst, arg, + &mcht_default, &cmp_default); +} + +/* + * Test generation + */ + +static bool +tst_metadata_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *tst) +{ + if (sieve_command_is(tst, metadata_test)) { + sieve_operation_emit(cgenv->sblock, tst->ext, + &metadata_operation); + } else if (sieve_command_is(tst, servermetadata_test)) { + sieve_operation_emit(cgenv->sblock, tst->ext, + &servermetadata_operation); + } else { + i_unreached(); + } + + /* Generate arguments */ + if (!sieve_generate_arguments(cgenv, tst, NULL)) + return FALSE; + return TRUE; +} + +/* + * Code dump + */ + +static bool +tst_metadata_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + bool metadata = sieve_operation_is(denv->oprtn, metadata_operation); + + if (metadata) + sieve_code_dumpf(denv, "METADATA"); + else + sieve_code_dumpf(denv, "SERVERMETADATA"); + + sieve_code_descend(denv); + + /* Handle any optional arguments */ + if (sieve_match_opr_optional_dump(denv, address, NULL) != 0) + return FALSE; + if (metadata && !sieve_opr_string_dump(denv, address, "mailbox")) + return FALSE; + + return (sieve_opr_string_dump(denv, address, "annotation-name") && + sieve_opr_stringlist_dump(denv, address, "key list")); +} + +/* + * Code execution + */ + +static int +tst_metadata_get_annotation(const struct sieve_runtime_env *renv, + const char *mailbox, const char *aname, + const char **annotation_r) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct mail_user *user = eenv->scriptenv->user; + struct mailbox *box; + struct imap_metadata_transaction *imtrans; + struct mail_attribute_value avalue; + int status, ret; + + *annotation_r = NULL; + + if (user == NULL) + return SIEVE_EXEC_OK; + + if (mailbox != NULL) { + struct mail_namespace *ns; + ns = mail_namespace_find(user->namespaces, mailbox); + box = mailbox_alloc(ns->list, mailbox, 0); + imtrans = imap_metadata_transaction_begin(box); + } else { + box = NULL; + imtrans = imap_metadata_transaction_begin_server(user); + } + + status = SIEVE_EXEC_OK; + ret = imap_metadata_get(imtrans, aname, &avalue); + if (ret < 0) { + enum mail_error error_code; + const char *error; + + error = imap_metadata_transaction_get_last_error( + imtrans, &error_code); + + sieve_runtime_error( + renv, NULL, "%s test: " + "failed to retrieve annotation `%s': %s%s", + (mailbox != NULL ? "metadata" : "servermetadata"), + str_sanitize(aname, 256), + sieve_error_from_external(error), + (error_code == MAIL_ERROR_TEMP ? + " (temporary failure)" : "")); + + status = (error_code == MAIL_ERROR_TEMP ? + SIEVE_EXEC_TEMP_FAILURE : SIEVE_EXEC_FAILURE); + + } else if (avalue.value != NULL) { + *annotation_r = avalue.value; + } + (void)imap_metadata_transaction_commit(&imtrans, NULL, NULL); + if (box != NULL) + mailbox_free(&box); + return status; +} + +static int +tst_metadata_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + bool metadata = sieve_operation_is(renv->oprtn, metadata_operation); + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + string_t *mailbox, *aname; + struct sieve_stringlist *value_list, *key_list; + const char *annotation = NULL, *error; + int match, ret; + + /* + * Read operands + */ + + /* Handle match-type and comparator operands */ + if (sieve_match_opr_optional_read(renv, address, NULL, + &ret, &cmp, &mcht) < 0) + return ret; + + /* Read mailbox */ + if (metadata) { + ret = sieve_opr_string_read(renv, address, "mailbox", &mailbox); + if (ret <= 0) + return ret; + } + + /* Read annotation-name */ + ret = sieve_opr_string_read(renv, address, "annotation-name", &aname); + if (ret <= 0) + return ret; + + /* Read key-list */ + ret = sieve_opr_stringlist_read(renv, address, "key-list", &key_list); + if (ret <= 0) + return ret; + + /* + * Perform operation + */ + + if (metadata) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "metadata test"); + } else { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "servermetadata test"); + } + sieve_runtime_trace_descend(renv); + + if (!imap_metadata_verify_entry_name(str_c(aname), &error)) { + sieve_runtime_warning( + renv, NULL, "%s test: " + "specified annotation name `%s' is invalid: %s", + (metadata ? "metadata" : "servermetadata"), + str_sanitize(str_c(aname), 256), + sieve_error_from_external(error)); + sieve_interpreter_set_test_result(renv->interp, FALSE); + return SIEVE_EXEC_OK; + } + + if (metadata) { + if (!sieve_mailbox_check_name(str_c(mailbox), &error)) { + sieve_runtime_warning( + renv, NULL, "metadata test: " + "invalid mailbox name `%s' specified: %s", + str_sanitize(str_c(mailbox), 256), error); + sieve_interpreter_set_test_result(renv->interp, FALSE); + return SIEVE_EXEC_OK; + } + + sieve_runtime_trace( + renv, SIEVE_TRLVL_TESTS, + "retrieving annotation `%s' from mailbox `%s'", + str_sanitize(str_c(aname), 256), + str_sanitize(str_c(mailbox), 80)); + } else { + sieve_runtime_trace( + renv, SIEVE_TRLVL_TESTS, + "retrieving server annotation `%s'", + str_sanitize(str_c(aname), 256)); + } + + /* Get annotation */ + ret = tst_metadata_get_annotation(renv, + (metadata ? str_c(mailbox) : NULL), + str_c(aname), &annotation); + if (ret == SIEVE_EXEC_OK) { + /* Perform match */ + if (annotation != NULL) { + /* Create value stringlist */ + value_list = sieve_single_stringlist_create_cstr( + renv, annotation, FALSE); + + /* Perform match */ + match = sieve_match(renv, &mcht, &cmp, + value_list, key_list, &ret); + if (ret < 0) + return ret; + } else { + match = 0; + } + } + + /* Set test result for subsequent conditional jump */ + if (ret == SIEVE_EXEC_OK) + sieve_interpreter_set_test_result(renv->interp, match > 0); + return ret; +} diff --git a/pigeonhole/src/lib-sieve/plugins/metadata/tst-metadataexists.c b/pigeonhole/src/lib-sieve/plugins/metadata/tst-metadataexists.c new file mode 100644 index 0000000..e11d692 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/metadata/tst-metadataexists.c @@ -0,0 +1,431 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" +#include "mail-storage.h" +#include "mail-namespace.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-metadata-common.h" + +/* + * Command definitions + */ + +/* Forward declarations */ + +static bool +tst_metadataexists_validate(struct sieve_validator *valdtr, + struct sieve_command *tst); +static bool +tst_metadataexists_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +/* Metadataexists command + * + * Syntax: + * metadataexists <mailbox: string> <annotation-names: string-list> + */ + +static bool +tst_metadataexists_validate(struct sieve_validator *valdtr, + struct sieve_command *tst); +static bool +tst_metadataexists_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def metadataexists_test = { + .identifier = "metadataexists", + .type = SCT_TEST, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = tst_metadataexists_validate, + .generate = tst_metadataexists_generate, +}; + +/* Servermetadataexists command + * + * Syntax: + * servermetadataexists <annotation-names: string-list> + */ + +const struct sieve_command_def servermetadataexists_test = { + .identifier = "servermetadataexists", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = tst_metadataexists_validate, + .generate = tst_metadataexists_generate, +}; + +/* + * Opcode definitions + */ + +static bool +tst_metadataexists_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +tst_metadataexists_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +/* Metadata operation */ + +const struct sieve_operation_def metadataexists_operation = { + .mnemonic = "METADATAEXISTS", + .ext_def = &mboxmetadata_extension, + .code = EXT_METADATA_OPERATION_METADATAEXISTS, + .dump = tst_metadataexists_operation_dump, + .execute = tst_metadataexists_operation_execute, +}; + +/* Mailboxexists operation */ + +const struct sieve_operation_def servermetadataexists_operation = { + .mnemonic = "SERVERMETADATAEXISTS", + .ext_def = &servermetadata_extension, + .code = EXT_METADATA_OPERATION_METADATAEXISTS, + .dump = tst_metadataexists_operation_dump, + .execute = tst_metadataexists_operation_execute, +}; + +/* + * Test validation + */ + +struct _validate_context { + struct sieve_validator *valdtr; + struct sieve_command *tst; +}; + +static int +tst_metadataexists_annotation_validate(void *context, + struct sieve_ast_argument *arg) +{ + struct _validate_context *valctx = + (struct _validate_context *)context; + + if (sieve_argument_is_string_literal(arg)) { + const char *aname = sieve_ast_strlist_strc(arg); + const char *error; + + if (!imap_metadata_verify_entry_name(aname, &error)) { + sieve_argument_validate_warning( + valctx->valdtr, arg, "%s test: " + "specified annotation name `%s' is invalid: %s", + sieve_command_identifier(valctx->tst), + str_sanitize(aname, 256), + sieve_error_from_external(error)); + } + } + return 1; /* Can't check at compile time */ +} + +static bool +tst_metadataexists_validate(struct sieve_validator *valdtr, + struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + struct sieve_ast_argument *aarg; + struct _validate_context valctx; + unsigned int arg_index = 1; + + if (sieve_command_is(tst, metadataexists_test)) { + if (!sieve_validate_positional_argument(valdtr, tst, arg, + "mailbox", arg_index++, + SAAT_STRING)) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) + return FALSE; + + /* Check name validity when mailbox argument is not a variable */ + if (sieve_argument_is_string_literal(arg)) { + const char *mailbox = sieve_ast_argument_strc(arg); + const char *error; + + if (!sieve_mailbox_check_name(mailbox, &error)) { + sieve_argument_validate_warning( + valdtr, arg, "%s test: " + "invalid mailbox name `%s' specified: %s", + sieve_command_identifier(tst), + str_sanitize(mailbox, 256), error); + } + } + arg = sieve_ast_argument_next(arg); + } + + if (!sieve_validate_positional_argument(valdtr, tst, arg, + "annotation-names", arg_index++, + SAAT_STRING_LIST)) + return FALSE; + if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) + return FALSE; + + aarg = arg; + i_zero(&valctx); + valctx.valdtr = valdtr; + valctx.tst = tst; + + return (sieve_ast_stringlist_map( + &aarg, (void*)&valctx, + tst_metadataexists_annotation_validate) >= 0); +} + +/* + * Test generation + */ + +static bool +tst_metadataexists_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *tst) +{ + if (sieve_command_is(tst, metadataexists_test)) { + sieve_operation_emit(cgenv->sblock, tst->ext, + &metadataexists_operation); + } else if (sieve_command_is(tst, servermetadataexists_test)) { + sieve_operation_emit(cgenv->sblock, tst->ext, + &servermetadataexists_operation); + } else { + i_unreached(); + } + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool +tst_metadataexists_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + bool metadata = sieve_operation_is(denv->oprtn, + metadataexists_operation); + + if (metadata) + sieve_code_dumpf(denv, "METADATAEXISTS"); + else + sieve_code_dumpf(denv, "SERVERMETADATAEXISTS"); + + sieve_code_descend(denv); + + if (metadata && !sieve_opr_string_dump(denv, address, "mailbox")) + return FALSE; + + return sieve_opr_stringlist_dump(denv, address, "annotation-names"); +} + +/* + * Code execution + */ + +static int +tst_metadataexists_check_annotation(const struct sieve_runtime_env *renv, + struct imap_metadata_transaction *imtrans, + const char *mailbox, const char *aname, + bool *all_exist_r) +{ + struct mail_attribute_value avalue; + const char *error; + int ret; + + if (!imap_metadata_verify_entry_name(aname, &error)) { + sieve_runtime_warning( + renv, NULL, "%s test: " + "specified annotation name `%s' is invalid: %s", + (mailbox != NULL ? + "metadataexists" : "servermetadataexists"), + str_sanitize(aname, 256), + sieve_error_from_external(error)); + *all_exist_r = FALSE; + return SIEVE_EXEC_OK; + } + + ret = imap_metadata_get(imtrans, aname, &avalue); + if (ret < 0) { + enum mail_error error_code; + const char *error; + + error = imap_metadata_transaction_get_last_error( + imtrans, &error_code); + sieve_runtime_error( + renv, NULL, "%s test: " + "failed to retrieve annotation `%s': %s%s", + (mailbox != NULL ? + "metadataexists" : "servermetadataexists"), + str_sanitize(aname, 256), + sieve_error_from_external(error), + (error_code == MAIL_ERROR_TEMP ? + " (temporary failure)" : "")); + + *all_exist_r = FALSE; + return (error_code == MAIL_ERROR_TEMP ? + SIEVE_EXEC_TEMP_FAILURE : SIEVE_EXEC_FAILURE); + } + if (avalue.value == NULL && avalue.value_stream == NULL) { + sieve_runtime_trace(renv, 0, + "annotation `%s': not found", aname); + *all_exist_r = FALSE; + } + + sieve_runtime_trace(renv, 0, "annotation `%s': found", aname); + return SIEVE_EXEC_OK; +} + +static int +tst_metadataexists_check_annotations(const struct sieve_runtime_env *renv, + const char *mailbox, + struct sieve_stringlist *anames, + bool *all_exist_r) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct mail_user *user = eenv->scriptenv->user; + struct mailbox *box = NULL; + struct imap_metadata_transaction *imtrans; + string_t *aname; + bool all_exist = TRUE; + int ret, sret, status; + + *all_exist_r = FALSE; + + if (user == NULL) + return SIEVE_EXEC_OK; + + if (mailbox != NULL) { + struct mail_namespace *ns; + ns = mail_namespace_find(user->namespaces, mailbox); + box = mailbox_alloc(ns->list, mailbox, 0); + imtrans = imap_metadata_transaction_begin(box); + } else { + imtrans = imap_metadata_transaction_begin_server(user); + } + + if (mailbox != NULL) { + sieve_runtime_trace( + renv, SIEVE_TRLVL_TESTS, + "checking annotations of mailbox `%s':", + str_sanitize(mailbox, 80)); + } else { + sieve_runtime_trace( + renv, SIEVE_TRLVL_TESTS, + "checking server annotations"); + } + + aname = NULL; + status = SIEVE_EXEC_OK; + while (all_exist && + (sret = sieve_stringlist_next_item(anames, &aname)) > 0) { + ret = tst_metadataexists_check_annotation( + renv, imtrans, mailbox, str_c(aname), &all_exist); + if (ret <= 0) { + status = ret; + break; + } + } + + if (sret < 0) { + sieve_runtime_trace_error( + renv, "invalid annotation name stringlist item"); + status = SIEVE_EXEC_BIN_CORRUPT; + } + + (void)imap_metadata_transaction_commit(&imtrans, NULL, NULL); + if (box != NULL) + mailbox_free(&box); + + *all_exist_r = all_exist; + return status; +} + +static int +tst_metadataexists_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + bool metadata = sieve_operation_is(renv->oprtn, + metadataexists_operation); + struct sieve_stringlist *anames; + string_t *mailbox; + bool trace = FALSE, all_exist = TRUE; + const char *error; + int ret; + + /* + * Read operands + */ + + /* Read mailbox */ + if (metadata) { + ret = sieve_opr_string_read(renv, address, "mailbox", &mailbox); + if (ret <= 0) + return ret; + } + + /* Read annotation names */ + ret = sieve_opr_stringlist_read(renv, address, "annotation-names", + &anames); + if (ret <= 0) + return ret; + + /* + * Perform operation + */ + + if (metadata && + !sieve_mailbox_check_name(str_c(mailbox), &error)) { + sieve_runtime_warning( + renv, NULL, "metadataexists test: " + "invalid mailbox name `%s' specified: %s", + str_sanitize(str_c(mailbox), 256), error); + sieve_interpreter_set_test_result(renv->interp, FALSE); + return SIEVE_EXEC_OK; + } + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_TESTS)) { + if (metadata) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "metadataexists test"); + } else { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "servermetadataexists test"); + } + + sieve_runtime_trace_descend(renv); + + trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); + } + + ret = tst_metadataexists_check_annotations( + renv, (metadata ? str_c(mailbox) : NULL), anames, &all_exist); + if (ret <= 0) + return ret; + + if (trace) { + if (all_exist) { + sieve_runtime_trace(renv, 0, + "all annotations exist"); + } else { + sieve_runtime_trace(renv, 0, + "some annotations do not exist"); + } + } + + sieve_interpreter_set_test_result(renv->interp, all_exist); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/mime/Makefile.am b/pigeonhole/src/lib-sieve/plugins/mime/Makefile.am new file mode 100644 index 0000000..8ded659 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/Makefile.am @@ -0,0 +1,30 @@ +noinst_LTLIBRARIES = libsieve_ext_mime.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../util \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-foreverypart.c \ + cmd-break.c \ + cmd-extracttext.c + +tags = \ + tag-mime.c + +extensions = \ + ext-mime.c \ + ext-foreverypart.c \ + ext-extracttext.c + +libsieve_ext_mime_la_SOURCES = \ + ext-mime-common.c \ + $(commands) \ + $(tags) \ + $(extensions) + +noinst_HEADERS = \ + ext-mime-common.h + diff --git a/pigeonhole/src/lib-sieve/plugins/mime/Makefile.in b/pigeonhole/src/lib-sieve/plugins/mime/Makefile.in new file mode 100644 index 0000000..cfe25ff --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/Makefile.in @@ -0,0 +1,727 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/mime +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_mime_la_LIBADD = +am__objects_1 = cmd-foreverypart.lo cmd-break.lo cmd-extracttext.lo +am__objects_2 = tag-mime.lo +am__objects_3 = ext-mime.lo ext-foreverypart.lo ext-extracttext.lo +am_libsieve_ext_mime_la_OBJECTS = ext-mime-common.lo $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) +libsieve_ext_mime_la_OBJECTS = $(am_libsieve_ext_mime_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/cmd-break.Plo \ + ./$(DEPDIR)/cmd-extracttext.Plo \ + ./$(DEPDIR)/cmd-foreverypart.Plo \ + ./$(DEPDIR)/ext-extracttext.Plo \ + ./$(DEPDIR)/ext-foreverypart.Plo \ + ./$(DEPDIR)/ext-mime-common.Plo ./$(DEPDIR)/ext-mime.Plo \ + ./$(DEPDIR)/tag-mime.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_mime_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_mime_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_mime.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../util \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-foreverypart.c \ + cmd-break.c \ + cmd-extracttext.c + +tags = \ + tag-mime.c + +extensions = \ + ext-mime.c \ + ext-foreverypart.c \ + ext-extracttext.c + +libsieve_ext_mime_la_SOURCES = \ + ext-mime-common.c \ + $(commands) \ + $(tags) \ + $(extensions) + +noinst_HEADERS = \ + ext-mime-common.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/mime/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/mime/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_mime.la: $(libsieve_ext_mime_la_OBJECTS) $(libsieve_ext_mime_la_DEPENDENCIES) $(EXTRA_libsieve_ext_mime_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_mime_la_OBJECTS) $(libsieve_ext_mime_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-break.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-extracttext.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-foreverypart.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-extracttext.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-foreverypart.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-mime-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-mime.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tag-mime.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-break.Plo + -rm -f ./$(DEPDIR)/cmd-extracttext.Plo + -rm -f ./$(DEPDIR)/cmd-foreverypart.Plo + -rm -f ./$(DEPDIR)/ext-extracttext.Plo + -rm -f ./$(DEPDIR)/ext-foreverypart.Plo + -rm -f ./$(DEPDIR)/ext-mime-common.Plo + -rm -f ./$(DEPDIR)/ext-mime.Plo + -rm -f ./$(DEPDIR)/tag-mime.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/cmd-break.Plo + -rm -f ./$(DEPDIR)/cmd-extracttext.Plo + -rm -f ./$(DEPDIR)/cmd-foreverypart.Plo + -rm -f ./$(DEPDIR)/ext-extracttext.Plo + -rm -f ./$(DEPDIR)/ext-foreverypart.Plo + -rm -f ./$(DEPDIR)/ext-mime-common.Plo + -rm -f ./$(DEPDIR)/ext-mime.Plo + -rm -f ./$(DEPDIR)/tag-mime.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/mime/cmd-break.c b/pigeonhole/src/lib-sieve/plugins/mime/cmd-break.c new file mode 100644 index 0000000..e6ade4c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/cmd-break.c @@ -0,0 +1,273 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-binary.h" +#include "sieve-dump.h" + +#include "ext-mime-common.h" + +#include <ctype.h> + +/* break + * + * Syntax: + * break [":name" <name: string>] + * + */ + +static bool cmd_break_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool cmd_break_pre_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_break_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_break_generate + (const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def cmd_break = { + .identifier = "break", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_break_registered, + .pre_validate = cmd_break_pre_validate, + .validate = cmd_break_validate, + .generate = cmd_break_generate, +}; + +/* + * Tagged arguments + */ + +/* Forward declarations */ + +static bool cmd_break_validate_name_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +/* Argument objects */ + +static const struct sieve_argument_def break_name_tag = { + .identifier = "name", + .validate = cmd_break_validate_name_tag +}; + +/* + * Break operation + */ + +static bool cmd_break_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_break_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def break_operation = { + .mnemonic = "BREAK", + .ext_def = &foreverypart_extension, + .code = EXT_FOREVERYPART_OPERATION_BREAK, + .dump = cmd_break_operation_dump, + .execute = cmd_break_operation_execute +}; + +/* + * Validation data + */ + +struct cmd_break_data { + struct sieve_ast_argument *name; + struct sieve_command *loop_cmd; +}; + +/* + * Tag validation + */ + +static bool cmd_break_validate_name_tag +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct cmd_break_data *data = + (struct cmd_break_data *)cmd->data; + struct sieve_ast_argument *tag = *arg; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + /* Check syntax: + * :name <string> + */ + if ( !sieve_validate_tag_parameter + (valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING, TRUE) ) + return FALSE; + data->name = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + return TRUE; +} + +/* + * Command registration + */ + +static bool cmd_break_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &break_name_tag, 0); + + return TRUE; +} + +/* + * Command validation + */ + +static bool cmd_break_pre_validate +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command *cmd) +{ + struct cmd_break_data *data; + pool_t pool = sieve_command_pool(cmd); + + data = p_new(pool, struct cmd_break_data, 1); + cmd->data = data; + return TRUE; +} + +static bool cmd_break_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct cmd_break_data *data = + (struct cmd_break_data *)cmd->data; + struct sieve_ast_node *node = cmd->ast_node; + const char *name = ( data->name == NULL ? + NULL : sieve_ast_argument_strc(data->name) ); + + i_assert(node != NULL); + while ( node != NULL && node->command != NULL ) { + if ( sieve_command_is(node->command, cmd_foreverypart) ) { + struct ext_foreverypart_loop *loop = + (struct ext_foreverypart_loop *)node->command->data; + if ( name == NULL || + (name != NULL && loop->name != NULL && + strcmp(name, loop->name) == 0) ) { + data->loop_cmd = node->command; + break; + } + } + node = sieve_ast_node_parent(node); + } + + if ( data->loop_cmd == NULL ) { + if ( name == NULL ) { + sieve_command_validate_error(valdtr, cmd, + "the break command is not placed inside " + "a foreverypart loop"); + } else { + sieve_command_validate_error(valdtr, cmd, + "the break command is not placed inside " + "a foreverypart loop named `%s'", + name); + } + return FALSE; + } + + sieve_command_exit_block_unconditionally(cmd); + return TRUE; +} + +/* + * Code generation + */ + +static bool cmd_break_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + struct cmd_break_data *data = + (struct cmd_break_data *)cmd->data; + struct ext_foreverypart_loop *loop; + + i_assert( data->loop_cmd != NULL ); + loop = (struct ext_foreverypart_loop *)data->loop_cmd->data; + + sieve_operation_emit(cgenv->sblock, cmd->ext, &break_operation); + sieve_jumplist_add(loop->exit_jumps, + sieve_binary_emit_offset(cgenv->sblock, 0)); + return TRUE; +} + +/* + * Code dump + */ + +static bool cmd_break_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + unsigned int pc = *address; + sieve_offset_t offset; + + sieve_code_dumpf(denv, "BREAK"); + sieve_code_descend(denv); + + if ( !sieve_binary_read_offset(denv->sblock, address, &offset) ) + return FALSE; + + sieve_code_dumpf(denv, "END: %d [%08x]", offset, pc + offset); + return TRUE; +} + +/* + * Code execution + */ + +static int cmd_break_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_interpreter_loop *loop; + unsigned int pc = *address; + sieve_offset_t offset; + sieve_size_t loop_end; + + /* + * Read operands + */ + + if ( !sieve_binary_read_offset(renv->sblock, address, &offset) ) + { + sieve_runtime_trace_error(renv, "invalid loop end offset"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + loop_end = pc + offset; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "break command"); + sieve_runtime_trace_descend(renv); + + loop = sieve_interpreter_loop_get + (renv->interp, loop_end, &foreverypart_extension); + if ( loop == NULL ) { + sieve_runtime_trace_error(renv, "no matching loop found"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + sieve_interpreter_loop_break(renv->interp, loop); + return SIEVE_EXEC_OK; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/mime/cmd-extracttext.c b/pigeonhole/src/lib-sieve/plugins/mime/cmd-extracttext.c new file mode 100644 index 0000000..d9b31a2 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/cmd-extracttext.c @@ -0,0 +1,370 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-code.h" +#include "sieve-ast.h" +#include "sieve-commands.h" +#include "sieve-binary.h" +#include "sieve-message.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "ext-mime-common.h" + +/* + * Extracttext command + * + * Syntax: + * extracttext [MODIFIER] [":first" number] <varname: string> + */ + +static bool cmd_extracttext_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool cmd_extracttext_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_extracttext_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def cmd_extracttext = { + .identifier = "extracttext", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_extracttext_registered, + .validate = cmd_extracttext_validate, + .generate = cmd_extracttext_generate +}; + +/* + * Extracttext command tags + */ + +enum cmd_extracttext_optional { + CMD_EXTRACTTEXT_OPT_END, + CMD_EXTRACTTEXT_OPT_FIRST +}; + +static bool cmd_extracttext_validate_first_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +static const struct sieve_argument_def extracttext_from_tag = { + .identifier = "first", + .validate = cmd_extracttext_validate_first_tag +}; + +/* + * Extracttext operation + */ + +static bool cmd_extracttext_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_extracttext_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def extracttext_operation = { + .mnemonic = "EXTRACTTEXT", + .ext_def = &extracttext_extension, + .dump = cmd_extracttext_operation_dump, + .execute = cmd_extracttext_operation_execute +}; + +/* + * Compiler context + */ + +struct cmd_extracttext_context { + ARRAY_TYPE(sieve_variables_modifier) modifiers; +}; + +/* + * Tag validation + */ + +static bool cmd_extracttext_validate_first_tag +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :first <number> + */ + if ( !sieve_validate_tag_parameter + (valdtr, cmd, tag, *arg, NULL, 0, SAAT_NUMBER, FALSE) ) + return FALSE; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* Command registration */ + +static bool cmd_extracttext_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + struct ext_extracttext_context *ectx = + (struct ext_extracttext_context *)ext->context; + + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &extracttext_from_tag, CMD_EXTRACTTEXT_OPT_FIRST); + sieve_variables_modifiers_link_tag + (valdtr, ectx->var_ext, cmd_reg); + return TRUE; +} + +/* + * Command validation + */ + +static bool cmd_extracttext_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct ext_extracttext_context *ectx = + (struct ext_extracttext_context *)this_ext->context; + struct sieve_ast_node *node = cmd->ast_node; + struct sieve_ast_argument *arg = cmd->first_positional; + pool_t pool = sieve_command_pool(cmd); + struct cmd_extracttext_context *sctx; + + /* Create command context */ + sctx = p_new(pool, struct cmd_extracttext_context, 1); + p_array_init(&sctx->modifiers, pool, 4); + cmd->data = (void *) sctx; + + /* Validate modifiers */ + if ( !sieve_variables_modifiers_validate + (valdtr, cmd, &sctx->modifiers) ) + return FALSE; + + /* Validate varname argument */ + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "varname", 1, SAAT_STRING) ) { + return FALSE; + } + if ( !sieve_variable_argument_activate + (ectx->var_ext, ectx->var_ext, valdtr, cmd, arg, TRUE) ) + return FALSE; + + /* Check foreverypart context */ + i_assert(node != NULL); + while ( node != NULL ) { + if ( node->command != NULL && + sieve_command_is(node->command, cmd_foreverypart) ) + break; + node = sieve_ast_node_parent(node); + } + + if ( node == NULL ) { + sieve_command_validate_error(valdtr, cmd, + "the extracttext command is not placed inside " + "a foreverypart loop"); + return FALSE; + } + return TRUE; +} + +/* + * Code generation + */ + +static bool cmd_extracttext_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct sieve_binary_block *sblock = cgenv->sblock; + struct cmd_extracttext_context *sctx = + (struct cmd_extracttext_context *) cmd->data; + + sieve_operation_emit(sblock, this_ext, &extracttext_operation); + + /* Generate arguments */ + if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) + return FALSE; + + /* Generate modifiers */ + if ( !sieve_variables_modifiers_generate + (cgenv, &sctx->modifiers) ) + return FALSE; + + return TRUE; +} + +/* + * Code dump + */ + +static bool cmd_extracttext_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "EXTRACTTEXT"); + sieve_code_descend(denv); + + /* Dump optional operands */ + + for (;;) { + int opt; + bool opok = TRUE; + + if ( (opt=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + if ( opt == 0 ) break; + + switch ( opt_code ) { + case CMD_EXTRACTTEXT_OPT_FIRST: + opok = sieve_opr_number_dump(denv, address, "first"); + break; + default: + return FALSE; + } + if ( !opok ) return FALSE; + } + + /* Print both variable name and string value */ + if ( !sieve_opr_string_dump(denv, address, "varname") ) + return FALSE; + + return sieve_variables_modifiers_code_dump(denv, address); +} + +/* + * Code execution + */ + +static int cmd_extracttext_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct ext_extracttext_context *ectx = + (struct ext_extracttext_context *)this_ext->context; + struct sieve_variable_storage *storage; + ARRAY_TYPE(sieve_variables_modifier) modifiers; + struct ext_foreverypart_runtime_loop *sfploop; + struct sieve_message_part *mpart; + struct sieve_message_part_data mpart_data; + int opt_code = 0; + sieve_number_t first = 0; + string_t *value; + unsigned int var_index; + bool have_first = FALSE; + int ret = SIEVE_EXEC_OK; + + /* + * Read the normal operands + */ + + /* Optional operands */ + + for (;;) { + int opt; + + if ( (opt=sieve_opr_optional_read + (renv, address, &opt_code)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + if ( opt == 0 ) break; + + switch ( opt_code ) { + case CMD_EXTRACTTEXT_OPT_FIRST: + ret = sieve_opr_number_read + (renv, address, "first", &first); + have_first = TRUE; + break; + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + if ( ret <= 0 ) return ret; + } + + /* Varname operand */ + + if ( (ret=sieve_variable_operand_read + (renv, address, "varname", &storage, &var_index)) <= 0 ) + return ret; + + /* Modifiers */ + + if ( (ret=sieve_variables_modifiers_code_read + (renv, ectx->var_ext, address, &modifiers)) <= 0 ) + return ret; + + /* + * Determine and assign the value + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "extracttext command"); + sieve_runtime_trace_descend(renv); + + sfploop = ext_foreverypart_runtime_loop_get_current(renv); + if ( sfploop == NULL ) { + sieve_runtime_trace_error(renv, + "outside foreverypart context"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + /* Get current message part */ + mpart = sieve_message_part_iter_current(&sfploop->part_iter); + i_assert( mpart != NULL ); + + /* Get message part content */ + sieve_message_part_get_data(mpart, &mpart_data, TRUE); + + /* Apply ":first" limit, if any */ + if ( !have_first || (size_t)first > mpart_data.size ) { + value = t_str_new_const(mpart_data.content, mpart_data.size); + } else { + value = t_str_new((size_t)first); + str_append_data(value, mpart_data.content, (size_t)first); + } + + /* Apply modifiers */ + if ( (ret=sieve_variables_modifiers_apply + (renv, ectx->var_ext, &modifiers, &value)) <= 0 ) + return ret; + + /* Actually assign the value if all is well */ + i_assert ( value != NULL ); + if ( !sieve_variable_assign(storage, var_index, value) ) + return SIEVE_EXEC_BIN_CORRUPT; + + /* Trace */ + if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) { + const char *var_name, *var_id; + + (void)sieve_variable_get_identifier(storage, var_index, &var_name); + var_id = sieve_variable_get_varid(storage, var_index); + + sieve_runtime_trace_here(renv, 0, "assign `%s' [%s] = \"%s\"", + var_name, var_id, str_c(value)); + } + + return SIEVE_EXEC_OK; +} + + + + + + diff --git a/pigeonhole/src/lib-sieve/plugins/mime/cmd-foreverypart.c b/pigeonhole/src/lib-sieve/plugins/mime/cmd-foreverypart.c new file mode 100644 index 0000000..435cb5c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/cmd-foreverypart.c @@ -0,0 +1,377 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-limits.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-binary.h" +#include "sieve-dump.h" +#include "sieve-message.h" + +#include "ext-mime-common.h" + +#include <ctype.h> + +/* Foreverypart + * + * Syntax: + * foreverypart [":name" <name: string>] <block> + * + */ + +static bool cmd_foreverypart_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool cmd_foreverypart_pre_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_foreverypart_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_foreverypart_generate + (const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def cmd_foreverypart = { + .identifier = "foreverypart", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = TRUE, + .block_required = TRUE, + .registered = cmd_foreverypart_registered, + .pre_validate = cmd_foreverypart_pre_validate, + .validate = cmd_foreverypart_validate, + .generate = cmd_foreverypart_generate +}; + +/* + * Tagged arguments + */ + +/* Forward declarations */ + +static bool cmd_foreverypart_validate_name_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +/* Argument objects */ + +static const struct sieve_argument_def foreverypart_name_tag = { + .identifier = "name", + .validate = cmd_foreverypart_validate_name_tag, +}; + +/* + * foreverypart operation + */ + +static bool cmd_foreverypart_begin_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_foreverypart_begin_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def foreverypart_begin_operation = { + .mnemonic = "FOREVERYPART_BEGIN", + .ext_def = &foreverypart_extension, + .code = EXT_FOREVERYPART_OPERATION_FOREVERYPART_BEGIN, + .dump = cmd_foreverypart_begin_operation_dump, + .execute = cmd_foreverypart_begin_operation_execute +}; + +static bool cmd_foreverypart_end_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_foreverypart_end_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def foreverypart_end_operation = { + .mnemonic = "FOREVERYPART_END", + .ext_def = &foreverypart_extension, + .code = EXT_FOREVERYPART_OPERATION_FOREVERYPART_END, + .dump = cmd_foreverypart_end_operation_dump, + .execute = cmd_foreverypart_end_operation_execute +}; + +/* + * Tag validation + */ + +static bool cmd_foreverypart_validate_name_tag +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct ext_foreverypart_loop *loop = + (struct ext_foreverypart_loop *)cmd->data; + struct sieve_ast_argument *tag = *arg; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + /* Check syntax: + * :name <string> + */ + if ( !sieve_validate_tag_parameter + (valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING, TRUE) ) + return FALSE; + loop->name = sieve_ast_argument_strc(*arg); + + /* Detach parameter */ + *arg = sieve_ast_arguments_detach(*arg, 1); + return TRUE; +} + +/* + * Command registration + */ + +static bool cmd_foreverypart_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &foreverypart_name_tag, 0); + return TRUE; +} + +/* + * Command validation + */ + +static bool cmd_foreverypart_pre_validate +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command *cmd) +{ + struct ext_foreverypart_loop *loop; + pool_t pool = sieve_command_pool(cmd); + + loop = p_new(pool, struct ext_foreverypart_loop, 1); + cmd->data = loop; + + return TRUE; +} + +static bool cmd_foreverypart_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_ast_node *node = cmd->ast_node; + unsigned int nesting = 0; + + /* Determine nesting depth of foreverypart commands at this point. */ + i_assert(node != NULL); + node = sieve_ast_node_parent(node); + while ( node != NULL && node->command != NULL ) { + if ( sieve_command_is(node->command, cmd_foreverypart) ) + nesting++; + node = sieve_ast_node_parent(node); + } + + /* Enforce nesting limit + NOTE: this only recognizes the foreverypart command as a loop; if + new loop commands are introduced in the future, these must be + recognized somehow. */ + if ( nesting + 1 > SIEVE_MAX_LOOP_DEPTH ) { + sieve_command_validate_error(valdtr, cmd, + "the nested foreverypart loop exceeds " + "the nesting limit (<= %u levels)", + SIEVE_MAX_LOOP_DEPTH); + return FALSE; + } + + return TRUE; +} + +/* + * Code generation + */ + +static bool cmd_foreverypart_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + struct ext_foreverypart_loop *loop = + (struct ext_foreverypart_loop *)cmd->data; + sieve_size_t block_begin, loop_jump; + + /* Emit FOREVERYPART_BEGIN operation */ + sieve_operation_emit(cgenv->sblock, + cmd->ext, &foreverypart_begin_operation); + + /* Emit exit address */ + loop->exit_jumps = sieve_jumplist_create + (sieve_command_pool(cmd), cgenv->sblock); + sieve_jumplist_add(loop->exit_jumps, + sieve_binary_emit_offset(cgenv->sblock, 0)); + block_begin = sieve_binary_block_get_size(cgenv->sblock); + + /* Generate loop block */ + if ( !sieve_generate_block(cgenv, cmd->ast_node) ) + return FALSE; + + /* Emit FOREVERYPART_END operation */ + sieve_operation_emit(cgenv->sblock, + cmd->ext, &foreverypart_end_operation); + loop_jump = sieve_binary_block_get_size(cgenv->sblock); + i_assert(loop_jump > block_begin); + (void)sieve_binary_emit_offset + (cgenv->sblock, (loop_jump - block_begin)); + + /* Resolve exit address */ + sieve_jumplist_resolve(loop->exit_jumps); + + return TRUE; +} + +/* + * Code dump + */ + +static bool cmd_foreverypart_begin_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + unsigned int pc = *address; + sieve_offset_t offset; + + sieve_code_dumpf(denv, "FOREVERYPART_BEGIN"); + sieve_code_descend(denv); + + if ( !sieve_binary_read_offset(denv->sblock, address, &offset) ) + return FALSE; + + sieve_code_dumpf(denv, "END: %d [%08x]", offset, pc + offset); + return TRUE; +} + +static bool cmd_foreverypart_end_operation_dump +(const struct sieve_dumptime_env *denv, + sieve_size_t *address ATTR_UNUSED) +{ + unsigned int pc = *address; + sieve_offset_t offset; + + sieve_code_dumpf(denv, "FOREVERYPART_END"); + sieve_code_descend(denv); + + if ( !sieve_binary_read_offset(denv->sblock, address, &offset) ) + return FALSE; + + sieve_code_dumpf(denv, "BEGIN: -%d [%08x]", offset, pc - offset); + return TRUE; +} + +/* + * Code execution + */ + +static int cmd_foreverypart_begin_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_interpreter_loop *loop; + struct ext_foreverypart_runtime_loop *fploop, *sfploop; + unsigned int pc = *address; + sieve_offset_t offset; + sieve_size_t loop_end; + pool_t pool; + int ret; + + /* + * Read operands + */ + + if ( !sieve_binary_read_offset(renv->sblock, address, &offset) ) + { + sieve_runtime_trace_error(renv, "invalid loop end offset"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + loop_end = pc + offset; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "foreverypart loop begin"); + sieve_runtime_trace_descend(renv); + + sfploop = ext_foreverypart_runtime_loop_get_current(renv); + + if ( (ret=sieve_interpreter_loop_start(renv->interp, + loop_end, &foreverypart_extension, &loop)) <= 0 ) + return ret; + + pool = sieve_interpreter_loop_get_pool(loop); + fploop = p_new(pool, struct ext_foreverypart_runtime_loop, 1); + + if ( sfploop == NULL ) { + if ( (ret=sieve_message_part_iter_init + (&fploop->part_iter, renv)) <= 0 ) + return ret; + } else { + sieve_message_part_iter_children(&sfploop->part_iter, + &fploop->part_iter); + } + fploop->part = sieve_message_part_iter_current(&fploop->part_iter); + if (fploop->part != NULL) { + sieve_interpreter_loop_set_context(loop, (void*)fploop); + } else { + /* No children parts to iterate */ + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "no children at this level"); + sieve_interpreter_loop_break(renv->interp, loop); + } + return SIEVE_EXEC_OK; +} + +static int cmd_foreverypart_end_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_interpreter_loop *loop; + struct ext_foreverypart_runtime_loop *fploop; + unsigned int pc = *address; + sieve_offset_t offset; + sieve_size_t loop_begin; + + /* + * Read operands + */ + + if ( !sieve_binary_read_offset(renv->sblock, address, &offset) ) + { + sieve_runtime_trace_error(renv, "invalid loop begin offset"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + loop_begin = pc - offset; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, + SIEVE_TRLVL_COMMANDS, "foreverypart loop end"); + sieve_runtime_trace_descend(renv); + + loop = sieve_interpreter_loop_get + (renv->interp, *address, &foreverypart_extension); + if ( loop == NULL ) { + sieve_runtime_trace_error(renv, "no matching loop found"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + fploop = (struct ext_foreverypart_runtime_loop *) + sieve_interpreter_loop_get_context(loop); + i_assert(fploop->part != NULL); + fploop->part = sieve_message_part_iter_next(&fploop->part_iter); + if ( fploop->part == NULL ) { + sieve_runtime_trace(renv, + SIEVE_TRLVL_COMMANDS, "no more message parts"); + return sieve_interpreter_loop_break(renv->interp, loop); + } + + sieve_runtime_trace(renv, + SIEVE_TRLVL_COMMANDS, "switched to next message part"); + return sieve_interpreter_loop_next(renv->interp, loop, loop_begin); +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/mime/ext-extracttext.c b/pigeonhole/src/lib-sieve/plugins/mime/ext-extracttext.c new file mode 100644 index 0000000..4eab76b --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/ext-extracttext.c @@ -0,0 +1,130 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension extracttext + * --------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5703, Section 7 + * Implementation: full + * Status: experimental + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "sieve-ext-variables.h" + +#include "ext-mime-common.h" + +/* + * Extension + */ + +static bool ext_extracttext_load + (const struct sieve_extension *ext, void **context); +static void ext_extracttext_unload + (const struct sieve_extension *ext); +static bool ext_extracttext_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def extracttext_extension = { + .name = "extracttext", + .load = ext_extracttext_load, + .unload = ext_extracttext_unload, + .validator_load = ext_extracttext_validator_load, + SIEVE_EXT_DEFINE_OPERATION(extracttext_operation) +}; + +static bool ext_extracttext_load +(const struct sieve_extension *ext, void **context) +{ + struct sieve_instance *svinst = ext->svinst; + struct ext_extracttext_context *ectx; + + if ( *context != NULL ) + ext_extracttext_unload(ext); + + ectx = i_new(struct ext_extracttext_context, 1); + ectx->var_ext = sieve_ext_variables_get_extension(ext->svinst); + ectx->fep_ext = sieve_extension_register + (svinst, &foreverypart_extension, FALSE); + *context = (void *)ectx; + return TRUE; +} + +static void ext_extracttext_unload +(const struct sieve_extension *ext) +{ + struct ext_extracttext_context *ctx = + (struct ext_extracttext_context *) ext->context; + + i_free(ctx); +} + +/* + * Extension validation + */ + +static bool ext_extracttext_validator_validate + (const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + bool required); + +const struct sieve_validator_extension +extracttext_validator_extension = { + .ext = &extracttext_extension, + .validate = ext_extracttext_validator_validate +}; + +static bool ext_extracttext_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register validator extension to check for conflict with eextracttext */ + sieve_validator_extension_register + (valdtr, ext, &extracttext_validator_extension, NULL); + + /* Register new commands */ + sieve_validator_register_command(valdtr, ext, &cmd_extracttext); + + return TRUE; +} + +static bool ext_extracttext_validator_validate +(const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg, + bool required ATTR_UNUSED) +{ + struct ext_extracttext_context *ectx = + (struct ext_extracttext_context *)ext->context; + + if ( ectx->var_ext == NULL || + !sieve_ext_variables_is_active + (ectx->var_ext, valdtr) ) { + sieve_argument_validate_error(valdtr, require_arg, + "extracttext extension cannot be used " + "without variables extension"); + return FALSE; + } + if ( ectx->fep_ext == NULL || + !sieve_validator_extension_loaded + (valdtr, ectx->fep_ext) ) { + sieve_argument_validate_error(valdtr, require_arg, + "extracttext extension cannot be used " + "without foreverypart extension"); + return FALSE; + } + + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/mime/ext-foreverypart.c b/pigeonhole/src/lib-sieve/plugins/mime/ext-foreverypart.c new file mode 100644 index 0000000..6bca199 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/ext-foreverypart.c @@ -0,0 +1,62 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension foreverypart + * ---------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5703, Section 3 + * Implementation: full + * Status: experimental + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "ext-mime-common.h" + +/* + * Operations + */ + +const struct sieve_operation_def *ext_foreverypart_operations[] = { + &foreverypart_begin_operation, + &foreverypart_end_operation, + &break_operation +}; + +/* + * Extension + */ + +static bool ext_foreverypart_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def foreverypart_extension = { + .name = "foreverypart", + .validator_load = ext_foreverypart_validator_load, + SIEVE_EXT_DEFINE_OPERATIONS(ext_foreverypart_operations) +}; + +/* + * Extension validation + */ + +static bool ext_foreverypart_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register new commands */ + sieve_validator_register_command(valdtr, ext, &cmd_foreverypart); + sieve_validator_register_command(valdtr, ext, &cmd_break); + + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/mime/ext-mime-common.c b/pigeonhole/src/lib-sieve/plugins/mime/ext-mime-common.c new file mode 100644 index 0000000..5b38bcb --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/ext-mime-common.c @@ -0,0 +1,27 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-interpreter.h" + +#include "ext-mime-common.h" + +struct ext_foreverypart_runtime_loop * +ext_foreverypart_runtime_loop_get_current +(const struct sieve_runtime_env *renv) +{ + struct sieve_interpreter_loop *loop; + struct ext_foreverypart_runtime_loop *fploop; + + loop = sieve_interpreter_loop_get_global + (renv->interp, NULL, &foreverypart_extension); + if ( loop == NULL ) { + fploop = NULL; + } else { + fploop = (struct ext_foreverypart_runtime_loop *) + sieve_interpreter_loop_get_context(loop); + i_assert(fploop->part != NULL); + } + + return fploop; +} diff --git a/pigeonhole/src/lib-sieve/plugins/mime/ext-mime-common.h b/pigeonhole/src/lib-sieve/plugins/mime/ext-mime-common.h new file mode 100644 index 0000000..8b0054d --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/ext-mime-common.h @@ -0,0 +1,85 @@ +#ifndef EXT_FOREVERYPART_COMMON_H +#define EXT_FOREVERYPART_COMMON_H + +#include "sieve-message.h" + +/* + * Extension + */ + +struct ext_extracttext_context { + const struct sieve_extension *var_ext; + const struct sieve_extension *fep_ext; +}; + +extern const struct sieve_extension_def foreverypart_extension; +extern const struct sieve_extension_def mime_extension; +extern const struct sieve_extension_def extracttext_extension; + +/* + * Tagged arguments + */ + +extern const struct sieve_argument_def mime_tag; +extern const struct sieve_argument_def mime_anychild_tag; +extern const struct sieve_argument_def mime_type_tag; +extern const struct sieve_argument_def mime_subtype_tag; +extern const struct sieve_argument_def mime_contenttype_tag; +extern const struct sieve_argument_def mime_param_tag; + +/* + * Commands + */ + +struct ext_foreverypart_loop { + const char *name; + struct sieve_jumplist *exit_jumps; +}; + +extern const struct sieve_command_def cmd_foreverypart; +extern const struct sieve_command_def cmd_break; +extern const struct sieve_command_def cmd_extracttext; + +/* + * Operations + */ + +extern const struct sieve_operation_def foreverypart_begin_operation; +extern const struct sieve_operation_def foreverypart_end_operation; +extern const struct sieve_operation_def break_operation; +extern const struct sieve_operation_def extracttext_operation; + +enum ext_foreverypart_opcode { + EXT_FOREVERYPART_OPERATION_FOREVERYPART_BEGIN, + EXT_FOREVERYPART_OPERATION_FOREVERYPART_END, + EXT_FOREVERYPART_OPERATION_BREAK, +}; + +/* + * Operands + */ + +enum ext_mime_option { + EXT_MIME_OPTION_NONE = 0, + EXT_MIME_OPTION_TYPE, + EXT_MIME_OPTION_SUBTYPE, + EXT_MIME_OPTION_CONTENTTYPE, + EXT_MIME_OPTION_PARAM +}; + +extern const struct sieve_operand_def mime_operand; + +/* + * Foreverypart loop + */ + +struct ext_foreverypart_runtime_loop { + struct sieve_message_part_iter part_iter; + struct sieve_message_part *part; +}; + +struct ext_foreverypart_runtime_loop * +ext_foreverypart_runtime_loop_get_current +(const struct sieve_runtime_env *renv); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/mime/ext-mime.c b/pigeonhole/src/lib-sieve/plugins/mime/ext-mime.c new file mode 100644 index 0000000..da9963f --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/ext-mime.c @@ -0,0 +1,77 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension mime + * -------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5703, Section 4 + * Implementation: full + * Status: experimental + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-message.h" +#include "sieve-result.h" + +#include "ext-mime-common.h" + +/* + * Extension + */ + +static bool ext_mime_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def mime_extension = { + .name = "mime", + .validator_load = ext_mime_validator_load, + SIEVE_EXT_DEFINE_OPERAND(mime_operand) +}; + +/* + * Extension validation + */ + +static bool ext_mime_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register :mime tag and friends with header, address and exists test + * commands and we don't care whether these command are registered or + * even whether these will be registered at all. The validator handles + * either situation gracefully. + */ + sieve_validator_register_external_tag + (valdtr, "header", ext, &mime_tag, SIEVE_OPT_MESSAGE_OVERRIDE); + sieve_validator_register_external_tag + (valdtr, "header", ext, &mime_anychild_tag, 0); + sieve_validator_register_external_tag + (valdtr, "header", ext, &mime_type_tag, 0); + sieve_validator_register_external_tag + (valdtr, "header", ext, &mime_subtype_tag, 0); + sieve_validator_register_external_tag + (valdtr, "header", ext, &mime_contenttype_tag, 0); + sieve_validator_register_external_tag + (valdtr, "header", ext, &mime_param_tag, 0); + + sieve_validator_register_external_tag + (valdtr, "address", ext, &mime_tag, SIEVE_OPT_MESSAGE_OVERRIDE); + sieve_validator_register_external_tag + (valdtr, "address", ext, &mime_anychild_tag, 0); + + sieve_validator_register_external_tag + (valdtr, "exists", ext, &mime_tag, SIEVE_OPT_MESSAGE_OVERRIDE); + sieve_validator_register_external_tag + (valdtr, "exists", ext, &mime_anychild_tag, 0); + + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/mime/tag-mime.c b/pigeonhole/src/lib-sieve/plugins/mime/tag-mime.c new file mode 100644 index 0000000..379365e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/tag-mime.c @@ -0,0 +1,757 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "rfc822-parser.h" +#include "rfc2231-parser.h" +#include "mail-storage.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-result.h" +#include "sieve-validator.h" +#include "sieve-generator.h" + +#include "ext-mime-common.h" + +/* + * Tagged argument + */ + +static bool tag_mime_validate + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool tag_mime_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *context); + +const struct sieve_argument_def mime_tag = { + .identifier = "mime", + .validate = tag_mime_validate, + .generate = tag_mime_generate +}; + +static bool tag_mime_option_validate + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +const struct sieve_argument_def mime_anychild_tag = { + .identifier = "anychild", + .validate = tag_mime_option_validate +}; + +const struct sieve_argument_def mime_type_tag = { + .identifier = "type", + .validate = tag_mime_option_validate +}; + +const struct sieve_argument_def mime_subtype_tag = { + .identifier = "subtype", + .validate = tag_mime_option_validate +}; + +const struct sieve_argument_def mime_contenttype_tag = { + .identifier = "contenttype", + .validate = tag_mime_option_validate +}; + +const struct sieve_argument_def mime_param_tag = { + .identifier = "param", + .validate = tag_mime_option_validate +}; + +/* + * Header override + */ + +static bool svmo_mime_dump_context + (const struct sieve_message_override *svmo, + const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int svmo_mime_read_context + (const struct sieve_message_override *svmo, + const struct sieve_runtime_env *renv, sieve_size_t *address, + void **ho_context); +static int svmo_mime_header_override + (const struct sieve_message_override *svmo, + const struct sieve_runtime_env *renv, + bool mime_decode, struct sieve_stringlist **headers); + +const struct sieve_message_override_def mime_header_override = { + SIEVE_OBJECT("mime", &mime_operand, 0), + .sequence = 0, /* Completely replace header source */ + .dump_context = svmo_mime_dump_context, + .read_context = svmo_mime_read_context, + .header_override = svmo_mime_header_override +}; + +/* + * Operand + */ + +static const struct sieve_extension_objects ext_header_overrides = + SIEVE_EXT_DEFINE_MESSAGE_OVERRIDE(mime_header_override); + +const struct sieve_operand_def mime_operand = { + .name = "mime operand", + .ext_def = &mime_extension, + .class = &sieve_message_override_operand_class, + .interface = &ext_header_overrides +}; + +/* + * Tag data + */ + +struct tag_mime_data { + enum ext_mime_option mimeopt; + struct sieve_ast_argument *param_arg; + bool anychild:1; +}; + +/* + * Tag validation + */ + +static struct tag_mime_data * +tag_mime_get_data(struct sieve_command *cmd, + struct sieve_ast_argument *tag) +{ + struct tag_mime_data *data; + + if (tag->argument->data == NULL) { + data = p_new(sieve_command_pool(cmd), struct tag_mime_data, 1); + tag->argument->data = (void *)data; + } else { + data = (struct tag_mime_data *)tag->argument->data; + } + + return data; +} + +static bool tag_mime_validate +(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_ast_argument **arg, struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + + /* Skip the tag itself */ + *arg = sieve_ast_argument_next(*arg); + + (void)tag_mime_get_data(cmd, tag); + return TRUE; +} + +static bool tag_mime_option_validate +(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_ast_argument **arg, struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct sieve_ast_argument *mime_arg; + struct tag_mime_data *data; + + i_assert(tag != NULL); + + /* Detach tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Find required ":mime" tag */ + mime_arg = sieve_command_find_argument(cmd, &mime_tag); + if ( mime_arg == NULL ) { + sieve_argument_validate_error(valdtr, tag, + "the :%s tag for the %s %s cannot be specified " + "without the :mime tag", sieve_ast_argument_tag(tag), + sieve_command_identifier(cmd), sieve_command_type_name(cmd)); + return FALSE; + } + + /* Annotate ":mime" tag with the data provided by this option tag */ + data = tag_mime_get_data(cmd, mime_arg); + if ( sieve_argument_is(tag, mime_anychild_tag) ) + data->anychild = TRUE; + else { + if ( data->mimeopt != EXT_MIME_OPTION_NONE ) { + sieve_argument_validate_error(valdtr, *arg, + "the :type, :subtype, :contenttype, and :param " + "arguments for the %s test are mutually exclusive, " + "but more than one was specified", + sieve_command_identifier(cmd)); + return FALSE; + } + if ( sieve_argument_is(tag, mime_type_tag) ) + data->mimeopt = EXT_MIME_OPTION_TYPE; + else if ( sieve_argument_is(tag, mime_subtype_tag) ) + data->mimeopt = EXT_MIME_OPTION_SUBTYPE; + else if ( sieve_argument_is(tag, mime_contenttype_tag) ) + data->mimeopt = EXT_MIME_OPTION_CONTENTTYPE; + else if ( sieve_argument_is(tag, mime_param_tag) ) { + /* Check syntax: + * ":param" <param-list: string-list> + */ + if ( !sieve_validate_tag_parameter + (valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING_LIST, FALSE) ) { + return FALSE; + } + + data->mimeopt = EXT_MIME_OPTION_PARAM; + data->param_arg = *arg; + + /* Detach parameter */ + *arg = sieve_ast_arguments_detach(*arg,1); + } else + i_unreached(); + } + return TRUE; +} + +/* + * Code generation + */ + +static bool tag_mime_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd) +{ + struct tag_mime_data *data = + (struct tag_mime_data *)arg->argument->data; + + if ( sieve_ast_argument_type(arg) != SAAT_TAG ) + return FALSE; + + sieve_opr_message_override_emit + (cgenv->sblock, arg->argument->ext, &mime_header_override); + + (void)sieve_binary_emit_byte + (cgenv->sblock, ( data->anychild ? 1 : 0 )); + (void)sieve_binary_emit_byte + (cgenv->sblock, data->mimeopt); + if ( data->mimeopt == EXT_MIME_OPTION_PARAM && + !sieve_generate_argument(cgenv, data->param_arg, cmd) ) + return FALSE; + return TRUE; +} + +/* + * Content-type stringlist + */ + +enum content_type_part { + CONTENT_TYPE_PART_NONE = 0, + CONTENT_TYPE_PART_TYPE, + CONTENT_TYPE_PART_SUBTYPE, + CONTENT_TYPE_PART_CONTENTTYPE, +}; + +/* Object */ + +static int content_header_stringlist_next_item + (struct sieve_stringlist *_strlist, string_t **str_r); +static void content_header_stringlist_reset + (struct sieve_stringlist *_strlist); +static int content_header_stringlist_get_length + (struct sieve_stringlist *_strlist); +static void content_header_stringlist_set_trace + (struct sieve_stringlist *strlist, bool trace); + +struct content_header_stringlist { + struct sieve_stringlist strlist; + + struct sieve_header_list *source; + + enum ext_mime_option option; + const char *const *params; + + const char *const *param_values; +}; + +static struct sieve_stringlist *content_header_stringlist_create +(const struct sieve_runtime_env *renv, + struct sieve_header_list *source, + enum ext_mime_option option, const char *const *params) +{ + struct content_header_stringlist *strlist; + + strlist = t_new(struct content_header_stringlist, 1); + strlist->strlist.runenv = renv; + strlist->strlist.exec_status = SIEVE_EXEC_OK; + strlist->strlist.next_item = content_header_stringlist_next_item; + strlist->strlist.reset = content_header_stringlist_reset; + strlist->strlist.set_trace = content_header_stringlist_set_trace; + strlist->source = source; + strlist->option = option; + strlist->params = params; + + if ( option != EXT_MIME_OPTION_PARAM ) { + /* One header can have multiple parameters, so we cannot rely + on the source length for the :param option. */ + strlist->strlist.get_length = content_header_stringlist_get_length; + } + + return &strlist->strlist; +} + +/* Implementation */ + +static inline int _decode_hex_digit(const unsigned char digit) +{ + switch ( digit ) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return digit - '0'; + + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + return digit - 'a' + 0x0a; + + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + return digit - 'A' + 0x0A; + } + return -1; +} + +static string_t * +content_type_param_decode(const char *value) +{ + const unsigned char *p, *plast; + + string_t *str = t_str_new(64); + plast = p = (const unsigned char *)value; + while ( *p != '\0' ) { + unsigned char ch; + int digit; + + if ( *p == '%' ) { + if ( p - plast > 0 ) + str_append_data(str, plast, (p - plast)); + p++; + if ( *p == '\0' || (digit=_decode_hex_digit(*p)) < 0 ) + return NULL; + ch = (unsigned char)digit; + p++; + if ( *p == '\0' || (digit=_decode_hex_digit(*p)) < 0 ) + return NULL; + ch = (ch << 4) + (unsigned char)digit; + str_append_data(str, &ch, 1); + plast = p + 1; + } + p++; + } + if ( p - plast > 0 ) + str_append_data(str, plast, (p - plast)); + return str; +} + +static string_t * +content_type_param_next(struct content_header_stringlist *strlist) +{ + const struct sieve_runtime_env *renv = strlist->strlist.runenv; + const char *const *values = strlist->param_values; + bool trace = strlist->strlist.trace; + + i_assert( strlist->params != NULL ); + + /* Iterate over all parsed parameter values */ + for ( ; *values != NULL; values += 2 ) { + const char *const *params = strlist->params; + const char *name = values[0], *value = values[1]; + size_t nlen = strlen(name); + + /* Iterate over all interesting parameter names */ + for ( ; *params != NULL; params++ ) { + size_t plen = strlen(*params); + + if ( plen != nlen && + (nlen != plen + 1 || name[nlen-1] != '*') ) + continue; + + if ( plen == nlen ) { + if ( strcasecmp(name, *params) == 0 ) { + /* Return raw value */ + if ( trace ) { + sieve_runtime_trace(renv, 0, + "found mime parameter `%s' in mime header", + *params); + } + + strlist->param_values = values + 2; + return t_str_new_const(value, strlen(value)); + } + } else { + if ( trace ) { + sieve_runtime_trace(renv, 0, + "found encoded parameter `%s' in mime header", + *params); + } + + if ( strncasecmp(name, *params, plen) == 0 ) { + string_t *result = NULL; + + strlist->param_values = values + 2; + + /* Decode value first */ + // FIXME: transcode charset + value = strchr(value, '\''); + if (value != NULL) + value = strchr(value+1, '\''); + if (value != NULL) + result = content_type_param_decode(value + 1); + if (result == NULL) + strlist->param_values = NULL; + return result; + } + } + } + } + + strlist->param_values = NULL; + return NULL; +} + +// FIXME: not too happy with the use of string_t like this. +// Sieve should have a special runtime string type (TODO) +static string_t * +content_header_parse(struct content_header_stringlist *strlist, + const char *hdr_name, string_t *str) +{ + const struct sieve_runtime_env *renv = strlist->strlist.runenv; + bool trace = strlist->strlist.trace; + struct rfc822_parser_context parser; + const char *type, *p; + bool is_ctype = FALSE; + string_t *content; + + if ( strlist->option == EXT_MIME_OPTION_NONE ) + return str; + + if ( strcasecmp(hdr_name, "content-type") == 0 ) + is_ctype = TRUE; + else if ( strcasecmp(hdr_name, "content-disposition") != 0 ) { + if ( trace ) { + sieve_runtime_trace(renv, 0, + "non-mime header yields empty string"); + } + return t_str_new(0); + } + + /* Initialize parsing */ + rfc822_parser_init(&parser, str_data(str), str_len(str), NULL); + (void)rfc822_skip_lwsp(&parser); + + /* Parse content type/disposition */ + content = t_str_new(64); + if ( is_ctype ){ + if (rfc822_parse_content_type(&parser, content) < 0) { + str_truncate(content, 0); + return content; + } + } else { + if (rfc822_parse_mime_token(&parser, content) < 0) { + str_truncate(content, 0); + return content; + } + } + + /* Content-type value must end here, otherwise it is invalid after all */ + (void)rfc822_skip_lwsp(&parser); + if ( parser.data != parser.end && *parser.data != ';' ) { + str_truncate(content, 0); + return content; + } + + if ( strlist->option == EXT_MIME_OPTION_PARAM ) { + string_t *param_val; + + /* MIME parameter */ + i_assert( strlist->params != NULL ); + + // FIXME: not very nice when multiple parameters in the same header + // are queried in successive tests. + str_truncate(content, 0); + rfc2231_parse(&parser, &strlist->param_values); + + param_val = content_type_param_next(strlist); + if ( param_val != NULL ) + content = param_val; + } else { + /* Get :type/:subtype:/:contenttype value */ + type = str_c(content); + p = strchr(type, '/'); + switch ( strlist->option ) { + case EXT_MIME_OPTION_TYPE: + if ( trace ) { + sieve_runtime_trace(renv, 0, + "extracted MIME type"); + } + if ( p != NULL ) { + i_assert( is_ctype ); + str_truncate(content, (p - type)); + } + break; + case EXT_MIME_OPTION_SUBTYPE: + if ( p == NULL ) { + i_assert( !is_ctype ); + if ( trace ) { + sieve_runtime_trace(renv, 0, + "no MIME sub-type for content-disposition"); + } + str_truncate(content, 0); + break; + } + + i_assert( is_ctype ); + if ( trace ) { + sieve_runtime_trace(renv, 0, + "extracted MIME sub-type"); + } + str_delete(content, 0, (p - type) + 1); + break; + case EXT_MIME_OPTION_CONTENTTYPE: + sieve_runtime_trace(renv, 0, + "extracted full MIME contenttype"); + break; + default: + break; + } + } + + /* Success */ + return content; +} + +static int content_header_stringlist_next_item +(struct sieve_stringlist *_strlist, string_t **str_r) +{ + struct content_header_stringlist *strlist = + (struct content_header_stringlist *)_strlist; + const char *hdr_name; + int ret; + + if ( strlist->param_values != NULL ) { + string_t *param_val; + + i_assert( strlist->option == EXT_MIME_OPTION_PARAM ); + param_val = content_type_param_next(strlist); + if ( param_val != NULL ) { + *str_r = param_val; + return 1; + } + } + + if ( (ret=sieve_header_list_next_item + (strlist->source, &hdr_name, str_r)) <= 0 ) { + if (ret < 0) { + _strlist->exec_status = + strlist->source->strlist.exec_status; + } + return ret; + } + + *str_r = content_header_parse(strlist, hdr_name, *str_r); + return 1; +} + +static void content_header_stringlist_reset +(struct sieve_stringlist *_strlist) +{ + struct content_header_stringlist *strlist = + (struct content_header_stringlist *)_strlist; + sieve_header_list_reset(strlist->source); +} + +static int content_header_stringlist_get_length +(struct sieve_stringlist *_strlist) +{ + struct content_header_stringlist *strlist = + (struct content_header_stringlist *)_strlist; + return sieve_header_list_get_length(strlist->source); +} + +static void content_header_stringlist_set_trace +(struct sieve_stringlist *_strlist, bool trace) +{ + struct content_header_stringlist *strlist = + (struct content_header_stringlist *)_strlist; + sieve_header_list_set_trace(strlist->source, trace); +} + +/* + * Header override implementation + */ + +/* Context data */ + +struct svmo_mime_context { + enum ext_mime_option mimeopt; + const char *const *params; + bool anychild:1; +}; + +/* Context coding */ + +static bool svmo_mime_dump_context +(const struct sieve_message_override *svmo ATTR_UNUSED, + const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + unsigned int anychild, mimeopt; + + if ( !sieve_binary_read_byte(denv->sblock, address, &anychild) ) + return FALSE; + if ( anychild > 0 ) + sieve_code_dumpf(denv, "anychild"); + + if ( !sieve_binary_read_byte(denv->sblock, address, &mimeopt) ) + return FALSE; + + switch ( mimeopt ) { + case EXT_MIME_OPTION_NONE: + break; + case EXT_MIME_OPTION_TYPE: + sieve_code_dumpf(denv, "option: type"); + break; + case EXT_MIME_OPTION_SUBTYPE: + sieve_code_dumpf(denv, "option: subtype"); + break; + case EXT_MIME_OPTION_CONTENTTYPE: + sieve_code_dumpf(denv, "option: contenttype"); + break; + case EXT_MIME_OPTION_PARAM: + sieve_code_dumpf(denv, "option: param"); + sieve_code_descend(denv); + if ( !sieve_opr_stringlist_dump(denv, address, "param-list") ) + return FALSE; + sieve_code_ascend(denv); + break; + default: + return FALSE; + } + return TRUE; +} + +static int svmo_mime_read_context +(const struct sieve_message_override *svmo ATTR_UNUSED, + const struct sieve_runtime_env *renv, sieve_size_t *address, + void **ho_context) +{ + pool_t pool = sieve_result_pool(renv->result); // FIXME: investigate + struct svmo_mime_context *ctx; + unsigned int anychild = 0, mimeopt = EXT_MIME_OPTION_NONE; + struct sieve_stringlist *param_list = NULL; + int ret; + + if ( !sieve_binary_read_byte + (renv->sblock, address, &anychild) ) { + sieve_runtime_trace_error(renv, + "anychild: invalid byte"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( !sieve_binary_read_byte + (renv->sblock, address, &mimeopt) || + mimeopt > EXT_MIME_OPTION_PARAM ) { + sieve_runtime_trace_error(renv, + "option: invalid mime option code"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( mimeopt == EXT_MIME_OPTION_PARAM && + (ret=sieve_opr_stringlist_read + (renv, address, "param-list", ¶m_list)) <= 0 ) + return ret; + + ctx = p_new(pool, struct svmo_mime_context, 1); + ctx->anychild = (anychild == 0 ? FALSE : TRUE); + ctx->mimeopt = (enum ext_mime_option)mimeopt; + + if ( param_list != NULL && sieve_stringlist_read_all + (param_list, pool, &ctx->params) < 0 ) { + sieve_runtime_trace_error(renv, + "failed to read param-list operand"); + return param_list->exec_status; + } + + *ho_context = (void *) ctx; + return SIEVE_EXEC_OK; +} + +/* Override */ + +static int svmo_mime_header_override +(const struct sieve_message_override *svmo, + const struct sieve_runtime_env *renv, bool mime_decode, + struct sieve_stringlist **headers_r) +{ + struct svmo_mime_context *ctx = + (struct svmo_mime_context *)svmo->context; + struct ext_foreverypart_runtime_loop *sfploop; + struct sieve_header_list *headers; + struct sieve_stringlist *values; + int ret; + + sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, + "header mime override:"); + sieve_runtime_trace_descend(renv); + + if ( ctx->anychild ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, + "headers from current mime part and children"); + } else { + sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, + "headers from current mime part"); + } + + sfploop = ext_foreverypart_runtime_loop_get_current(renv); + if ( sfploop != NULL ) { + headers = sieve_mime_header_list_create + (renv, *headers_r, &sfploop->part_iter, + mime_decode, ctx->anychild); + } else if ( ctx->anychild ) { + struct sieve_message_part_iter part_iter; + + if ( (ret=sieve_message_part_iter_init + (&part_iter, renv)) <= 0 ) + return ret; + + headers = sieve_mime_header_list_create + (renv, *headers_r, &part_iter, mime_decode, TRUE); + } else { + headers = sieve_message_header_list_create + (renv, *headers_r, mime_decode); + } + values = &headers->strlist; + + switch ( ctx->mimeopt ) { + case EXT_MIME_OPTION_NONE: + break; + case EXT_MIME_OPTION_TYPE: + sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, + "extract mime type from header value"); + break; + case EXT_MIME_OPTION_SUBTYPE: + sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, + "extract mime subtype from header value"); + break; + case EXT_MIME_OPTION_CONTENTTYPE: + sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, + "extract mime contenttype from header value"); + break; + case EXT_MIME_OPTION_PARAM: + sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, + "extract mime parameters from header value"); + break; + default: + i_unreached(); + } + + if ( ctx->mimeopt != EXT_MIME_OPTION_NONE ) { + values = content_header_stringlist_create + (renv, headers, ctx->mimeopt, ctx->params); + } + *headers_r = values; + + sieve_runtime_trace_ascend(renv); + return SIEVE_EXEC_OK; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/notify/Makefile.am b/pigeonhole/src/lib-sieve/plugins/notify/Makefile.am new file mode 100644 index 0000000..aaa76b3 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/notify/Makefile.am @@ -0,0 +1,20 @@ +noinst_LTLIBRARIES = libsieve_ext_notify.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../util \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-notify.c \ + cmd-denotify.c + +libsieve_ext_notify_la_SOURCES = \ + ext-notify.c \ + ext-notify-common.c \ + $(commands) + +noinst_HEADERS = \ + ext-notify-common.h \ + ext-notify-limits.h + diff --git a/pigeonhole/src/lib-sieve/plugins/notify/Makefile.in b/pigeonhole/src/lib-sieve/plugins/notify/Makefile.in new file mode 100644 index 0000000..910007d --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/notify/Makefile.in @@ -0,0 +1,699 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/notify +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_notify_la_LIBADD = +am__objects_1 = cmd-notify.lo cmd-denotify.lo +am_libsieve_ext_notify_la_OBJECTS = ext-notify.lo ext-notify-common.lo \ + $(am__objects_1) +libsieve_ext_notify_la_OBJECTS = $(am_libsieve_ext_notify_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/cmd-denotify.Plo \ + ./$(DEPDIR)/cmd-notify.Plo ./$(DEPDIR)/ext-notify-common.Plo \ + ./$(DEPDIR)/ext-notify.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_notify_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_notify_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_notify.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../util \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-notify.c \ + cmd-denotify.c + +libsieve_ext_notify_la_SOURCES = \ + ext-notify.c \ + ext-notify-common.c \ + $(commands) + +noinst_HEADERS = \ + ext-notify-common.h \ + ext-notify-limits.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/notify/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/notify/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_notify.la: $(libsieve_ext_notify_la_OBJECTS) $(libsieve_ext_notify_la_DEPENDENCIES) $(EXTRA_libsieve_ext_notify_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_notify_la_OBJECTS) $(libsieve_ext_notify_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-denotify.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-notify.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-notify-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-notify.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-denotify.Plo + -rm -f ./$(DEPDIR)/cmd-notify.Plo + -rm -f ./$(DEPDIR)/ext-notify-common.Plo + -rm -f ./$(DEPDIR)/ext-notify.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/cmd-denotify.Plo + -rm -f ./$(DEPDIR)/cmd-notify.Plo + -rm -f ./$(DEPDIR)/ext-notify-common.Plo + -rm -f ./$(DEPDIR)/ext-notify.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/notify/cmd-denotify.c b/pigeonhole/src/lib-sieve/plugins/notify/cmd-denotify.c new file mode 100644 index 0000000..8769808 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/notify/cmd-denotify.c @@ -0,0 +1,389 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-ast.h" +#include "sieve-commands.h" +#include "sieve-match-types.h" +#include "sieve-comparators.h" +#include "sieve-match.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-result.h" + +#include "ext-notify-common.h" + +/* + * Denotify command + * + * Syntax: + * denotify [MATCH-TYPE string] [<":low" / ":normal" / ":high">] + */ + +static bool cmd_denotify_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool cmd_denotify_pre_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_denotify_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_denotify_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + +const struct sieve_command_def cmd_denotify = { + .identifier = "denotify", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_denotify_registered, + .pre_validate = cmd_denotify_pre_validate, + .validate = cmd_denotify_validate, + .generate = cmd_denotify_generate +}; + +/* + * Tagged arguments + */ + +/* Forward declarations */ + +static bool tag_match_type_is_instance_of + (struct sieve_validator *validator, struct sieve_command *cmd, + const struct sieve_extension *ext, const char *identifier, void **data); +static bool tag_match_type_validate + (struct sieve_validator *validator, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +/* Argument object */ + +const struct sieve_argument_def denotify_match_tag = { + .identifier = "MATCH-TYPE-STRING", + .is_instance_of = tag_match_type_is_instance_of, + .validate = tag_match_type_validate +}; + +/* Codes for optional operands */ + +enum cmd_denotify_optional { + OPT_END, + OPT_IMPORTANCE, + OPT_MATCH_TYPE, + OPT_MATCH_KEY +}; + +/* + * Denotify operation + */ + +static bool cmd_denotify_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_denotify_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def denotify_operation = { + .mnemonic = "DENOTIFY", + .ext_def = ¬ify_extension, + .code = EXT_NOTIFY_OPERATION_DENOTIFY, + .dump = cmd_denotify_operation_dump, + .execute = cmd_denotify_operation_execute +}; + +/* + * Command validation context + */ + +struct cmd_denotify_context_data { + struct sieve_ast_argument *match_key_arg; +}; + +/* + * Tag validation + */ + +static bool tag_match_type_is_instance_of +(struct sieve_validator *valdtr, struct sieve_command *cmd, + const struct sieve_extension *ext, const char *identifier, void **data) +{ + return match_type_tag.is_instance_of(valdtr, cmd, ext, identifier, data); +} + +static bool tag_match_type_validate +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct cmd_denotify_context_data *cmd_data = + (struct cmd_denotify_context_data *) cmd->data; + struct sieve_ast_argument *tag = *arg; + + i_assert(tag != NULL); + + if ( !match_type_tag.validate(valdtr, arg, cmd) ) + return FALSE; + + if ( *arg == NULL ) { + sieve_argument_validate_error(valdtr, tag, + "the MATCH-TYPE argument (:%s) for the denotify command requires " + "an additional key-string parameter, but no more arguments were found", + sieve_ast_argument_tag(tag)); + return FALSE; + } + + if ( sieve_ast_argument_type(*arg) != SAAT_STRING ) + { + sieve_argument_validate_error(valdtr, *arg, + "the MATCH-TYPE argument (:%s) for the denotify command requires " + "an additional key-string parameter, but %s was found", + sieve_ast_argument_tag(tag), sieve_ast_argument_name(*arg)); + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, cmd, *arg, FALSE) ) + return FALSE; + + tag->argument->def = &match_type_tag; + tag->argument->ext = NULL; + + (*arg)->argument->id_code = OPT_MATCH_KEY; + cmd_data->match_key_arg = *arg; + + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Command registration + */ + +static bool cmd_denotify_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &denotify_match_tag, OPT_MATCH_TYPE); + + ext_notify_register_importance_tags(valdtr, cmd_reg, ext, OPT_IMPORTANCE); + + return TRUE; +} + +/* + * Command validation + */ + +static bool cmd_denotify_pre_validate +(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *cmd) +{ + struct cmd_denotify_context_data *ctx_data; + + /* Assign context */ + ctx_data = p_new(sieve_command_pool(cmd), + struct cmd_denotify_context_data, 1); + cmd->data = (void *) ctx_data; + + return TRUE; +} + +static bool cmd_denotify_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct cmd_denotify_context_data *ctx_data = + (struct cmd_denotify_context_data *) cmd->data; + struct sieve_ast_argument *key_arg = ctx_data->match_key_arg; + const struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_octet_comparator); + + if ( key_arg != NULL ) { + if ( !sieve_match_type_validate + (valdtr, cmd, key_arg, &mcht_default, &cmp_default) ) + return FALSE; + } + + return TRUE; +} + +/* + * Code generation + */ + +static bool cmd_denotify_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &denotify_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool cmd_denotify_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + const struct sieve_operation *op = denv->oprtn; + int opt_code = 0; + + sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(op)); + sieve_code_descend(denv); + + for (;;) { + int opt; + bool opok = TRUE; + + if ( (opt=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_MATCH_KEY: + opok = sieve_opr_string_dump(denv, address, "key-string"); + break; + case OPT_MATCH_TYPE: + opok = sieve_opr_match_type_dump(denv, address); + break; + case OPT_IMPORTANCE: + opok = sieve_opr_number_dump(denv, address, "importance"); + break; + default: + return FALSE; + } + + if ( !opok ) return FALSE; + } + + return TRUE; +} + +/* + * Code execution + */ + +static int cmd_denotify_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + int opt_code = 0; + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_octet_comparator); + struct sieve_stringlist *match_key = NULL; + sieve_number_t importance = 0; + struct sieve_match_context *mctx; + struct sieve_result_iterate_context *rictx; + const struct sieve_action *action; + int ret; + + /* + * Read operands + */ + + /* Optional operands */ + + for (;;) { + int opt; + + if ( (opt=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_MATCH_TYPE: + ret = sieve_opr_match_type_read(renv, address, &mcht); + break; + case OPT_MATCH_KEY: + ret = sieve_opr_stringlist_read(renv, address, "match key", &match_key); + break; + case OPT_IMPORTANCE: + ret = sieve_opr_number_read(renv, address, "importance", &importance); + break; + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( ret <= 0 ) return ret; + } + + /* + * Perform operation + */ + + /* Enforce 0 < importance < 4 (just to be sure) */ + + if ( importance < 1 ) + importance = 1; + else if ( importance > 3 ) + importance = 3; + + /* Trace */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "denotify action"); + + /* Either do string matching or just kill all notify actions */ + if ( match_key != NULL ) { + /* Initialize match */ + mctx = sieve_match_begin(renv, &mcht, &cmp); + + /* Iterate through all notify actions and delete those that match */ + rictx = sieve_result_iterate_init(renv->result); + + while ( (action=sieve_result_iterate_next(rictx, NULL)) != NULL ) { + if ( sieve_action_is(action, act_notify_old) ) { + struct ext_notify_action *nact = + (struct ext_notify_action *) action->context; + + if ( importance == 0 || nact->importance == importance ) { + int match; + + if ( (match=sieve_match_value + (mctx, nact->id, strlen(nact->id), match_key)) < 0 ) + break; + + if ( match > 0 ) + sieve_result_iterate_delete(rictx); + } + } + } + + /* Finish match */ + if ( sieve_match_end(&mctx, &ret) < 0 ) + return ret; + + } else { + /* Delete all notify actions */ + rictx = sieve_result_iterate_init(renv->result); + + while ( (action=sieve_result_iterate_next(rictx, NULL)) != NULL ) { + + if ( sieve_action_is(action, act_notify_old) ) { + struct ext_notify_action *nact = + (struct ext_notify_action *) action->context; + + if ( importance == 0 || nact->importance == importance ) + sieve_result_iterate_delete(rictx); + } + } + } + + return SIEVE_EXEC_OK; +} + + + diff --git a/pigeonhole/src/lib-sieve/plugins/notify/cmd-notify.c b/pigeonhole/src/lib-sieve/plugins/notify/cmd-notify.c new file mode 100644 index 0000000..a683c31 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/notify/cmd-notify.c @@ -0,0 +1,900 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "str.h" +#include "ioloop.h" +#include "str-sanitize.h" +#include "ostream.h" +#include "message-date.h" +#include "mail-storage.h" + +#include "rfc2822.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-result.h" +#include "sieve-address.h" +#include "sieve-message.h" +#include "sieve-smtp.h" + +#include "ext-notify-common.h" +#include "ext-notify-limits.h" + +#include <ctype.h> + +/* Notify command (DEPRECATED) + * + * Syntax: + * notify [":method" string] [":id" string] [":options" string-list] + * [<":low" / ":normal" / ":high">] ["message:" string] + * + */ + +static bool +cmd_notify_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool +cmd_notify_pre_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd); +static bool +cmd_notify_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd); +static bool +cmd_notify_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def cmd_notify_old = { + .identifier = "notify", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_notify_registered, + .pre_validate = cmd_notify_pre_validate, + .validate = cmd_notify_validate, + .generate = cmd_notify_generate +}; + +/* + * Tagged arguments + */ + +/* Forward declarations */ + +static bool +cmd_notify_validate_string_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +cmd_notify_validate_stringlist_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +/* Argument objects */ + +static const struct sieve_argument_def notify_method_tag = { + .identifier = "method", + .validate = cmd_notify_validate_string_tag +}; + +static const struct sieve_argument_def notify_options_tag = { + .identifier = "options", + .validate = cmd_notify_validate_stringlist_tag +}; + +static const struct sieve_argument_def notify_id_tag = { + .identifier = "id", + .validate = cmd_notify_validate_string_tag +}; + +static const struct sieve_argument_def notify_message_tag = { + .identifier = "message", + .validate = cmd_notify_validate_string_tag +}; + +/* + * Notify operation + */ + +static bool +cmd_notify_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_notify_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def notify_old_operation = { + .mnemonic = "NOTIFY", + .ext_def = ¬ify_extension, + .code = EXT_NOTIFY_OPERATION_NOTIFY, + .dump = cmd_notify_operation_dump, + .execute = cmd_notify_operation_execute +}; + +/* Codes for optional operands */ + +enum cmd_notify_optional { + OPT_END, + OPT_MESSAGE, + OPT_IMPORTANCE, + OPT_OPTIONS, + OPT_ID +}; + +/* + * Notify action + */ + +/* Forward declarations */ + +static int +act_notify_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other); +static void +act_notify_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep); +static int +act_notify_commit(const struct sieve_action_exec_env *aenv, + void *tr_context); + +/* Action object */ + +const struct sieve_action_def act_notify_old = { + .name = "notify", + .check_duplicate = act_notify_check_duplicate, + .print = act_notify_print, + .commit = act_notify_commit +}; + +/* + * Command validation context + */ + +struct cmd_notify_context_data { + struct sieve_ast_argument *id; + struct sieve_ast_argument *method; + struct sieve_ast_argument *options; + struct sieve_ast_argument *message; +}; + +/* + * Tag validation + */ + +static bool +cmd_notify_validate_string_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct cmd_notify_context_data *ctx_data = + (struct cmd_notify_context_data *)cmd->data; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + /* Check syntax: + * :id <string> + * :method <string> + * :message <string> + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING, FALSE)) + return FALSE; + + if (sieve_argument_is(tag, notify_method_tag)) { + ctx_data->method = *arg; + + /* Removed */ + *arg = sieve_ast_arguments_detach(*arg, 1); + } else if (sieve_argument_is(tag, notify_id_tag)) { + ctx_data->id = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + } else if (sieve_argument_is(tag, notify_message_tag)) { + ctx_data->message = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + } + return TRUE; +} + +static bool +cmd_notify_validate_stringlist_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct cmd_notify_context_data *ctx_data = + (struct cmd_notify_context_data *)cmd->data; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :options string-list + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING_LIST, FALSE)) + return FALSE; + + /* Assign context */ + ctx_data->options = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Command registration + */ + +static bool +cmd_notify_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag(valdtr, cmd_reg, ext, + ¬ify_method_tag, 0); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + ¬ify_id_tag, OPT_ID); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + ¬ify_message_tag, OPT_MESSAGE); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + ¬ify_options_tag, OPT_OPTIONS); + + ext_notify_register_importance_tags(valdtr, cmd_reg, ext, + OPT_IMPORTANCE); + + return TRUE; +} + +/* + * Command validation + */ + +static bool +cmd_notify_pre_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *cmd) +{ + struct cmd_notify_context_data *ctx_data; + + /* Create context */ + ctx_data = p_new(sieve_command_pool(cmd), + struct cmd_notify_context_data, 1); + cmd->data = ctx_data; + + return TRUE; +} + +static int +cmd_notify_address_validate(void *context, struct sieve_ast_argument *arg) +{ + struct sieve_validator *valdtr = (struct sieve_validator *)context; + + if (sieve_argument_is_string_literal(arg)) { + string_t *address = sieve_ast_argument_str(arg); + const char *error; + int result; + + T_BEGIN { + result = (sieve_address_validate_str(address, &error) ? + 1 : -1); + + if (result <= 0) { + sieve_argument_validate_error( + valdtr, arg, + "specified :options address '%s' is invalid for " + "the mailto notify method: %s", + str_sanitize(str_c(address), 128), + error); + } + } T_END; + + return result; + } + + return 1; +} + +static bool +cmd_notify_validate(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct cmd_notify_context_data *ctx_data = + (struct cmd_notify_context_data *)cmd->data; + + /* Check :method argument */ + if (ctx_data->method != NULL) { + const char *method = sieve_ast_argument_strc(ctx_data->method); + + if (strcasecmp(method, "mailto") != 0) { + sieve_command_validate_error( + valdtr, cmd, + "the notify command of the deprecated notify extension " + "only supports the 'mailto' notification method"); + return FALSE; + } + } + + /* Check :options argument */ + if (ctx_data->options != NULL) { + struct sieve_ast_argument *option = ctx_data->options; + + /* Parse and check options */ + if (sieve_ast_stringlist_map( + &option, (void *)valdtr, + cmd_notify_address_validate) <= 0) { + return FALSE; + } + } else { + sieve_command_validate_warning( + valdtr, cmd, + "no :options (and hence recipients) specified for the notify command"); + } + + return TRUE; +} + +/* + * Code generation + */ + +static bool +cmd_notify_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, ¬ify_old_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool +cmd_notify_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "NOTIFY"); + sieve_code_descend(denv); + + /* Dump optional operands */ + for (;;) { + int opt; + bool opok = TRUE; + + if ((opt = sieve_opr_optional_dump(denv, address, + &opt_code)) < 0) + return FALSE; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_IMPORTANCE: + opok = sieve_opr_number_dump(denv, address, + "importance"); + break; + case OPT_ID: + opok = sieve_opr_string_dump(denv, address, + "id"); + break; + case OPT_OPTIONS: + opok = sieve_opr_stringlist_dump(denv, address, + "options"); + break; + case OPT_MESSAGE: + opok = sieve_opr_string_dump(denv, address, + "message"); + break; + default: + return FALSE; + } + + if (!opok) + return FALSE; + } + + return TRUE; +} + +/* + * Code execution + */ + + +static int +cmd_notify_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct ext_notify_action *act; + pool_t pool; + int opt_code = 0; + sieve_number_t importance = 1; + struct sieve_stringlist *options = NULL; + string_t *message = NULL, *id = NULL; + int ret = 0; + + /* + * Read operands + */ + + /* Optional operands */ + + for (;;) { + int opt; + + if ((opt = sieve_opr_optional_read(renv, address, + &opt_code)) < 0) + return SIEVE_EXEC_BIN_CORRUPT; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_IMPORTANCE: + ret = sieve_opr_number_read(renv, address, "importance", + &importance); + break; + case OPT_ID: + ret = sieve_opr_string_read(renv, address, "id", &id); + break; + case OPT_MESSAGE: + ret = sieve_opr_string_read(renv, address, "from", + &message); + break; + case OPT_OPTIONS: + ret = sieve_opr_stringlist_read(renv, address, + "options", &options); + break; + default: + sieve_runtime_trace_error( + renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if (ret <= 0) return ret; + } + + /* + * Perform operation + */ + + /* Enforce 0 < importance < 4 (just to be sure) */ + + if (importance < 1) + importance = 1; + else if (importance > 3) + importance = 3; + + /* Trace */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "notify action"); + + /* Compose action */ + if (options != NULL) { + string_t *raw_address; + string_t *out_message; + + pool = sieve_result_pool(renv->result); + act = p_new(pool, struct ext_notify_action, 1); + if (id != NULL) + act->id = p_strdup(pool, str_c(id)); + act->importance = importance; + + /* Process message */ + + out_message = t_str_new(1024); + if ((ret = ext_notify_construct_message( + renv, (message == NULL ? NULL : str_c(message)), + out_message)) <= 0) + return ret; + act->message = p_strdup(pool, str_c(out_message)); + + /* Normalize and verify all :options addresses */ + + sieve_stringlist_reset(options); + + p_array_init(&act->recipients, pool, 4); + + raw_address = NULL; + while ((ret = sieve_stringlist_next_item( + options, &raw_address)) > 0) { + const char *error = NULL; + const struct smtp_address *address; + + /* Add if valid address */ + address = sieve_address_parse_str(raw_address, &error); + if (address != NULL) { + const struct ext_notify_recipient *rcpts; + unsigned int rcpt_count, i; + + /* Prevent duplicates */ + rcpts = array_get(&act->recipients, &rcpt_count); + + for (i = 0; i < rcpt_count; i++) { + if (smtp_address_equals(rcpts[i].address, + address)) + break; + } + + /* Add only if unique */ + if (i != rcpt_count) { + sieve_runtime_warning( + renv, NULL, + "duplicate recipient '%s' specified in the :options argument of " + "the deprecated notify command", + str_sanitize(str_c(raw_address), 128)); + + } else if (array_count(&act->recipients) >= + EXT_NOTIFY_MAX_RECIPIENTS) { + sieve_runtime_warning(renv, NULL, + "more than the maximum %u recipients are specified " + "for the deprecated notify command; " + "the rest is discarded", + EXT_NOTIFY_MAX_RECIPIENTS); + break; + + } else { + struct ext_notify_recipient recipient; + + recipient.full = + p_strdup(pool, str_c(raw_address)); + recipient.address = + smtp_address_clone(pool, address); + + array_append(&act->recipients, &recipient, 1); + } + } else { + sieve_runtime_error( + renv, NULL, + "specified :options address '%s' is invalid for " + "the deprecated notify command: %s", + str_sanitize(str_c(raw_address), 128), error); + return SIEVE_EXEC_FAILURE; + } + } + + if (ret < 0) { + sieve_runtime_trace_error( + renv, "invalid options stringlist"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if (sieve_result_add_action(renv, this_ext, "notify", + &act_notify_old, NULL, (void *)act, + 0, FALSE) < 0) + return SIEVE_EXEC_FAILURE; + } + + return SIEVE_EXEC_OK; +} + +/* + * Action + */ + +/* Runtime verification */ + +static int +act_notify_check_duplicate(const struct sieve_runtime_env *renv ATTR_UNUSED, + const struct sieve_action *act ATTR_UNUSED, + const struct sieve_action *act_other ATTR_UNUSED) +{ + struct ext_notify_action *new_nact, *old_nact; + const struct ext_notify_recipient *new_rcpts; + const struct ext_notify_recipient *old_rcpts; + unsigned int new_count, old_count, i, j; + unsigned int del_start = 0, del_len = 0; + + if (act->context == NULL || act_other->context == NULL) + return 0; + + new_nact = (struct ext_notify_action *)act->context; + old_nact = (struct ext_notify_action *)act_other->context; + + new_rcpts = array_get(&new_nact->recipients, &new_count); + old_rcpts = array_get(&old_nact->recipients, &old_count); + + for (i = 0; i < new_count; i++) { + for (j = 0; j < old_count; j++) { + if (smtp_address_equals(new_rcpts[i].address, + old_rcpts[j].address)) + break; + } + + if (j == old_count) { + /* Not duplicate */ + if (del_len > 0) { + /* Perform pending deletion */ + array_delete(&new_nact->recipients, + del_start, del_len); + + /* Make sure the loop integrity is maintained */ + i -= del_len; + new_rcpts = array_get(&new_nact->recipients, + &new_count); + } + + del_len = 0; + } else { + /* Mark deletion */ + if (del_len == 0) + del_start = i; + del_len++; + } + } + + /* Perform pending deletion */ + if (del_len > 0) + array_delete(&new_nact->recipients, del_start, del_len); + + return (array_count(&new_nact->recipients) > 0 ? 0 : 1); +} + +/* Result printing */ + +static void +act_notify_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, + bool *keep ATTR_UNUSED) +{ + const struct ext_notify_action *act = + (const struct ext_notify_action *)action->context; + const struct ext_notify_recipient *recipients; + unsigned int count, i; + + sieve_result_action_printf( + rpenv, "send (deprecated) notification with method 'mailto':"); + + /* Print main method parameters */ + + sieve_result_printf(rpenv, " => importance : %llu\n", + (unsigned long long)act->importance); + + if (act->message != NULL) { + sieve_result_printf( + rpenv, " => message : %s\n", act->message); + } + if (act->id != NULL) { + sieve_result_printf( + rpenv, " => id : %s \n", act->id); + } + + /* Print mailto: recipients */ + + sieve_result_printf(rpenv, " => recipients :\n"); + + recipients = array_get(&act->recipients, &count); + if (count == 0) { + sieve_result_printf( + rpenv, " NONE, action has no effect\n"); + } else { + for (i = 0; i < count; i++) { + sieve_result_printf( + rpenv, " + To: %s\n", recipients[i].full); + } + } + + /* Finish output with an empty line */ + + sieve_result_printf(rpenv, "\n"); +} + +/* Result execution */ + +static bool contains_8bit(const char *msg) +{ + const unsigned char *s = (const unsigned char *)msg; + + for (; *s != '\0'; s++) { + if ((*s & 0x80) != 0) + return TRUE; + } + return FALSE; +} + +static bool +act_notify_send(const struct sieve_action_exec_env *aenv, + const struct ext_notify_action *act) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + const struct sieve_script_env *senv = eenv->scriptenv; + const struct ext_notify_recipient *recipients; + struct sieve_smtp_context *sctx; + unsigned int count, i; + struct ostream *output; + string_t *msg, *to, *all; + const char *outmsgid, *error; + int ret; + + /* Get recipients */ + recipients = array_get(&act->recipients, &count); + if (count == 0) { + sieve_result_warning( + aenv, "notify action specifies no recipients; " + "action has no effect"); + return TRUE; + } + + /* Just to be sure */ + if (!sieve_smtp_available(senv)) { + sieve_result_global_warning( + aenv, "notify action has no means to send mail"); + return TRUE; + } + + /* Compose common headers */ + msg = t_str_new(512); + rfc2822_header_write(msg, "X-Sieve", SIEVE_IMPLEMENTATION); + rfc2822_header_write(msg, "Date", message_date_create(ioloop_time)); + + /* Set importance */ + switch (act->importance) { + case 1: + rfc2822_header_write(msg, "X-Priority", "1 (Highest)"); + rfc2822_header_write(msg, "Importance", "High"); + break; + case 3: + rfc2822_header_write(msg, "X-Priority", "5 (Lowest)"); + rfc2822_header_write(msg, "Importance", "Low"); + break; + case 2: + default: + rfc2822_header_write(msg, "X-Priority", "3 (Normal)"); + rfc2822_header_write(msg, "Importance", "Normal"); + break; + } + + rfc2822_header_write(msg, "From", sieve_get_postmaster_address(senv)); + + rfc2822_header_write(msg, "Subject", "[SIEVE] New mail notification"); + + rfc2822_header_write(msg, "Auto-Submitted", "auto-generated (notify)"); + rfc2822_header_write(msg, "Precedence", "bulk"); + + rfc2822_header_write(msg, "MIME-Version", "1.0"); + if (contains_8bit(act->message)) { + rfc2822_header_write(msg, "Content-Type", + "text/plain; charset=utf-8"); + rfc2822_header_write(msg, "Content-Transfer-Encoding", "8bit"); + } else { + rfc2822_header_write(msg, "Content-Type", + "text/plain; charset=us-ascii"); + rfc2822_header_write(msg, "Content-Transfer-Encoding", "7bit"); + } + + outmsgid = sieve_message_get_new_id(eenv->svinst); + rfc2822_header_write(msg, "Message-ID", outmsgid); + + if ((eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0 && + sieve_message_get_sender(aenv->msgctx) != NULL) { + sctx = sieve_smtp_start(senv, sieve_get_postmaster_smtp(senv)); + } else { + sctx = sieve_smtp_start(senv, NULL); + } + + /* Add all recipients (and compose To header field) */ + to = t_str_new(128); + all = t_str_new(256); + for (i = 0; i < count; i++) { + sieve_smtp_add_rcpt(sctx, recipients[i].address); + if (i > 0) + str_append(to, ", "); + str_append(to, recipients[i].full); + if (i < 3) { + if (i > 0) + str_append(all, ", "); + str_append(all, smtp_address_encode_path( + recipients[i].address)); + } else if (i == 3) { + str_printfa(all, ", ... (%u total)", count); + } + } + + rfc2822_header_write_address(msg, "To", str_c(to)); + + /* Generate message body */ + str_printfa(msg, "\r\n%s\r\n", act->message); + + output = sieve_smtp_send(sctx); + o_stream_nsend(output, str_data(msg), str_len(msg)); + + if ((ret = sieve_smtp_finish(sctx, &error)) <= 0) { + if (ret < 0) { + sieve_result_global_error( + aenv, "failed to send mail notification to %s: " + "%s (temporary failure)", str_c(all), + str_sanitize(error, 512)); + } else { + sieve_result_global_log_error( + aenv, "failed to send mail notification to %s: " + "%s (permanent failure)", str_c(all), + str_sanitize(error, 512)); + } + } else { + struct event_passthrough *e = + sieve_action_create_finish_event(aenv)-> + add_str("notify_target", str_c(all)); + + sieve_result_event_log(aenv, e->event(), + "sent mail notification to %s", + str_c(all)); + } + + return TRUE; +} + +static int +act_notify_commit(const struct sieve_action_exec_env *aenv, + void *tr_context ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct mail *mail = eenv->msgdata->mail; + const struct ext_notify_action *act = + (const struct ext_notify_action *)aenv->action->context; + const char *const *hdsp; + bool result; + int ret; + + /* Is the message an automatic reply ? */ + if ((ret = mail_get_headers(mail, "auto-submitted", &hdsp)) < 0) { + return sieve_result_mail_error( + aenv, mail, + "failed to read `auto-submitted' header field"); + } + + /* Theoretically multiple headers could exist, so lets make sure */ + if (ret > 0) { + while (*hdsp != NULL) { + if (strcasecmp(*hdsp, "no") != 0) { + const struct smtp_address *sender = NULL; + const char *from; + + if ((eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0) + sender = sieve_message_get_sender(aenv->msgctx); + from = (sender == NULL ? "" : + t_strdup_printf(" from <%s>", + smtp_address_encode(sender))); + + sieve_result_global_log( + aenv, + "not sending notification for auto-submitted message%s", + from); + return SIEVE_EXEC_OK; + } + hdsp++; + } + } + + T_BEGIN { + result = act_notify_send(aenv, act); + } T_END; + + if (!result) + return SIEVE_EXEC_FAILURE; + eenv->exec_status->significant_action_executed = TRUE; + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/notify/ext-notify-common.c b/pigeonhole/src/lib-sieve/plugins/notify/ext-notify-common.c new file mode 100644 index 0000000..589b21b --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/notify/ext-notify-common.c @@ -0,0 +1,361 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "istream.h" +#include "rfc822-parser.h" +#include "message-parser.h" +#include "message-decoder.h" +#include "mail-storage.h" + +#include "sieve-common.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-result.h" + +#include "ext-notify-common.h" + +#include <ctype.h> + +/* + * Importance argument + */ + +static bool +tag_importance_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +static const struct sieve_argument_def importance_low_tag = { + .identifier = "low", + .validate = tag_importance_validate, +}; + +static const struct sieve_argument_def importance_normal_tag = { + .identifier = "normal", + .validate = tag_importance_validate, +}; + +static const struct sieve_argument_def importance_high_tag = { + .identifier = "high", + .validate = tag_importance_validate, +}; + +static bool +tag_importance_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_ast_argument **arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + struct sieve_ast_argument *tag = *arg; + + if (sieve_argument_is(tag, importance_low_tag)) + sieve_ast_argument_number_substitute(tag, 3); + else if (sieve_argument_is(tag, importance_normal_tag)) + sieve_ast_argument_number_substitute(tag, 2); + else + sieve_ast_argument_number_substitute(tag, 1); + + tag->argument = sieve_argument_create(tag->ast, &number_argument, + tag->argument->ext, + tag->argument->id_code); + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +void ext_notify_register_importance_tags( + struct sieve_validator *valdtr, + struct sieve_command_registration *cmd_reg, + const struct sieve_extension *ext, unsigned int id_code) +{ + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &importance_low_tag, id_code); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &importance_normal_tag, id_code); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &importance_high_tag, id_code); +} + +/* + * Body extraction + */ + +/* FIXME: overlaps somewhat with body extension */ + +struct ext_notify_message_context { + pool_t pool; + buffer_t *body_text; +}; + +static struct ext_notify_message_context * +ext_notify_get_message_context(const struct sieve_extension *this_ext, + struct sieve_message_context *msgctx) +{ + struct ext_notify_message_context *ctx; + + /* Get message context (contains cached message body information) */ + ctx = (struct ext_notify_message_context *) + sieve_message_context_extension_get(msgctx, this_ext); + + /* Create it if it does not exist already */ + if (ctx == NULL) { + pool_t pool = sieve_message_context_pool(msgctx); + ctx = p_new(pool, struct ext_notify_message_context, 1); + ctx->pool = pool; + ctx->body_text = NULL; + + /* Register context */ + sieve_message_context_extension_set(msgctx, this_ext, + (void *)ctx); + } + + return ctx; +} + +static bool _is_text_content(const struct message_header_line *hdr) +{ + struct rfc822_parser_context parser; + string_t *content_type; + const char *data; + + /* Initialize parsing */ + rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL); + (void)rfc822_skip_lwsp(&parser); + + /* Parse content type */ + content_type = t_str_new(64); + if (rfc822_parse_content_type(&parser, content_type) < 0) + return FALSE; + + /* Content-type value must end here, otherwise it is invalid after all + */ + (void)rfc822_skip_lwsp(&parser); + if (parser.data != parser.end && *parser.data != ';') + return FALSE; + + /* Success */ + data = str_c(content_type); + if (str_begins(data, "text/")) + return TRUE; + return FALSE; +} + +static int +cmd_notify_extract_body_text(const struct sieve_runtime_env *renv, + const char **body_text_r, size_t *body_size_r) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct ext_notify_message_context *mctx; + struct mail *mail = eenv->msgdata->mail; + struct message_parser_ctx *parser; + struct message_decoder_context *decoder; + struct message_part *parts; + struct message_block block, decoded; + struct istream *input; + bool is_text, save_body; + int ret = 1; + + *body_text_r = NULL; + *body_size_r = 0; + + /* Return cached result if available */ + mctx = ext_notify_get_message_context(this_ext, renv->msgctx); + if (mctx->body_text != NULL) { + *body_text_r = (const char *) + buffer_get_data(mctx->body_text, body_size_r); + return SIEVE_EXEC_OK; + } + + /* Create buffer */ + mctx->body_text = buffer_create_dynamic(mctx->pool, 1024*64); + + /* Get the message stream */ + if (mail_get_stream(mail, NULL, NULL, &input) < 0) { + return sieve_runtime_mail_error(renv, mail, "notify action: " + "failed to read input message"); + } + + /* Initialize body decoder */ + decoder = message_decoder_init(NULL, 0); + + struct message_parser_settings mparser_set = { + .hdr_flags = 0, + .flags = 0, + }; + parser = message_parser_init(mctx->pool, input, &mparser_set); + is_text = TRUE; + save_body = FALSE; + while ((ret = message_parser_parse_next_block(parser, &block)) > 0) { + if (block.hdr != NULL || block.size == 0) { + /* Decode block */ + (void)message_decoder_decode_next_block(decoder, &block, + &decoded); + + /* Check for end of headers */ + if (block.hdr == NULL) { + save_body = is_text; + continue; + } + + /* We're interested of only Content-Type: header */ + if (strcasecmp(block.hdr->name, "Content-Type") != 0) + continue; + + /* Header can have folding whitespace. Acquire the full + value before continuing */ + if (block.hdr->continues) { + block.hdr->use_full_value = TRUE; + continue; + } + + /* Is it a text part? */ + T_BEGIN { + is_text = _is_text_content(block.hdr); + } T_END; + + continue; + } + + /* Read text body */ + if (save_body) { + (void)message_decoder_decode_next_block(decoder, &block, + &decoded); + buffer_append(mctx->body_text, decoded.data, + decoded.size); + is_text = TRUE; + } + } + + /* Cleanup */ + (void)message_parser_deinit(&parser, &parts); + message_decoder_deinit(&decoder); + + if (ret < 0 && input->stream_errno != 0) { + sieve_runtime_critical(renv, NULL, "notify action: " + "failed to read input message", + "notify action: read(%s) failed: %s", + i_stream_get_name(input), + i_stream_get_error(input)); + return SIEVE_EXEC_TEMP_FAILURE; + } + + /* Return status */ + *body_text_r = (const char *)buffer_get_data(mctx->body_text, + body_size_r); + return SIEVE_EXEC_OK; +} + +int ext_notify_construct_message(const struct sieve_runtime_env *renv, + const char *msg_format, + string_t *out_msg) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_message_data *msgdata = eenv->msgdata; + struct sieve_message_context *msgctx = renv->msgctx; + const struct smtp_address *return_path = + sieve_message_get_sender(msgctx); + const char *p; + int ret; + + if (msg_format == NULL) + msg_format = "$from$: $subject$"; + + /* Scan message for substitutions */ + p = msg_format; + while (*p != '\0') { + const char *header; + + if (strncasecmp(p, "$from$", 6) == 0) { + p += 6; + + /* Fetch sender from original message */ + if ((ret = mail_get_first_header_utf8( + msgdata->mail, "from", &header)) < 0) { + return sieve_runtime_mail_error( + renv, msgdata->mail, + "failed to read header field `from'"); + } + if (ret > 0) + str_append(out_msg, header); + } else if (strncasecmp(p, "$env-from$", 10) == 0) { + p += 10; + + if (return_path != NULL) + smtp_address_write(out_msg, return_path); + } else if (strncasecmp(p, "$subject$", 9) == 0) { + p += 9; + + /* Fetch sender from oriinal message */ + if ((ret = mail_get_first_header_utf8( + msgdata->mail, "subject", &header)) < 0) { + return sieve_runtime_mail_error( + renv, msgdata->mail, + "failed to read header field `subject'"); + } + if (ret > 0) + str_append(out_msg, header); + } else if (strncasecmp(p, "$text", 5) == 0 && + (p[5] == '[' || p[5] == '$')) { + size_t num = 0; + const char *begin = p; + bool valid = TRUE; + + p += 5; + if (*p == '[') { + p += 1; + + while (i_isdigit(*p)) { + num = num * 10 + (*p - '0'); + p++; + } + + if (*p++ != ']' || *p++ != '$') { + str_append_data(out_msg, begin, + p-begin); + valid = FALSE; + } + } else { + p += 1; + } + + if (valid) { + size_t body_size; + const char *body_text; + + if ((ret = cmd_notify_extract_body_text( + renv, &body_text, &body_size)) <= 0) + return ret; + + if (num > 0 && num < body_size) { + str_append_data(out_msg, body_text, + num); + } else { + str_append_data(out_msg, body_text, + body_size); + } + } + } else { + size_t len; + + /* Find next substitution */ + len = strcspn(p + 1, "$") + 1; + + /* Copy normal text */ + str_append_data(out_msg, p, len); + p += len; + } + } + + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/notify/ext-notify-common.h b/pigeonhole/src/lib-sieve/plugins/notify/ext-notify-common.h new file mode 100644 index 0000000..09db2cb --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/notify/ext-notify-common.h @@ -0,0 +1,66 @@ +#ifndef EXT_NOTIFY_COMMON_H +#define EXT_NOTIFY_COMMON_H + +/* + * Extension + */ + +extern const struct sieve_extension_def notify_extension; + +/* + * Commands + */ + +extern const struct sieve_command_def cmd_notify_old; +extern const struct sieve_command_def cmd_denotify; + +/* + * Arguments + */ + +void ext_notify_register_importance_tags( + struct sieve_validator *valdtr, + struct sieve_command_registration *cmd_reg, + const struct sieve_extension *this_ext, unsigned int id_code); + +/* + * Operations + */ + +extern const struct sieve_operation_def notify_old_operation; +extern const struct sieve_operation_def denotify_operation; + +enum ext_notify_opcode { + EXT_NOTIFY_OPERATION_NOTIFY, + EXT_NOTIFY_OPERATION_DENOTIFY, +}; + +/* + * Actions + */ + +extern const struct sieve_action_def act_notify_old; + +struct ext_notify_recipient { + const char *full; + const struct smtp_address *address; +}; + +ARRAY_DEFINE_TYPE(recipients, struct ext_notify_recipient); + +struct ext_notify_action { + const char *id; + const char *message; + sieve_number_t importance; + + ARRAY_TYPE(recipients) recipients; +}; + +/* + * Message construct + */ + +int ext_notify_construct_message(const struct sieve_runtime_env *renv, + const char *msg_format, string_t *out_msg); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/notify/ext-notify-limits.h b/pigeonhole/src/lib-sieve/plugins/notify/ext-notify-limits.h new file mode 100644 index 0000000..5fab7cb --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/notify/ext-notify-limits.h @@ -0,0 +1,7 @@ +#ifndef EXT_NOTIFY_LIMITS_H +#define EXT_NOTIFY_LIMITS_H + +#define EXT_NOTIFY_MAX_RECIPIENTS 8 +#define EXT_NOTIFY_MAX_MESSAGE 256 + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/notify/ext-notify.c b/pigeonhole/src/lib-sieve/plugins/notify/ext-notify.c new file mode 100644 index 0000000..e79e049 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/notify/ext-notify.c @@ -0,0 +1,108 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension notify + * ---------------- + * + * Authors: Stephan Bosch + * Specification: draft-ietf-sieve-notify-00.txt + * Implementation: full, but deprecated; provided for backwards compatibility + * Status: testing + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "ext-notify-common.h" + +/* + * Operations + */ + +const struct sieve_operation_def *ext_notify_operations[] = { + ¬ify_old_operation, + &denotify_operation +}; + +/* + * Extension + */ + +static bool ext_notify_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def notify_extension = { + .name = "notify", + .validator_load = ext_notify_validator_load, + SIEVE_EXT_DEFINE_OPERATIONS(ext_notify_operations) +}; + +/* + * Extension validation + */ + +static bool ext_notify_validator_check_conflict + (const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + const struct sieve_extension *ext_other, + bool required); +static bool ext_notify_validator_validate + (const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + bool required); + +const struct sieve_validator_extension notify_validator_extension = { + .ext = ¬ify_extension, + .check_conflict = ext_notify_validator_check_conflict, + .validate = ext_notify_validator_validate +}; + +static bool ext_notify_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register validator extension to check for conflict with enotify */ + sieve_validator_extension_register + (valdtr, ext, ¬ify_validator_extension, NULL); + return TRUE; +} + +static bool ext_notify_validator_check_conflict +(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_validator *valdtr, void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg, + const struct sieve_extension *ext_other, + bool required ATTR_UNUSED) +{ + /* Check for conflict with enotify */ + if ( sieve_extension_name_is(ext_other, "enotify") ) { + sieve_argument_validate_error(valdtr, require_arg, + "the (deprecated) notify extension cannot be used " + "together with the enotify extension"); + return FALSE; + } + + return TRUE; +} + +static bool ext_notify_validator_validate +(const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg ATTR_UNUSED, + bool required ATTR_UNUSED) +{ + /* No conflicts: register new commands */ + sieve_validator_register_command(valdtr, ext, &cmd_notify_old); + sieve_validator_register_command(valdtr, ext, &cmd_denotify); + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/regex/Makefile.am b/pigeonhole/src/lib-sieve/plugins/regex/Makefile.am new file mode 100644 index 0000000..eeb735e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/regex/Makefile.am @@ -0,0 +1,13 @@ +noinst_LTLIBRARIES = libsieve_ext_regex.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_regex_la_SOURCES = \ + mcht-regex.c \ + ext-regex-common.c \ + ext-regex.c + +noinst_HEADERS = \ + ext-regex-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/regex/Makefile.in b/pigeonhole/src/lib-sieve/plugins/regex/Makefile.in new file mode 100644 index 0000000..379d384 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/regex/Makefile.in @@ -0,0 +1,688 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/regex +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_regex_la_LIBADD = +am_libsieve_ext_regex_la_OBJECTS = mcht-regex.lo ext-regex-common.lo \ + ext-regex.lo +libsieve_ext_regex_la_OBJECTS = $(am_libsieve_ext_regex_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ext-regex-common.Plo \ + ./$(DEPDIR)/ext-regex.Plo ./$(DEPDIR)/mcht-regex.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_regex_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_regex_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_regex.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_regex_la_SOURCES = \ + mcht-regex.c \ + ext-regex-common.c \ + ext-regex.c + +noinst_HEADERS = \ + ext-regex-common.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/regex/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/regex/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_regex.la: $(libsieve_ext_regex_la_OBJECTS) $(libsieve_ext_regex_la_DEPENDENCIES) $(EXTRA_libsieve_ext_regex_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_regex_la_OBJECTS) $(libsieve_ext_regex_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-regex-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-regex.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcht-regex.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-regex-common.Plo + -rm -f ./$(DEPDIR)/ext-regex.Plo + -rm -f ./$(DEPDIR)/mcht-regex.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ext-regex-common.Plo + -rm -f ./$(DEPDIR)/ext-regex.Plo + -rm -f ./$(DEPDIR)/mcht-regex.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/regex/ext-regex-common.c b/pigeonhole/src/lib-sieve/plugins/regex/ext-regex-common.c new file mode 100644 index 0000000..975f4fb --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/regex/ext-regex-common.c @@ -0,0 +1,22 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-match-types.h" + +#include "ext-regex-common.h" + +/* + * Regex match type operand + */ + +static const struct sieve_extension_objects ext_match_types = + SIEVE_EXT_DEFINE_MATCH_TYPE(regex_match_type); + +const struct sieve_operand_def regex_match_type_operand = { + .name = "regex match", + .ext_def = ®ex_extension, + .class = &sieve_match_type_operand_class, + .interface = &ext_match_types +}; + diff --git a/pigeonhole/src/lib-sieve/plugins/regex/ext-regex-common.h b/pigeonhole/src/lib-sieve/plugins/regex/ext-regex-common.h new file mode 100644 index 0000000..e9d809f --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/regex/ext-regex-common.h @@ -0,0 +1,24 @@ +#ifndef EXT_REGEX_COMMON_H +#define EXT_REGEX_COMMON_H + +/* + * Extension + */ + +extern const struct sieve_extension_def regex_extension; + +/* + * Operand + */ + +extern const struct sieve_operand_def regex_match_type_operand; + +/* + * Match type + */ + +extern const struct sieve_match_type_def regex_match_type; + +#endif + + diff --git a/pigeonhole/src/lib-sieve/plugins/regex/ext-regex.c b/pigeonhole/src/lib-sieve/plugins/regex/ext-regex.c new file mode 100644 index 0000000..0440b30 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/regex/ext-regex.c @@ -0,0 +1,65 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension regex + * --------------- + * + * Authors: Stephan Bosch + * Specification: draft-murchison-sieve-regex-08 (not latest) + * Implementation: full + * Status: testing + * + */ + +/* FIXME: Regular expressions are compiled during compilation and + * again during interpretation. This is suboptimal and should be + * changed. This requires dumping the compiled regex to the binary. + * Most likely, this will only be possible when we implement regular + * expressions ourselves. + * + */ + +#include "lib.h" +#include "mempool.h" +#include "buffer.h" + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" + +#include "sieve-comparators.h" +#include "sieve-match-types.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-regex-common.h" + +#include <sys/types.h> +#include <regex.h> + +/* + * Extension + */ + +static bool ext_regex_validator_load + (const struct sieve_extension *ext, struct sieve_validator *validator); + +const struct sieve_extension_def regex_extension = { + .name = "regex", + .validator_load = ext_regex_validator_load, + SIEVE_EXT_DEFINE_OPERAND(regex_match_type_operand) +}; + +static bool ext_regex_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + sieve_match_type_register(valdtr, ext, ®ex_match_type); + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/regex/mcht-regex.c b/pigeonhole/src/lib-sieve/plugins/regex/mcht-regex.c new file mode 100644 index 0000000..f0c630e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/regex/mcht-regex.c @@ -0,0 +1,385 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Match-type ':regex' + */ + +#include "lib.h" +#include "mempool.h" +#include "buffer.h" +#include "array.h" +#include "str.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-limits.h" +#include "sieve-ast.h" +#include "sieve-stringlist.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-interpreter.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-match.h" + +#include "ext-regex-common.h" + +#include <sys/types.h> +#include <regex.h> +#include <ctype.h> + +/* + * Configuration + */ + +#define MCHT_REGEX_MAX_SUBSTITUTIONS SIEVE_MAX_MATCH_VALUES + +/* + * Match type + */ + +static bool mcht_regex_validate_context +(struct sieve_validator *valdtr, struct sieve_ast_argument *arg, + struct sieve_match_type_context *ctx, struct sieve_ast_argument *key_arg); + +static void mcht_regex_match_init(struct sieve_match_context *mctx); +static int mcht_regex_match_keys + (struct sieve_match_context *mctx, const char *val, size_t val_size, + struct sieve_stringlist *key_list); +static void mcht_regex_match_deinit(struct sieve_match_context *mctx); + +const struct sieve_match_type_def regex_match_type = { + SIEVE_OBJECT("regex", ®ex_match_type_operand, 0), + .validate_context = mcht_regex_validate_context, + .match_init = mcht_regex_match_init, + .match_keys = mcht_regex_match_keys, + .match_deinit = mcht_regex_match_deinit +}; + +/* + * Match type validation + */ + +/* Wrapper around the regerror function for easy access */ +static const char *_regexp_error(regex_t *regexp, int errorcode) +{ + size_t errsize = regerror(errorcode, regexp, NULL, 0); + + if ( errsize > 0 ) { + char *errbuf; + + buffer_t *error_buf = + buffer_create_dynamic(pool_datastack_create(), errsize); + errbuf = buffer_get_space_unsafe(error_buf, 0, errsize); + + errsize = regerror(errorcode, regexp, errbuf, errsize); + + /* We don't want the error to start with a capital letter */ + errbuf[0] = i_tolower(errbuf[0]); + + buffer_append_space_unsafe(error_buf, errsize); + + return str_c(error_buf); + } + + return ""; +} + +static int mcht_regex_validate_regexp +(struct sieve_validator *valdtr, + struct sieve_match_type_context *mtctx ATTR_UNUSED, + struct sieve_ast_argument *key, int cflags) +{ + int ret; + regex_t regexp; + const char *regex_str = sieve_ast_argument_strc(key); + + if ( (ret=regcomp(®exp, regex_str, cflags)) != 0 ) { + sieve_argument_validate_error(valdtr, key, + "invalid regular expression '%s' for regex match: %s", + str_sanitize(regex_str, 128), _regexp_error(®exp, ret)); + + regfree(®exp); + return -1; + } + + regfree(®exp); + return 1; +} + +struct _regex_key_context { + struct sieve_validator *valdtr; + struct sieve_match_type_context *mtctx; + int cflags; +}; + +static int mcht_regex_validate_key_argument +(void *context, struct sieve_ast_argument *key) +{ + struct _regex_key_context *keyctx = (struct _regex_key_context *) context; + + /* FIXME: We can currently only handle string literal argument, so + * variables are not allowed. + */ + if ( sieve_argument_is_string_literal(key) ) { + return mcht_regex_validate_regexp + (keyctx->valdtr, keyctx->mtctx, key, keyctx->cflags); + } + + return 1; +} + +static bool mcht_regex_validate_context +(struct sieve_validator *valdtr, struct sieve_ast_argument *arg ATTR_UNUSED, + struct sieve_match_type_context *mtctx, struct sieve_ast_argument *key_arg) +{ + const struct sieve_comparator *cmp = mtctx->comparator; + int cflags = REG_EXTENDED | REG_NOSUB; + struct _regex_key_context keyctx; + struct sieve_ast_argument *kitem; + + if ( cmp != NULL ) { + if ( sieve_comparator_is(cmp, i_ascii_casemap_comparator) ) + cflags = REG_EXTENDED | REG_NOSUB | REG_ICASE; + else if ( sieve_comparator_is(cmp, i_octet_comparator) ) + cflags = REG_EXTENDED | REG_NOSUB; + else { + sieve_argument_validate_error(valdtr, mtctx->argument, + "regex match type only supports " + "i;octet and i;ascii-casemap comparators" ); + return FALSE; + } + } + + /* Validate regular expression keys */ + + keyctx.valdtr = valdtr; + keyctx.mtctx = mtctx; + keyctx.cflags = cflags; + + kitem = key_arg; + if ( sieve_ast_stringlist_map(&kitem, (void *) &keyctx, + mcht_regex_validate_key_argument) <= 0 ) + return FALSE; + + return TRUE; +} + +/* + * Match type implementation + */ + +struct mcht_regex_key { + regex_t regexp; + int status; +}; + +struct mcht_regex_context { + ARRAY(struct mcht_regex_key) reg_expressions; + regmatch_t *pmatch; + size_t nmatch; + bool all_compiled:1; +}; + +static void mcht_regex_match_init +(struct sieve_match_context *mctx) +{ + pool_t pool = mctx->pool; + struct mcht_regex_context *ctx; + + /* Create context */ + ctx = p_new(pool, struct mcht_regex_context, 1); + + /* Create storage for match values if match values are requested */ + if ( sieve_match_values_are_enabled(mctx->runenv) ) { + ctx->pmatch = p_new(pool, regmatch_t, MCHT_REGEX_MAX_SUBSTITUTIONS); + ctx->nmatch = MCHT_REGEX_MAX_SUBSTITUTIONS; + } else { + ctx->pmatch = NULL; + ctx->nmatch = 0; + } + + /* Assign context */ + mctx->data = (void *) ctx; +} + +static int mcht_regex_match_key +(struct sieve_match_context *mctx, const char *val, + const regex_t *regexp) +{ + struct mcht_regex_context *ctx = (struct mcht_regex_context *) mctx->data; + int ret; + + /* Execute regex */ + + ret = regexec(regexp, val, ctx->nmatch, ctx->pmatch, 0); + + /* Handle match values if necessary */ + + if ( ret == 0 ) { + if ( ctx->nmatch > 0 ) { + struct sieve_match_values *mvalues; + size_t i; + int skipped = 0; + string_t *subst = t_str_new(32); + + /* Start new list of match values */ + mvalues = sieve_match_values_start(mctx->runenv); + + i_assert( mvalues != NULL ); + + /* Add match values from regular expression */ + for ( i = 0; i < ctx->nmatch; i++ ) { + str_truncate(subst, 0); + + if ( ctx->pmatch[i].rm_so != -1 ) { + if ( skipped > 0 ) { + sieve_match_values_skip(mvalues, skipped); + skipped = 0; + } + + str_append_data(subst, val + ctx->pmatch[i].rm_so, + ctx->pmatch[i].rm_eo - ctx->pmatch[i].rm_so); + sieve_match_values_add(mvalues, subst); + } else + skipped++; + } + + /* Substitute the new match values */ + sieve_match_values_commit(mctx->runenv, &mvalues); + } + + return 1; + } + + return 0; +} + +static int mcht_regex_match_keys +(struct sieve_match_context *mctx, const char *val, size_t val_size ATTR_UNUSED, + struct sieve_stringlist *key_list) +{ + const struct sieve_runtime_env *renv = mctx->runenv; + bool trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); + struct mcht_regex_context *ctx = (struct mcht_regex_context *) mctx->data; + const struct sieve_comparator *cmp = mctx->comparator; + int match; + + if ( !ctx->all_compiled ) { + string_t *key_item = NULL; + unsigned int i; + int ret; + + /* Regular expressions still need to be compiled */ + + if ( !array_is_created(&ctx->reg_expressions) ) + p_array_init(&ctx->reg_expressions, mctx->pool, 16); + + i = 0; + match = 0; + while ( match == 0 && + (ret=sieve_stringlist_next_item(key_list, &key_item)) > 0 ) { + + T_BEGIN { + struct mcht_regex_key *rkey; + + if ( i >= array_count(&ctx->reg_expressions) ) { + int cflags; + + rkey = array_append_space(&ctx->reg_expressions); + + /* Configure case-sensitivity according to comparator */ + if ( sieve_comparator_is(cmp, i_octet_comparator) ) + cflags = REG_EXTENDED; + else if ( sieve_comparator_is(cmp, i_ascii_casemap_comparator) ) + cflags = REG_EXTENDED | REG_ICASE; + else + rkey->status = -1; /* Not supported */ + + if ( rkey->status >= 0 ) { + const char *regex_str = str_c(key_item); + int rxret; + + /* Indicate whether match values need to be produced */ + if ( ctx->nmatch == 0 ) cflags |= REG_NOSUB; + + /* Compile regular expression */ + if ( (rxret=regcomp(&rkey->regexp, regex_str, cflags)) != 0 ) { + sieve_runtime_error(renv, NULL, + "invalid regular expression '%s' for regex match: %s", + str_sanitize(regex_str, 128), + _regexp_error(&rkey->regexp, rxret)); + rkey->status = -1; + } else { + rkey->status = 1; + } + } + } else { + rkey = array_idx_modifiable(&ctx->reg_expressions, 1); + } + + if ( rkey->status > 0 ) { + match = mcht_regex_match_key(mctx, val, &rkey->regexp); + + if ( trace ) { + sieve_runtime_trace(renv, 0, + "with regex `%s' [id=%d] => %d", + str_sanitize(str_c(key_item), 80), + array_count(&ctx->reg_expressions)-1, match); + } + } + } T_END; + + i++; + } + + if ( ret == 0 ) { + ctx->all_compiled = TRUE; + } else if ( ret < 0 ) { + mctx->exec_status = key_list->exec_status; + match = -1; + } + + } else { + const struct mcht_regex_key *rkeys; + unsigned int i, count; + + /* Regular expressions are compiled */ + + rkeys = array_get(&ctx->reg_expressions, &count); + + i = 0; + match = 0; + while ( match == 0 && i < count ) { + if ( rkeys[i].status > 0 ) { + match = mcht_regex_match_key(mctx, val, &rkeys[i].regexp); + + if ( trace ) { + sieve_runtime_trace(renv, 0, + "with compiled regex [id=%d] => %d", i, match); + } + } + + i++; + } + } + + return match; +} + +void mcht_regex_match_deinit +(struct sieve_match_context *mctx) +{ + struct mcht_regex_context *ctx = (struct mcht_regex_context *) mctx->data; + struct mcht_regex_key *rkeys; + unsigned int count, i; + + /* Clean up compiled regular expressions */ + if ( array_is_created(&ctx->reg_expressions) ) { + rkeys = array_get_modifiable(&ctx->reg_expressions, &count); + for ( i = 0; i < count; i++ ) { + regfree(&rkeys[i].regexp); + } + } +} + diff --git a/pigeonhole/src/lib-sieve/plugins/relational/Makefile.am b/pigeonhole/src/lib-sieve/plugins/relational/Makefile.am new file mode 100644 index 0000000..dd28cc5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/relational/Makefile.am @@ -0,0 +1,14 @@ +noinst_LTLIBRARIES = libsieve_ext_relational.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_relational_la_SOURCES = \ + ext-relational-common.c \ + mcht-value.c \ + mcht-count.c \ + ext-relational.c + +noinst_HEADERS = \ + ext-relational-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/relational/Makefile.in b/pigeonhole/src/lib-sieve/plugins/relational/Makefile.in new file mode 100644 index 0000000..4977808 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/relational/Makefile.in @@ -0,0 +1,694 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/relational +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_relational_la_LIBADD = +am_libsieve_ext_relational_la_OBJECTS = ext-relational-common.lo \ + mcht-value.lo mcht-count.lo ext-relational.lo +libsieve_ext_relational_la_OBJECTS = \ + $(am_libsieve_ext_relational_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ext-relational-common.Plo \ + ./$(DEPDIR)/ext-relational.Plo ./$(DEPDIR)/mcht-count.Plo \ + ./$(DEPDIR)/mcht-value.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_relational_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_relational_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_relational.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_relational_la_SOURCES = \ + ext-relational-common.c \ + mcht-value.c \ + mcht-count.c \ + ext-relational.c + +noinst_HEADERS = \ + ext-relational-common.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/relational/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/relational/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_relational.la: $(libsieve_ext_relational_la_OBJECTS) $(libsieve_ext_relational_la_DEPENDENCIES) $(EXTRA_libsieve_ext_relational_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_relational_la_OBJECTS) $(libsieve_ext_relational_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-relational-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-relational.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcht-count.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcht-value.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-relational-common.Plo + -rm -f ./$(DEPDIR)/ext-relational.Plo + -rm -f ./$(DEPDIR)/mcht-count.Plo + -rm -f ./$(DEPDIR)/mcht-value.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ext-relational-common.Plo + -rm -f ./$(DEPDIR)/ext-relational.Plo + -rm -f ./$(DEPDIR)/mcht-count.Plo + -rm -f ./$(DEPDIR)/mcht-value.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/relational/ext-relational-common.c b/pigeonhole/src/lib-sieve/plugins/relational/ext-relational-common.c new file mode 100644 index 0000000..a6dd1ed --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/relational/ext-relational-common.c @@ -0,0 +1,171 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Syntax: + + MATCH-TYPE =/ COUNT / VALUE + COUNT = ":count" relational-match + VALUE = ":value" relational-match + relational-match = DQUOTE ( "gt" / "ge" / "lt" + / "le" / "eq" / "ne" ) DQUOTE + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-ast.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-relational-common.h" + +/* + * Forward declarations + */ + +const struct sieve_match_type_def *rel_match_types[]; + +/* + * Validation + */ + +bool mcht_relational_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_match_type_context *ctx) +{ + struct sieve_match_type *mcht; + enum relational_match rel_match = REL_MATCH_INVALID; + pool_t pool = sieve_ast_argument_pool(ctx->argument); + string_t *rel_match_ident; + + /* Check syntax: + relational-match = DQUOTE ( "gt" / "ge" / "lt" + / "le" / "eq" / "ne" ) DQUOTE + + So, actually this must be a constant string and it is implemented as + such. + */ + + /* Did we get a string in the first place? */ + if (*arg == NULL || (*arg)->type != SAAT_STRING) { + sieve_argument_validate_error( + valdtr, (*arg == NULL ? ctx->argument : *arg), + "the :%s match-type requires a constant string argument being " + "one of \"gt\", \"ge\", \"lt\", \"le\", \"eq\" or \"ne\", " + "but %s was found", + sieve_match_type_name(ctx->match_type), + (*arg == NULL ? + "none" : sieve_ast_argument_name(*arg))); + return FALSE; + } + + /* Check the relational match id */ + + rel_match_ident = sieve_ast_argument_str(*arg); + if (str_len(rel_match_ident) == 2) { + const char *rel_match_id = str_c(rel_match_ident); + + switch (rel_match_id[0]) { + /* "gt" or "ge" */ + case 'g': + switch (rel_match_id[1]) { + case 't': + rel_match = REL_MATCH_GREATER; + break; + case 'e': + rel_match = REL_MATCH_GREATER_EQUAL; + break; + default: + rel_match = REL_MATCH_INVALID; + } + break; + /* "lt" or "le" */ + case 'l': + switch (rel_match_id[1]) { + case 't': + rel_match = REL_MATCH_LESS; + break; + case 'e': + rel_match = REL_MATCH_LESS_EQUAL; + break; + default: + rel_match = REL_MATCH_INVALID; + } + break; + /* "eq" */ + case 'e': + if (rel_match_id[1] == 'q') + rel_match = REL_MATCH_EQUAL; + else + rel_match = REL_MATCH_INVALID; + break; + /* "ne" */ + case 'n': + if (rel_match_id[1] == 'e') + rel_match = REL_MATCH_NOT_EQUAL; + else + rel_match = REL_MATCH_INVALID; + break; + /* invalid */ + default: + rel_match = REL_MATCH_INVALID; + } + } + + if (rel_match >= REL_MATCH_INVALID) { + sieve_argument_validate_error( + valdtr, *arg, + "the :%s match-type requires a constant string argument being " + "one of \"gt\", \"ge\", \"lt\", \"le\", \"eq\" or \"ne\", " + "but \"%s\" was found", + sieve_match_type_name(ctx->match_type), + str_sanitize(str_c(rel_match_ident), 32)); + return FALSE; + } + + /* Delete argument */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + /* Not used just yet */ + ctx->ctx_data = (void *) rel_match; + + /* Override the actual match type with a parameter-specific one + * FIXME: ugly! + */ + mcht = p_new(pool, struct sieve_match_type, 1); + mcht->object.ext = ctx->match_type->object.ext; + SIEVE_OBJECT_SET_DEF(mcht, rel_match_types[ + REL_MATCH_INDEX(ctx->match_type->object.def->code, rel_match)]); + ctx->match_type = mcht; + + return TRUE; +} + +/* + * Relational match-type operand + */ + +const struct sieve_match_type_def *rel_match_types[] = { + &rel_match_value_gt, &rel_match_value_ge, &rel_match_value_lt, + &rel_match_value_le, &rel_match_value_eq, &rel_match_value_ne, + &rel_match_count_gt, &rel_match_count_ge, &rel_match_count_lt, + &rel_match_count_le, &rel_match_count_eq, &rel_match_count_ne, +}; + +static const struct sieve_extension_objects ext_match_types = + SIEVE_EXT_DEFINE_MATCH_TYPES(rel_match_types); + +const struct sieve_operand_def rel_match_type_operand = { + .name = "relational match", + .ext_def = &relational_extension, + .class = &sieve_match_type_operand_class, + .interface = &ext_match_types, +}; diff --git a/pigeonhole/src/lib-sieve/plugins/relational/ext-relational-common.h b/pigeonhole/src/lib-sieve/plugins/relational/ext-relational-common.h new file mode 100644 index 0000000..c0f7d3b --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/relational/ext-relational-common.h @@ -0,0 +1,86 @@ +#ifndef EXT_RELATIONAL_COMMON_H +#define EXT_RELATIONAL_COMMON_H + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" + +/* + * Types + */ + +enum ext_relational_match_type { + RELATIONAL_VALUE, + RELATIONAL_COUNT +}; + +enum relational_match { + REL_MATCH_GREATER, + REL_MATCH_GREATER_EQUAL, + REL_MATCH_LESS, + REL_MATCH_LESS_EQUAL, + REL_MATCH_EQUAL, + REL_MATCH_NOT_EQUAL, + REL_MATCH_INVALID +}; + +#define REL_MATCH_INDEX(type, match) (type * REL_MATCH_INVALID + match) +#define REL_MATCH_TYPE(index) (index / REL_MATCH_INVALID) +#define REL_MATCH(index) (index % REL_MATCH_INVALID) + +/* + * Extension definitions + */ + +extern const struct sieve_extension_def relational_extension; + +/* + * Match types + */ + +/* Registered for validation */ + +extern const struct sieve_match_type_def value_match_type; +extern const struct sieve_match_type_def count_match_type; + +/* Used in byte code */ + +extern const struct sieve_match_type_def rel_match_count_gt; +extern const struct sieve_match_type_def rel_match_count_ge; +extern const struct sieve_match_type_def rel_match_count_lt; +extern const struct sieve_match_type_def rel_match_count_le; +extern const struct sieve_match_type_def rel_match_count_eq; +extern const struct sieve_match_type_def rel_match_count_ne; + +extern const struct sieve_match_type_def rel_match_value_gt; +extern const struct sieve_match_type_def rel_match_value_ge; +extern const struct sieve_match_type_def rel_match_value_lt; +extern const struct sieve_match_type_def rel_match_value_le; +extern const struct sieve_match_type_def rel_match_value_eq; +extern const struct sieve_match_type_def rel_match_value_ne; + +/* + * Operand + */ + +extern const struct sieve_operand_def rel_match_type_operand; + + +/* + * Match type validation + */ + +bool mcht_relational_validate(struct sieve_validator *validator, + struct sieve_ast_argument **arg, + struct sieve_match_type_context *ctx); + +/* + * Value match function (also used by :count) + */ + +int mcht_value_match_key(struct sieve_match_context *mctx, + const char *val, size_t val_size, + const char *key, size_t key_size); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/relational/ext-relational.c b/pigeonhole/src/lib-sieve/plugins/relational/ext-relational.c new file mode 100644 index 0000000..28c278f --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/relational/ext-relational.c @@ -0,0 +1,53 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension relational + * -------------------- + * + * Author: Stephan Bosch + * Specification: RFC 3431 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" + +#include "sieve-ast.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-relational-common.h" + +/* + * Extension + */ + +static bool ext_relational_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def relational_extension = { + .name = "relational", + .validator_load = ext_relational_validator_load, + SIEVE_EXT_DEFINE_OPERAND(rel_match_type_operand) +}; + +static bool ext_relational_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + sieve_match_type_register(valdtr, ext, &value_match_type); + sieve_match_type_register(valdtr, ext, &count_match_type); + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/relational/mcht-count.c b/pigeonhole/src/lib-sieve/plugins/relational/mcht-count.c new file mode 100644 index 0000000..e31a63a --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/relational/mcht-count.c @@ -0,0 +1,119 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Match-type ':count' + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-ast.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-runtime-trace.h" +#include "sieve-match.h" + +#include "ext-relational-common.h" + +/* + * Forward declarations + */ + +static int mcht_count_match + (struct sieve_match_context *mctx, struct sieve_stringlist *value_list, + struct sieve_stringlist *key_list); + +/* + * Match-type objects + */ + +const struct sieve_match_type_def count_match_type = { + SIEVE_OBJECT("count", + &rel_match_type_operand, RELATIONAL_COUNT), + .validate = mcht_relational_validate +}; + +#define COUNT_MATCH_TYPE(name, rel_match) \ +const struct sieve_match_type_def rel_match_count_ ## name = { \ + SIEVE_OBJECT("count-" #name, \ + &rel_match_type_operand, \ + REL_MATCH_INDEX(RELATIONAL_COUNT, rel_match)), \ + .match = mcht_count_match, \ +} + +COUNT_MATCH_TYPE(gt, REL_MATCH_GREATER); +COUNT_MATCH_TYPE(ge, REL_MATCH_GREATER_EQUAL); +COUNT_MATCH_TYPE(lt, REL_MATCH_LESS); +COUNT_MATCH_TYPE(le, REL_MATCH_LESS_EQUAL); +COUNT_MATCH_TYPE(eq, REL_MATCH_EQUAL); +COUNT_MATCH_TYPE(ne, REL_MATCH_NOT_EQUAL); + +/* + * Match-type implementation + */ + +static int mcht_count_match +(struct sieve_match_context *mctx, struct sieve_stringlist *value_list, + struct sieve_stringlist *key_list) +{ + const struct sieve_runtime_env *renv = mctx->runenv; + bool trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); + int count; + string_t *key_item; + int match, ret; + + if ( (count=sieve_stringlist_get_length(value_list)) < 0 ) { + mctx->exec_status = value_list->exec_status; + return -1; + } + + sieve_stringlist_reset(key_list); + + string_t *value = t_str_new(20); + str_printfa(value, "%d", count); + + if ( trace ) { + sieve_runtime_trace(renv, 0, + "matching count value `%s'", str_sanitize(str_c(value), 80)); + } + + sieve_runtime_trace_descend(renv); + + /* Match to all key values */ + key_item = NULL; + match = 0; + while ( match == 0 && + (ret=sieve_stringlist_next_item(key_list, &key_item)) > 0 ) + { + match = mcht_value_match_key + (mctx, str_c(value), str_len(value), str_c(key_item), str_len(key_item)); + + if ( trace ) { + sieve_runtime_trace(renv, 0, + "with key `%s' => %d", str_sanitize(str_c(key_item), 80), ret); + } + } + + sieve_runtime_trace_ascend(renv); + + if ( ret < 0 ) { + mctx->exec_status = key_list->exec_status; + match = -1; + } + + return match; +} + + + + + diff --git a/pigeonhole/src/lib-sieve/plugins/relational/mcht-value.c b/pigeonhole/src/lib-sieve/plugins/relational/mcht-value.c new file mode 100644 index 0000000..dd55590 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/relational/mcht-value.c @@ -0,0 +1,80 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" + +#include "sieve-ast.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-match.h" + +#include "ext-relational-common.h" + +/* + * Match-type objects + */ + +const struct sieve_match_type_def value_match_type = { + SIEVE_OBJECT("value", + &rel_match_type_operand, RELATIONAL_VALUE), + .validate = mcht_relational_validate +}; + +#define VALUE_MATCH_TYPE(name, rel_match) \ +const struct sieve_match_type_def rel_match_value_ ## name = { \ + SIEVE_OBJECT("value-" #name, \ + &rel_match_type_operand, \ + REL_MATCH_INDEX(RELATIONAL_VALUE, rel_match)), \ + .match_key = mcht_value_match_key, \ +} + +VALUE_MATCH_TYPE(gt, REL_MATCH_GREATER); +VALUE_MATCH_TYPE(ge, REL_MATCH_GREATER_EQUAL); +VALUE_MATCH_TYPE(lt, REL_MATCH_LESS); +VALUE_MATCH_TYPE(le, REL_MATCH_LESS_EQUAL); +VALUE_MATCH_TYPE(eq, REL_MATCH_EQUAL); +VALUE_MATCH_TYPE(ne, REL_MATCH_NOT_EQUAL); + +/* + * Match-type implementation + */ + +int mcht_value_match_key +(struct sieve_match_context *mctx, const char *val, size_t val_size, + const char *key, size_t key_size) +{ + const struct sieve_match_type *mtch = mctx->match_type; + unsigned int rel_match = REL_MATCH(mtch->object.def->code); + int cmp_result; + + cmp_result = mctx->comparator->def-> + compare(mctx->comparator, val, val_size, key, key_size); + + switch ( rel_match ) { + case REL_MATCH_GREATER: + return ( cmp_result > 0 ? 1 : 0 ); + case REL_MATCH_GREATER_EQUAL: + return ( cmp_result >= 0 ? 1 : 0 ); + case REL_MATCH_LESS: + return ( cmp_result < 0 ? 1 : 0 ); + case REL_MATCH_LESS_EQUAL: + return ( cmp_result <= 0 ? 1 : 0 ); + case REL_MATCH_EQUAL: + return ( cmp_result == 0 ? 1 : 0); + case REL_MATCH_NOT_EQUAL: + return ( cmp_result != 0 ? 1 : 0); + } + + i_unreached(); +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/spamvirustest/Makefile.am b/pigeonhole/src/lib-sieve/plugins/spamvirustest/Makefile.am new file mode 100644 index 0000000..6a15bdd --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/spamvirustest/Makefile.am @@ -0,0 +1,16 @@ +noinst_LTLIBRARIES = libsieve_ext_spamvirustest.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-spamvirustest.c + +libsieve_ext_spamvirustest_la_SOURCES = \ + $(tests) \ + ext-spamvirustest-common.c \ + ext-spamvirustest.c + +noinst_HEADERS = \ + ext-spamvirustest-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/spamvirustest/Makefile.in b/pigeonhole/src/lib-sieve/plugins/spamvirustest/Makefile.in new file mode 100644 index 0000000..dca31e3 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/spamvirustest/Makefile.in @@ -0,0 +1,694 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/spamvirustest +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_spamvirustest_la_LIBADD = +am__objects_1 = tst-spamvirustest.lo +am_libsieve_ext_spamvirustest_la_OBJECTS = $(am__objects_1) \ + ext-spamvirustest-common.lo ext-spamvirustest.lo +libsieve_ext_spamvirustest_la_OBJECTS = \ + $(am_libsieve_ext_spamvirustest_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ext-spamvirustest-common.Plo \ + ./$(DEPDIR)/ext-spamvirustest.Plo \ + ./$(DEPDIR)/tst-spamvirustest.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_spamvirustest_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_spamvirustest_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_spamvirustest.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-spamvirustest.c + +libsieve_ext_spamvirustest_la_SOURCES = \ + $(tests) \ + ext-spamvirustest-common.c \ + ext-spamvirustest.c + +noinst_HEADERS = \ + ext-spamvirustest-common.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/spamvirustest/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/spamvirustest/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_spamvirustest.la: $(libsieve_ext_spamvirustest_la_OBJECTS) $(libsieve_ext_spamvirustest_la_DEPENDENCIES) $(EXTRA_libsieve_ext_spamvirustest_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_spamvirustest_la_OBJECTS) $(libsieve_ext_spamvirustest_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-spamvirustest-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-spamvirustest.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-spamvirustest.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-spamvirustest-common.Plo + -rm -f ./$(DEPDIR)/ext-spamvirustest.Plo + -rm -f ./$(DEPDIR)/tst-spamvirustest.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ext-spamvirustest-common.Plo + -rm -f ./$(DEPDIR)/ext-spamvirustest.Plo + -rm -f ./$(DEPDIR)/tst-spamvirustest.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c b/pigeonhole/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c new file mode 100644 index 0000000..38cb5d8 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c @@ -0,0 +1,674 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "strfuncs.h" +#include "mail-storage.h" + +#include "sieve-common.h" +#include "sieve-settings.h" +#include "sieve-error.h" +#include "sieve-extensions.h" +#include "sieve-message.h" +#include "sieve-interpreter.h" +#include "sieve-runtime-trace.h" + +#include "ext-spamvirustest-common.h" + +#include <sys/types.h> +#include <regex.h> +#include <ctype.h> + +/* + * Extension data + */ + +enum ext_spamvirustest_status_type { + EXT_SPAMVIRUSTEST_STATUS_TYPE_SCORE, + EXT_SPAMVIRUSTEST_STATUS_TYPE_STRLEN, + EXT_SPAMVIRUSTEST_STATUS_TYPE_TEXT, +}; + +struct ext_spamvirustest_header_spec { + const char *header_name; + regex_t regexp; + bool regexp_match; +}; + +struct ext_spamvirustest_data { + pool_t pool; + + int reload; + + struct ext_spamvirustest_header_spec status_header; + struct ext_spamvirustest_header_spec max_header; + + enum ext_spamvirustest_status_type status_type; + + float max_value; + + const char *text_values[11]; +}; + +/* + * Regexp utility + */ + +static bool _regexp_compile +(regex_t *regexp, const char *data, const char **error_r) +{ + size_t errsize; + int ret; + + *error_r = ""; + + if ( (ret=regcomp(regexp, data, REG_EXTENDED)) == 0 ) { + return TRUE; + } + + errsize = regerror(ret, regexp, NULL, 0); + + if ( errsize > 0 ) { + char *errbuf = t_malloc0(errsize); + + (void)regerror(ret, regexp, errbuf, errsize); + + /* We don't want the error to start with a capital letter */ + errbuf[0] = i_tolower(errbuf[0]); + + *error_r = errbuf; + } + + return FALSE; +} + +static const char *_regexp_match_get_value +(const char *string, int index, regmatch_t pmatch[], int nmatch) +{ + if ( index > -1 && index < nmatch && pmatch[index].rm_so != -1 ) { + return t_strndup(string + pmatch[index].rm_so, + pmatch[index].rm_eo - pmatch[index].rm_so); + } + return NULL; +} + +/* + * Configuration parser + */ + +static bool ext_spamvirustest_header_spec_parse +(struct ext_spamvirustest_header_spec *spec, pool_t pool, const char *data, + const char **error_r) +{ + const char *p; + const char *regexp_error; + + if ( *data == '\0' ) { + *error_r = "empty header specification"; + return FALSE; + } + + /* Parse header name */ + + p = data; + + while ( *p == ' ' || *p == '\t' ) p++; + while ( *p != ':' && *p != '\0' && *p != ' ' && *p != '\t' ) p++; + + if ( *p == '\0' ) { + spec->header_name = p_strdup(pool, data); + return TRUE; + } + + spec->header_name = p_strdup_until(pool, data, p); + while ( *p == ' ' || *p == '\t' ) p++; + + if ( *p == '\0' ) { + spec->regexp_match = FALSE; + return TRUE; + } + + /* Parse and compile regular expression */ + + if ( *p != ':' ) { + *error_r = t_strdup_printf("expecting ':', but found '%c'", *p); + return FALSE; + } + p++; + while ( *p == ' ' || *p == '\t' ) p++; + + spec->regexp_match = TRUE; + if ( !_regexp_compile(&spec->regexp, p, ®exp_error) ) { + *error_r = t_strdup_printf("failed to compile regular expression '%s': " + "%s", p, regexp_error); + return FALSE; + } + + return TRUE; +} + +static void ext_spamvirustest_header_spec_free +(struct ext_spamvirustest_header_spec *spec) +{ + regfree(&spec->regexp); +} + +static bool ext_spamvirustest_parse_strlen_value +(const char *str_value, float *value_r, const char **error_r) +{ + const char *p = str_value; + char ch = *p; + + if ( *str_value == '\0' ) { + *value_r = 0; + return TRUE; + } + + while ( *p == ch ) p++; + + if ( *p != '\0' ) { + *error_r = t_strdup_printf( + "different character '%c' encountered in strlen value", + *p); + return FALSE; + } + + *value_r = ( p - str_value ); + + return TRUE; +} + +static bool ext_spamvirustest_parse_decimal_value +(const char *str_value, float *value_r, const char **error_r) +{ + const char *p = str_value; + float value; + float sign = 1; + int digits; + + if ( *p == '\0' ) { + *error_r = "empty value"; + return FALSE; + } + + if ( *p == '+' || *p == '-' ) { + if ( *p == '-' ) + sign = -1; + + p++; + } + + value = 0; + digits = 0; + while ( i_isdigit(*p) ) { + value = value*10 + (*p-'0'); + if ( digits++ > 4 ) { + *error_r = t_strdup_printf + ("decimal value has too many digits before radix point: %s", + str_value); + return FALSE; + } + p++; + } + + if ( *p == '.' || *p == ',' ) { + float radix = .1; + p++; + + digits = 0; + while ( i_isdigit(*p) ) { + value = value + (*p-'0')*radix; + + if ( digits++ > 4 ) { + *error_r = t_strdup_printf + ("decimal value has too many digits after radix point: %s", + str_value); + return FALSE; + } + radix /= 10; + p++; + } + } + + if ( *p != '\0' ) { + *error_r = t_strdup_printf + ("invalid decimal point value: %s", str_value); + return FALSE; + } + + *value_r = value * sign; + + return TRUE; +} + +/* + * Extension initialization + */ + +bool ext_spamvirustest_load +(const struct sieve_extension *ext, void **context) +{ + struct ext_spamvirustest_data *ext_data = + (struct ext_spamvirustest_data *) *context; + struct sieve_instance *svinst = ext->svinst; + const char *ext_name, *status_header, *max_header, *status_type, + *max_value; + enum ext_spamvirustest_status_type type; + const char *error; + pool_t pool; + bool result = TRUE; + int reload = 0; + + if ( *context != NULL ) { + reload = ext_data->reload + 1; + ext_spamvirustest_unload(ext); + *context = NULL; + } + + /* FIXME: + * Prevent loading of both spamtest and spamtestplus: let these share + * contexts. + */ + + if ( sieve_extension_is(ext, spamtest_extension) || + sieve_extension_is(ext, spamtestplus_extension) ) { + ext_name = spamtest_extension.name; + } else { + ext_name = sieve_extension_name(ext); + } + + /* Get settings */ + + status_header = sieve_setting_get + (svinst, t_strconcat("sieve_", ext_name, "_status_header", NULL)); + status_type = sieve_setting_get + (svinst, t_strconcat("sieve_", ext_name, "_status_type", NULL)); + max_header = sieve_setting_get + (svinst, t_strconcat("sieve_", ext_name, "_max_header", NULL)); + max_value = sieve_setting_get + (svinst, t_strconcat("sieve_", ext_name, "_max_value", NULL)); + + /* Base configuration */ + + if ( status_header == NULL ) { + return TRUE; + } + + if ( status_type == NULL || strcmp(status_type, "score") == 0 ) { + type = EXT_SPAMVIRUSTEST_STATUS_TYPE_SCORE; + } else if ( strcmp(status_type, "strlen") == 0 ) { + type = EXT_SPAMVIRUSTEST_STATUS_TYPE_STRLEN; + } else if ( strcmp(status_type, "text") == 0 ) { + type = EXT_SPAMVIRUSTEST_STATUS_TYPE_TEXT; + } else { + e_error(svinst->event, "%s: " + "invalid status type '%s'", ext_name, status_type); + return FALSE; + } + + /* Verify settings */ + + if ( type != EXT_SPAMVIRUSTEST_STATUS_TYPE_TEXT ) { + + if ( max_header != NULL && max_value != NULL ) { + e_error(svinst->event, "%s: " + "sieve_%s_max_header and sieve_%s_max_value " + "cannot both be configured", + ext_name, ext_name, ext_name); + return TRUE; + } + + if ( max_header == NULL && max_value == NULL ) { + e_error(svinst->event, "%s: " + "none of sieve_%s_max_header or sieve_%s_max_value " + "is configured", ext_name, ext_name, ext_name); + return TRUE; + } + } else { + if ( max_header != NULL ) { + e_warning(svinst->event, "%s: " + "setting sieve_%s_max_header has no meaning " + "for sieve_%s_status_type=text", + ext_name, ext_name, ext_name); + } + + if ( max_value != NULL ) { + e_warning(svinst->event, "%s: " + "setting sieve_%s_max_value has no meaning " + "for sieve_%s_status_type=text", + ext_name, ext_name, ext_name); + } + } + + pool = pool_alloconly_create("spamvirustest_data", 512); + ext_data = p_new(pool, struct ext_spamvirustest_data, 1); + ext_data->pool = pool; + ext_data->reload = reload; + ext_data->status_type = type; + + if ( !ext_spamvirustest_header_spec_parse + (&ext_data->status_header, ext_data->pool, status_header, &error) ) { + e_error(svinst->event, "%s: " + "invalid status header specification '%s': %s", + ext_name, status_header, error); + result = FALSE; + } + + if ( result ) { + if ( type != EXT_SPAMVIRUSTEST_STATUS_TYPE_TEXT ) { + /* Parse max header */ + + if ( max_header != NULL && !ext_spamvirustest_header_spec_parse + (&ext_data->max_header, ext_data->pool, max_header, &error) ) { + e_error(svinst->event, "%s: " + "invalid max header specification " + "'%s': %s", ext_name, max_header, + error); + result = FALSE; + } + + /* Parse max value */ + + if ( result && max_value != NULL ) { + if ( !ext_spamvirustest_parse_decimal_value + (max_value, &ext_data->max_value, &error) ) { + e_error(svinst->event, "%s: " + "invalid max value specification " + "'%s': %s", ext_name, max_value, + error); + result = FALSE; + } + } + + } else { + unsigned int i, max_text; + + max_text = ( sieve_extension_is(ext, virustest_extension) ? 5 : 10 ); + + /* Get text values */ + for ( i = 0; i <= max_text; i++ ) { + const char *value = sieve_setting_get + (svinst, t_strdup_printf("sieve_%s_text_value%d", ext_name, i)); + + if ( value != NULL && *value != '\0' ) + ext_data->text_values[i] = p_strdup(ext_data->pool, value); + } + + ext_data->max_value = 1; + } + } + + if ( result ) { + *context = (void *) ext_data; + } else { + e_warning(svinst->event, "%s: " + "extension not configured, " + "tests will always match against \"0\"", + ext_name); + ext_spamvirustest_unload(ext); + *context = NULL; + } + + return result; +} + +void ext_spamvirustest_unload(const struct sieve_extension *ext) +{ + struct ext_spamvirustest_data *ext_data = + (struct ext_spamvirustest_data *) ext->context; + + if ( ext_data != NULL ) { + ext_spamvirustest_header_spec_free(&ext_data->status_header); + ext_spamvirustest_header_spec_free(&ext_data->max_header); + pool_unref(&ext_data->pool); + } +} + +/* + * Runtime + */ + +struct ext_spamvirustest_message_context { + int reload; + float score_ratio; +}; + +static const char *ext_spamvirustest_get_score +(const struct sieve_extension *ext, float score_ratio, bool percent) +{ + int score; + + if ( score_ratio < 0 ) + return "0"; + + if ( score_ratio > 1 ) + score_ratio = 1; + + if ( percent ) + score = score_ratio * 100 + 0.001; + else if ( sieve_extension_is(ext, virustest_extension) ) + score = score_ratio * 4 + 1.001; + else + score = score_ratio * 9 + 1.001; + + return t_strdup_printf("%d", score); +} + +int ext_spamvirustest_get_value +(const struct sieve_runtime_env *renv, const struct sieve_extension *ext, + bool percent, const char **value_r) +{ + struct ext_spamvirustest_data *ext_data = + (struct ext_spamvirustest_data *) ext->context; + struct ext_spamvirustest_header_spec *status_header, *max_header; + struct sieve_message_context *msgctx = renv->msgctx; + struct ext_spamvirustest_message_context *mctx; + struct mail *mail; + regmatch_t match_values[2]; + const char *header_value, *error; + const char *status = NULL, *max = NULL; + float status_value, max_value; + unsigned int i, max_text; + pool_t pool = sieve_interpreter_pool(renv->interp); + + *value_r = "0"; + + /* + * Check whether extension is properly configured + */ + if ( ext_data == NULL ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "error: extension not configured"); + return SIEVE_EXEC_OK; + } + + /* + * Check wether a cached result is available + */ + + mctx = (struct ext_spamvirustest_message_context *) + sieve_message_context_extension_get(msgctx, ext); + + if ( mctx == NULL ) { + /* Create new context */ + mctx = p_new(pool, struct ext_spamvirustest_message_context, 1); + sieve_message_context_extension_set(msgctx, ext, (void *)mctx); + } else if ( mctx->reload == ext_data->reload ) { + /* Use cached result */ + *value_r = ext_spamvirustest_get_score(ext, mctx->score_ratio, percent); + return SIEVE_EXEC_OK; + } else { + /* Extension was reloaded (probably in testsuite) */ + } + + mctx->reload = ext_data->reload; + + /* + * Get max status value + */ + + mail = sieve_message_get_mail(renv->msgctx); + status_header = &ext_data->status_header; + max_header = &ext_data->max_header; + + if ( ext_data->status_type != EXT_SPAMVIRUSTEST_STATUS_TYPE_TEXT ) { + if ( max_header->header_name != NULL ) { + /* Get header from message */ + if ( mail_get_first_header_utf8 + (mail, max_header->header_name, &header_value) < 0 ) { + return sieve_runtime_mail_error (renv, mail, + "%s test: failed to read header field `%s'", + sieve_extension_name(ext), max_header->header_name); + } + if ( header_value == NULL ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "header '%s' not found in message", + max_header->header_name); + goto failed; + } + + if ( max_header->regexp_match ) { + /* Execute regex */ + if ( regexec(&max_header->regexp, header_value, 2, match_values, 0) + != 0 ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "regexp for header '%s' did not match " + "on value '%s'", max_header->header_name, header_value); + goto failed; + } + + max = _regexp_match_get_value(header_value, 1, match_values, 2); + if ( max == NULL ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "regexp did not return match value " + "for string '%s'", header_value); + goto failed; + } + } else { + max = header_value; + } + + if ( !ext_spamvirustest_parse_decimal_value(max, &max_value, &error) ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "failed to parse maximum value: %s", error); + goto failed; + } + } else { + max_value = ext_data->max_value; + } + + if ( max_value == 0 ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "error: max value is 0"); + goto failed; + } + } else { + max_value = ( sieve_extension_is(ext, virustest_extension) ? 5 : 10 ); + } + + /* + * Get status value + */ + + /* Get header from message */ + if ( mail_get_first_header_utf8 + (mail, status_header->header_name, &header_value) < 0 ) { + return sieve_runtime_mail_error (renv, mail, + "%s test: failed to read header field `%s'", + sieve_extension_name(ext), status_header->header_name); + } + if ( header_value == NULL ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "header '%s' not found in message", + status_header->header_name); + goto failed; + } + + /* Execute regex */ + if ( status_header->regexp_match ) { + if ( regexec(&status_header->regexp, header_value, 2, match_values, 0) + != 0 ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "regexp for header '%s' did not match on value '%s'", + status_header->header_name, header_value); + goto failed; + } + + status = _regexp_match_get_value(header_value, 1, match_values, 2); + if ( status == NULL ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "regexp did not return match value for string '%s'", + header_value); + goto failed; + } + } else { + status = header_value; + } + + switch ( ext_data->status_type ) { + case EXT_SPAMVIRUSTEST_STATUS_TYPE_SCORE: + if ( !ext_spamvirustest_parse_decimal_value + (status, &status_value, &error) ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "failed to parse status value '%s': %s", + status, error); + goto failed; + } + break; + case EXT_SPAMVIRUSTEST_STATUS_TYPE_STRLEN: + if ( !ext_spamvirustest_parse_strlen_value + (status, &status_value, &error) ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "failed to parse status value '%s': %s", + status, error); + goto failed; + } + break; + case EXT_SPAMVIRUSTEST_STATUS_TYPE_TEXT: + max_text = ( sieve_extension_is(ext, virustest_extension) ? 5 : 10 ); + status_value = 0; + + i = 0; + while ( i <= max_text ) { + if ( ext_data->text_values[i] != NULL && + strcmp(status, ext_data->text_values[i]) == 0 ) { + status_value = (float) i; + break; + } + i++; + } + + if ( i > max_text ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "failed to match textstatus value '%s'", + status); + goto failed; + } + break; + default: + i_unreached(); + break; + } + + /* Calculate value */ + if ( status_value < 0 ) + mctx->score_ratio = 0; + else if ( status_value > max_value ) + mctx->score_ratio = 1; + else + mctx->score_ratio = (status_value / max_value); + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "extracted score=%.3f, max=%.3f, ratio=%.0f %%", + status_value, max_value, mctx->score_ratio * 100); + + *value_r = ext_spamvirustest_get_score(ext, mctx->score_ratio, percent); + return SIEVE_EXEC_OK; + +failed: + mctx->score_ratio = -1; + *value_r = "0"; + return SIEVE_EXEC_OK; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h b/pigeonhole/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h new file mode 100644 index 0000000..331a637 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h @@ -0,0 +1,35 @@ +#ifndef EXT_SPAMVIRUSTEST_COMMON_H +#define EXT_SPAMVIRUSTEST_COMMON_H + +#include "sieve-common.h" + +/* + * Extensions + */ + +extern const struct sieve_extension_def spamtest_extension; +extern const struct sieve_extension_def spamtestplus_extension; +extern const struct sieve_extension_def virustest_extension; + +bool ext_spamvirustest_load(const struct sieve_extension *ext, void **context); +void ext_spamvirustest_unload(const struct sieve_extension *ext); + +/* + * Tests + */ + +extern const struct sieve_command_def spamtest_test; +extern const struct sieve_command_def virustest_test; + +int ext_spamvirustest_get_value +(const struct sieve_runtime_env *renv, const struct sieve_extension *ext, + bool percent, const char **value_r); + +/* + * Operations + */ + +extern const struct sieve_operation_def spamtest_operation; +extern const struct sieve_operation_def virustest_operation; + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c b/pigeonhole/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c new file mode 100644 index 0000000..e0c9b54 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c @@ -0,0 +1,146 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extensions spamtest, spamtestplus and virustest + * ----------------------------------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5235 + * Implementation: full + * Status: testing + * + */ + +/* Configuration examples: + * + * # 1: X-Spam-Score: No, score=-3.2 + * + * sieve_spamtest_status_header = \ + * X-Spam-Score: [[:alnum:]]+, score=(-?[[:digit:]]+\.[[:digit:]]) + * sieve_spamtest_max_value = 5.0 + * + * # 2: X-Spam-Status: Yes + * + * sieve_spamtest_status_header = X-Spam-Status + * sieve_spamtest_status_type = yesno + * sieve_spamtest_max_value = Yes + * + * # 3: X-Spam-Score: sssssss + * sieve_spamtest_status_header = X-Spam-Score + * sieve_spamtest_status_type = strlen + * sieve_spamtest_max_value = 5 + * + * # 4: X-Spam-Score: status=3.2 required=5.0 + * + * sieve_spamtest_status_header = \ + * X-Spam-Score: score=(-?[[:digit:]]+\.[[:digit:]]).* + * sieve_spamtest_max_header = \ + * X-Spam-Score: score=-?[[:digit:]]+\.[[:digit:]] required=([[:digit:]]+\.[[:digit:]]) + * + * # 5: X-Virus-Scan: Found to be clean. + * + * sieve_virustest_status_header = \ + * X-Virus-Scan: Found to be (.+)\. + * sieve_virustest_status_type = text + * sieve_virustest_text_value1 = clean + * sieve_virustest_text_value5 = infected + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-common.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" + +#include "sieve-validator.h" + +#include "ext-spamvirustest-common.h" + +/* + * Extensions + */ + +/* Spamtest */ + +static bool ext_spamvirustest_validator_load +(const struct sieve_extension *ext, struct sieve_validator *validator); + +const struct sieve_extension_def spamtest_extension = { + .name = "spamtest", + .load = ext_spamvirustest_load, + .unload = ext_spamvirustest_unload, + .validator_load = ext_spamvirustest_validator_load, + SIEVE_EXT_DEFINE_OPERATION(spamtest_operation) +}; + +const struct sieve_extension_def spamtestplus_extension = { + .name = "spamtestplus", + .load = ext_spamvirustest_load, + .unload = ext_spamvirustest_unload, + .validator_load = ext_spamvirustest_validator_load, + SIEVE_EXT_DEFINE_OPERATION(spamtest_operation) +}; + +const struct sieve_extension_def virustest_extension = { + .name = "virustest", + .load = ext_spamvirustest_load, + .unload = ext_spamvirustest_unload, + .validator_load = ext_spamvirustest_validator_load, + SIEVE_EXT_DEFINE_OPERATION(virustest_operation) +}; + +/* + * Implementation + */ + +static bool ext_spamtest_validator_check_conflict + (const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + const struct sieve_extension *ext_other, + bool required); + +const struct sieve_validator_extension spamtest_validator_extension = { + .ext = &spamtest_extension, + .check_conflict = ext_spamtest_validator_check_conflict +}; + +static bool ext_spamvirustest_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register new test */ + + if ( sieve_extension_is(ext, virustest_extension) ) { + sieve_validator_register_command(valdtr, ext, &virustest_test); + } else { + if ( sieve_extension_is(ext, spamtest_extension) ) { + /* Register validator extension to warn for duplicate */ + sieve_validator_extension_register + (valdtr, ext, &spamtest_validator_extension, NULL); + } + + sieve_validator_register_command(valdtr, ext, &spamtest_test); + } + + return TRUE; +} + +static bool ext_spamtest_validator_check_conflict +(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_validator *valdtr, void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg, + const struct sieve_extension *ext_other, + bool required ATTR_UNUSED) +{ + if ( sieve_extension_name_is(ext_other, "spamtestplus") ) { + sieve_argument_validate_warning(valdtr, require_arg, + "the spamtest and spamtestplus extensions should " + "not be specified at the same time"); + } + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c b/pigeonhole/src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c new file mode 100644 index 0000000..26d051e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c @@ -0,0 +1,304 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-spamvirustest-common.h" + +/* + * Tests + */ + +static bool tst_spamvirustest_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_spamvirustest_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); +static bool tst_spamvirustest_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); + +/* Spamtest test + * + * Syntax: + * spamtest [":percent"] [COMPARATOR] [MATCH-TYPE] <value: string> + */ + +const struct sieve_command_def spamtest_test = { + .identifier = "spamtest", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_spamvirustest_registered, + .validate = tst_spamvirustest_validate, + .generate = tst_spamvirustest_generate +}; + +/* Virustest test + * + * Syntax: + * virustest [COMPARATOR] [MATCH-TYPE] <value: string> + */ + +const struct sieve_command_def virustest_test = { + .identifier = "virustest", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_spamvirustest_registered, + .validate = tst_spamvirustest_validate, + .generate = tst_spamvirustest_generate +}; + +/* + * Tagged arguments + */ + +static bool tst_spamtest_validate_percent_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *tst); + +static const struct sieve_argument_def spamtest_percent_tag = { + .identifier = "percent", + .validate = tst_spamtest_validate_percent_tag +}; + +/* + * Spamtest and virustest operations + */ + +static bool tst_spamvirustest_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_spamvirustest_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def spamtest_operation = { + .mnemonic = "SPAMTEST", + .ext_def = &spamtest_extension, + .dump = tst_spamvirustest_operation_dump, + .execute = tst_spamvirustest_operation_execute +}; + +const struct sieve_operation_def virustest_operation = { + .mnemonic = "VIRUSTEST", + .ext_def = &virustest_extension, + .dump = tst_spamvirustest_operation_dump, + .execute = tst_spamvirustest_operation_execute +}; + +/* + * Optional operands + */ + +enum tst_spamvirustest_optional { + OPT_SPAMTEST_PERCENT = SIEVE_MATCH_OPT_LAST, + OPT_SPAMTEST_LAST +}; + +/* + * Test registration + */ + +static bool tst_spamvirustest_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + + if ( sieve_extension_is(ext, spamtestplus_extension) || + sieve_extension_is(ext, spamtest_extension) ) { + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &spamtest_percent_tag, OPT_SPAMTEST_PERCENT); + } + + return TRUE; +} + +/* + * Validation + */ + +static bool tst_spamtest_validate_percent_tag +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *tst) +{ + if ( !sieve_extension_is(tst->ext, spamtestplus_extension) ) { + sieve_argument_validate_error(valdtr, *arg, + "the spamtest test only accepts the :percent argument when " + "the spamtestplus extension is active"); + return FALSE; + } + + /* Skip tag */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +static bool tst_spamvirustest_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + const struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + + /* Check value */ + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "value", 1, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate + (valdtr, tst, arg, &mcht_default, &cmp_default); +} + +/* + * Code generation + */ + +static bool tst_spamvirustest_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *tst) +{ + if ( sieve_command_is(tst, spamtest_test) ) + sieve_operation_emit(cgenv->sblock, tst->ext, &spamtest_operation); + else if ( sieve_command_is(tst, virustest_test) ) + sieve_operation_emit(cgenv->sblock, tst->ext, &virustest_operation); + else + i_unreached(); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool tst_spamvirustest_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + int opt_code = 0; + const struct sieve_operation *op = denv->oprtn; + + sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(op)); + sieve_code_descend(denv); + + /* Optional operands */ + for (;;) { + int opt; + + if ( (opt=sieve_match_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_SPAMTEST_PERCENT: + sieve_code_dumpf(denv, "percent"); + break; + default: + return FALSE; + } + } + + return + sieve_opr_string_dump(denv, address, "value"); +} + +/* + * Code execution + */ + +static int tst_spamvirustest_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_operation *op = renv->oprtn; + const struct sieve_extension *this_ext = op->ext; + int opt_code = 0; + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + bool percent = FALSE; + struct sieve_stringlist *value_list, *key_list; + const char *score_value; + int match, ret; + + /* Read optional operands */ + for (;;) { + int opt; + + if ( (opt=sieve_match_opr_optional_read + (renv, address, &opt_code, &ret, &cmp, &mcht)) < 0 ) + return ret; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_SPAMTEST_PERCENT: + percent = TRUE; + break; + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + } + + /* Read value part */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "value", &key_list)) <= 0 ) + return ret; + + /* Perform test */ + + if ( sieve_operation_is(op, spamtest_operation) ) { + sieve_runtime_trace + (renv, SIEVE_TRLVL_TESTS, "spamtest test [percent=%s]", + ( percent ? "true" : "false" )); + } else { + sieve_runtime_trace + (renv, SIEVE_TRLVL_TESTS, "virustest test"); + } + + /* Get score value */ + sieve_runtime_trace_descend(renv); + if ( (ret=ext_spamvirustest_get_value + (renv, this_ext, percent, &score_value)) <= 0 ) + return ret; + sieve_runtime_trace_ascend(renv); + + /* Construct value list */ + value_list = sieve_single_stringlist_create_cstr(renv, score_value, TRUE); + + /* Perform match */ + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/special-use/Makefile.am b/pigeonhole/src/lib-sieve/plugins/special-use/Makefile.am new file mode 100644 index 0000000..0f31aee --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/special-use/Makefile.am @@ -0,0 +1,22 @@ +noinst_LTLIBRARIES = libsieve_ext_special_use.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tags = \ + tag-specialuse.c + +tests = \ + tst-specialuse-exists.c + +libsieve_ext_special_use_la_SOURCES = \ + $(tags) \ + $(tests) \ + ext-special-use-common.c \ + ext-special-use.c + +headers = \ + ext-special-use-common.h + +noinst_HEADERS = $(headers) diff --git a/pigeonhole/src/lib-sieve/plugins/special-use/Makefile.in b/pigeonhole/src/lib-sieve/plugins/special-use/Makefile.in new file mode 100644 index 0000000..5032dae --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/special-use/Makefile.in @@ -0,0 +1,703 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/special-use +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_special_use_la_LIBADD = +am__objects_1 = tag-specialuse.lo +am__objects_2 = tst-specialuse-exists.lo +am_libsieve_ext_special_use_la_OBJECTS = $(am__objects_1) \ + $(am__objects_2) ext-special-use-common.lo ext-special-use.lo +libsieve_ext_special_use_la_OBJECTS = \ + $(am_libsieve_ext_special_use_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ext-special-use-common.Plo \ + ./$(DEPDIR)/ext-special-use.Plo ./$(DEPDIR)/tag-specialuse.Plo \ + ./$(DEPDIR)/tst-specialuse-exists.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_special_use_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_special_use_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_special_use.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tags = \ + tag-specialuse.c + +tests = \ + tst-specialuse-exists.c + +libsieve_ext_special_use_la_SOURCES = \ + $(tags) \ + $(tests) \ + ext-special-use-common.c \ + ext-special-use.c + +headers = \ + ext-special-use-common.h + +noinst_HEADERS = $(headers) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/special-use/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/special-use/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_special_use.la: $(libsieve_ext_special_use_la_OBJECTS) $(libsieve_ext_special_use_la_DEPENDENCIES) $(EXTRA_libsieve_ext_special_use_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_special_use_la_OBJECTS) $(libsieve_ext_special_use_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-special-use-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-special-use.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tag-specialuse.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-specialuse-exists.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-special-use-common.Plo + -rm -f ./$(DEPDIR)/ext-special-use.Plo + -rm -f ./$(DEPDIR)/tag-specialuse.Plo + -rm -f ./$(DEPDIR)/tst-specialuse-exists.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ext-special-use-common.Plo + -rm -f ./$(DEPDIR)/ext-special-use.Plo + -rm -f ./$(DEPDIR)/tag-specialuse.Plo + -rm -f ./$(DEPDIR)/tst-specialuse-exists.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/special-use/ext-special-use-common.c b/pigeonhole/src/lib-sieve/plugins/special-use/ext-special-use-common.c new file mode 100644 index 0000000..fcaf1b5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/special-use/ext-special-use-common.c @@ -0,0 +1,31 @@ +/* Copyright (c) 2019 Pigeonhole authors, see the included COPYING file */ + +#include "lib.h" +#include "imap-arg.h" + +#include "ext-special-use-common.h" + +bool ext_special_use_flag_valid(const char *flag) +{ + const char *p = flag; + + /* RFC 6154, Section 6: + + use-attr = "\All" / "\Archive" / "\Drafts" / "\Flagged" / + "\Junk" / "\Sent" / "\Trash" / use-attr-ext + use-attr-ext = "\" atom + */ + + /* "\" */ + if (*p != '\\') + return FALSE; + p++; + + /* atom */ + for (; *p != '\0'; p++) { + if (!IS_ATOM_CHAR(*p)) + return FALSE; + } + + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/special-use/ext-special-use-common.h b/pigeonhole/src/lib-sieve/plugins/special-use/ext-special-use-common.h new file mode 100644 index 0000000..61f23d0 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/special-use/ext-special-use-common.h @@ -0,0 +1,43 @@ +#ifndef EXT_SPECIAL_USE_COMMON_H +#define EXT_SPECIAL_USE_COMMON_H + +#include "sieve-common.h" + +/* + * Tagged arguments + */ + +extern const struct sieve_argument_def specialuse_tag; + +/* + * Commands + */ + +extern const struct sieve_command_def specialuse_exists_test; + +/* + * Operands + */ + +extern const struct sieve_operand_def specialuse_operand; + +/* + * Operations + */ + +extern const struct sieve_operation_def specialuse_exists_operation; + +/* + * Extension + */ + +extern const struct sieve_extension_def special_use_extension; + +/* + * Flag checking + */ + +bool ext_special_use_flag_valid(const char *flag); + +#endif /* EXT_SPECIAL_USE_COMMON_H */ + diff --git a/pigeonhole/src/lib-sieve/plugins/special-use/ext-special-use.c b/pigeonhole/src/lib-sieve/plugins/special-use/ext-special-use.c new file mode 100644 index 0000000..acbb13e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/special-use/ext-special-use.c @@ -0,0 +1,57 @@ +/* Copyright (c) 2019 Pigeonhole authors, see the included COPYING file */ + +/* Extension special-use + * --------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 8579 + * Implementation: full + * Status: testing + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "ext-special-use-common.h" + +/* + * Extension + */ + +static bool +ext_special_use_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr); + +const struct sieve_extension_def special_use_extension = { + .name = "special-use", + .validator_load = ext_special_use_validator_load, + SIEVE_EXT_DEFINE_OPERATION(specialuse_exists_operation), + SIEVE_EXT_DEFINE_OPERAND(specialuse_operand) +}; + +static bool +ext_special_use_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr) +{ + /* Register :specialuse tag with fileinto command and we don't care + whether this command is registered or even whether it will be + registered at all. The validator handles either situation gracefully. + */ + sieve_validator_register_external_tag( + valdtr, "fileinto", ext, &specialuse_tag, + SIEVE_OPT_SIDE_EFFECT); + + /* Register new test */ + sieve_validator_register_command(valdtr, ext, &specialuse_exists_test); + + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/special-use/tag-specialuse.c b/pigeonhole/src/lib-sieve/plugins/special-use/tag-specialuse.c new file mode 100644 index 0000000..0f6d32a --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/special-use/tag-specialuse.c @@ -0,0 +1,316 @@ +/* Copyright (c) 2019 Pigeonhole authors, see the included COPYING file */ + +#include "lib.h" +#include "str-sanitize.h" +#include "mail-storage.h" +#include "mail-namespace.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-code.h" +#include "sieve-actions.h" +#include "sieve-result.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-special-use-common.h" + +/* + * Flags tagged argument + */ + +static bool +tag_specialuse_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +tag_specialuse_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, + struct sieve_command *cmd); + +const struct sieve_argument_def specialuse_tag = { + .identifier = "specialuse", + .validate = tag_specialuse_validate, + .generate = tag_specialuse_generate +}; + +/* + * Side effect + */ + +static bool +seff_specialuse_dump_context(const struct sieve_side_effect *seffect, + const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +seff_specialuse_read_context(const struct sieve_side_effect *seffect, + const struct sieve_runtime_env *renv, + sieve_size_t *address, void **context); + +static int +seff_specialuse_merge(const struct sieve_runtime_env *renv, + const struct sieve_action *action, + const struct sieve_side_effect *old_seffect, + const struct sieve_side_effect *new_seffect, + void **old_context); + +static void +seff_specialuse_print(const struct sieve_side_effect *seffect, + const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep); + +static int +seff_specialuse_pre_execute(const struct sieve_side_effect *seffect, + const struct sieve_action_exec_env *aenv, + void *tr_context, void **se_tr_context ATTR_UNUSED); + +const struct sieve_side_effect_def specialuse_side_effect = { + SIEVE_OBJECT("specialuse", &specialuse_operand, 0), + .precedence = 200, + .to_action = &act_store, + .dump_context = seff_specialuse_dump_context, + .read_context = seff_specialuse_read_context, + .merge = seff_specialuse_merge, + .print = seff_specialuse_print, + .pre_execute = seff_specialuse_pre_execute +}; + +/* + * Operand + */ + +static const struct sieve_extension_objects ext_side_effects = + SIEVE_EXT_DEFINE_SIDE_EFFECT(specialuse_side_effect); + +const struct sieve_operand_def specialuse_operand = { + .name = "specialuse operand", + .ext_def = &special_use_extension, + .class = &sieve_side_effect_operand_class, + .interface = &ext_side_effects +}; + +/* + * Tag validation + */ + +static bool +tag_specialuse_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + + /* Detach the tag itself */ + *arg = sieve_ast_argument_next(*arg); + + /* Check syntax: + * :specialuse <special-use-flag: string> + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING, FALSE)) + return FALSE; + if (sieve_argument_is_string_literal(*arg)) { + const char *use_flag = sieve_ast_argument_strc(*arg); + + if (!ext_special_use_flag_valid(use_flag)) { + sieve_argument_validate_error( + valdtr, *arg, "specialuse tag: " + "invalid special-use flag `%s' specified", + str_sanitize(use_flag, 64)); + return FALSE; + } + } + + tag->parameters = *arg; + + /* Detach parameter */ + *arg = sieve_ast_arguments_detach(*arg,1); + + return TRUE; +} + +/* + * Code generation + */ + +static bool +tag_specialuse_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *param; + + if (sieve_ast_argument_type(arg) != SAAT_TAG) + return FALSE; + + sieve_opr_side_effect_emit(cgenv->sblock, arg->argument->ext, + &specialuse_side_effect); + + /* Explicit :specialuse tag */ + param = arg->parameters; + + /* Call the generation function for the argument */ + if (param->argument != NULL && param->argument->def != NULL && + param->argument->def->generate != NULL && + !param->argument->def->generate(cgenv, param, cmd)) + return FALSE; + + return TRUE; +} + +/* + * Side effect implementation + */ + +/* Context data */ + +struct seff_specialuse_context { + const char *special_use_flag; +}; + +/* Context coding */ + +static bool +seff_specialuse_dump_context( + const struct sieve_side_effect *seffect ATTR_UNUSED, + const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + return sieve_opr_stringlist_dump(denv, address, "specialuse"); +} + +static int +seff_specialuse_read_context( + const struct sieve_side_effect *seffect ATTR_UNUSED, + const struct sieve_runtime_env *renv, sieve_size_t *address, + void **se_context) +{ + pool_t pool = sieve_result_pool(renv->result); + struct seff_specialuse_context *ctx; + string_t *special_use_flag; + const char *use_flag; + int ret; + + if ((ret = sieve_opr_string_read(renv, address, "specialuse", + &special_use_flag)) <= 0) + return ret; + + use_flag = str_c(special_use_flag); + if (!ext_special_use_flag_valid(use_flag)) { + sieve_runtime_error( + renv, NULL, "specialuse tag: " + "invalid special-use flag `%s' specified", + str_sanitize(use_flag, 64)); + return SIEVE_EXEC_FAILURE; + } + + ctx = p_new(pool, struct seff_specialuse_context, 1); + ctx->special_use_flag = p_strdup(pool, use_flag); + + *se_context = (void *) ctx; + + return SIEVE_EXEC_OK; +} + +/* Result verification */ + +static int +seff_specialuse_merge(const struct sieve_runtime_env *renv ATTR_UNUSED, + const struct sieve_action *action ATTR_UNUSED, + const struct sieve_side_effect *old_seffect ATTR_UNUSED, + const struct sieve_side_effect *new_seffect, + void **old_context) +{ + if (new_seffect != NULL) + *old_context = new_seffect->context; + + return 1; +} + +/* Result printing */ + +static void +seff_specialuse_print(const struct sieve_side_effect *seffect, + const struct sieve_action *action ATTR_UNUSED, + const struct sieve_result_print_env *rpenv, + bool *keep ATTR_UNUSED) +{ + struct seff_specialuse_context *ctx = + (struct seff_specialuse_context *)seffect->context; + + sieve_result_seffect_printf( + rpenv, + "use mailbox with special-use flag `%s' instead if accessible", + ctx->special_use_flag); +} + +/* Result execution */ + +static int +seff_specialuse_pre_execute(const struct sieve_side_effect *seffect, + const struct sieve_action_exec_env *aenv, + void *tr_context, void **se_tr_context ATTR_UNUSED) +{ + struct seff_specialuse_context *ctx = + (struct seff_specialuse_context *)seffect->context; + const struct sieve_execute_env *eenv = aenv->exec_env; + struct act_store_transaction *trans = + (struct act_store_transaction *)tr_context; + struct mailbox *box; + + if (trans->box == NULL || trans->disabled) + return SIEVE_EXEC_OK; + + /* Check whether something already failed */ + switch (trans->error_code) { + case MAIL_ERROR_NONE: + break; + case MAIL_ERROR_TEMP: + return SIEVE_EXEC_TEMP_FAILURE; + default: + return SIEVE_EXEC_FAILURE; + } + + trans->error = NULL; + trans->error_code = MAIL_ERROR_NONE; + + box = mailbox_alloc_for_user(eenv->scriptenv->user, + ctx->special_use_flag, + (MAILBOX_FLAG_POST_SESSION | + MAILBOX_FLAG_SPECIAL_USE)); + + /* We still override the allocate default mailbox with ours below even + when the default and special-use mailbox are identical. Choosing + either one is (currently) equal and setting trans->mailbox_identifier + for SPECIAL-USE needs to be done either way, so we use the same code + path. */ + + /* Try to open the mailbox */ + eenv->exec_status->last_storage = mailbox_get_storage(box); + if (mailbox_open(box) == 0) { + pool_t pool = sieve_result_pool(aenv->result); + + /* Success */ + mailbox_free(&trans->box); + trans->box = box; + trans->mailbox_identifier = p_strdup_printf(pool, + "[SPECIAL-USE %s]", ctx->special_use_flag); + + } else { + /* Failure */ + if (mailbox_get_last_mail_error(box) == MAIL_ERROR_NOTFOUND) { + /* Not found; revert to default */ + mailbox_free(&box); + } else { + /* Total failure */ + mailbox_free(&trans->box); + trans->box = box; + sieve_act_store_get_storage_error(aenv, trans); + return (trans->error_code == MAIL_ERROR_TEMP ? + SIEVE_EXEC_TEMP_FAILURE : SIEVE_EXEC_FAILURE); + } + } + + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/special-use/tst-specialuse-exists.c b/pigeonhole/src/lib-sieve/plugins/special-use/tst-specialuse-exists.c new file mode 100644 index 0000000..a1aa878 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/special-use/tst-specialuse-exists.c @@ -0,0 +1,525 @@ +/* Copyright (c) 2019 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" +#include "mail-storage.h" +#include "mail-namespace.h" + +#include "sieve-common.h" +#include "sieve-actions.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-special-use-common.h" + +/* + * specialuse_exists command + * + * Syntax: + * specialuse_exists [<mailbox: string>] + * <special-use-flags: string-list> + */ + +static bool +tst_specialuse_exists_validate(struct sieve_validator *valdtr, + struct sieve_command *tst); +static bool +tst_specialuse_exists_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def specialuse_exists_test = { + .identifier = "specialuse_exists", + .type = SCT_TEST, + .positional_args = -1, /* We check positional arguments ourselves */ + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = tst_specialuse_exists_validate, + .generate = tst_specialuse_exists_generate, +}; + +/* + * Mailboxexists operation + */ + +static bool +tst_specialuse_exists_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +tst_specialuse_exists_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def specialuse_exists_operation = { + .mnemonic = "SPECIALUSE_EXISTS", + .ext_def = &special_use_extension, + .dump = tst_specialuse_exists_operation_dump, + .execute = tst_specialuse_exists_operation_execute, +}; + +/* + * Test validation + */ + +struct _validate_context { + struct sieve_validator *valdtr; + struct sieve_command *tst; +}; + +static int +tst_specialuse_exists_flag_validate(void *context, + struct sieve_ast_argument *arg) +{ + struct _validate_context *valctx = (struct _validate_context *)context; + + if (sieve_argument_is_string_literal(arg)) { + const char *flag = sieve_ast_argument_strc(arg); + + if (!ext_special_use_flag_valid(flag)) { + sieve_argument_validate_error( + valctx->valdtr, arg, "%s test: " + "invalid special-use flag `%s' specified", + sieve_command_identifier(valctx->tst), + str_sanitize(flag, 64)); + } + } + + return 1; +} + +static bool +tst_specialuse_exists_validate(struct sieve_validator *valdtr, + struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + struct sieve_ast_argument *arg2; + struct sieve_ast_argument *aarg; + struct _validate_context valctx; + + if (arg == NULL) { + sieve_command_validate_error( + valdtr, tst, "the %s %s expects at least one argument, " + "but none was found", + sieve_command_identifier(tst), + sieve_command_type_name(tst)); + return FALSE; + } + + if (sieve_ast_argument_type(arg) != SAAT_STRING && + sieve_ast_argument_type(arg) != SAAT_STRING_LIST) { + sieve_argument_validate_error( + valdtr, arg, + "the %s %s expects either a string (mailbox) or " + "a string-list (special-use flags) as first argument, " + "but %s was found", + sieve_command_identifier(tst), + sieve_command_type_name(tst), + sieve_ast_argument_name(arg)); + return FALSE; + } + + arg2 = sieve_ast_argument_next(arg); + if (arg2 != NULL) { + /* First, check syntax sanity */ + if (sieve_ast_argument_type(arg) != SAAT_STRING) { + sieve_argument_validate_error( + valdtr, arg, + "if a second argument is specified for the %s %s, " + "the first must be a string (mailbox), " + "but %s was found", + sieve_command_identifier(tst), + sieve_command_type_name(tst), + sieve_ast_argument_name(arg)); + return FALSE; + } + if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) + return FALSE; + + /* Check name validity when mailbox argument is not a variable */ + if (sieve_argument_is_string_literal(arg)) { + const char *mailbox = sieve_ast_argument_strc(arg); + const char *error; + + if (!sieve_mailbox_check_name(mailbox, &error)) { + sieve_argument_validate_warning( + valdtr, arg, "%s test: " + "invalid mailbox name `%s' specified: %s", + sieve_command_identifier(tst), + str_sanitize(mailbox, 256), error); + } + } + + if (sieve_ast_argument_type(arg2) != SAAT_STRING && + sieve_ast_argument_type(arg2) != SAAT_STRING_LIST) { + sieve_argument_validate_error( + valdtr, arg2, + "the %s %s expects a string list (special-use flags) as " + "second argument when two arguments are specified, " + "but %s was found", + sieve_command_identifier(tst), + sieve_command_type_name(tst), + sieve_ast_argument_name(arg2)); + return FALSE; + } + } else + arg2 = arg; + + if (!sieve_validator_argument_activate(valdtr, tst, arg2, FALSE)) + return FALSE; + + aarg = arg2; + memset(&valctx, 0, sizeof(valctx)); + valctx.valdtr = valdtr; + valctx.tst = tst; + + return (sieve_ast_stringlist_map( + &aarg, (void*)&valctx, + tst_specialuse_exists_flag_validate) >= 0); +} + +/* + * Test generation + */ + +static bool +tst_specialuse_exists_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + struct sieve_ast_argument *arg2; + + sieve_operation_emit(cgenv->sblock, + tst->ext, &specialuse_exists_operation); + + /* Generate arguments */ + arg2 = sieve_ast_argument_next(arg); + if (arg2 != NULL) { + if (!sieve_generate_argument(cgenv, arg, tst)) + return FALSE; + } else { + sieve_opr_omitted_emit(cgenv->sblock); + arg2 = arg; + } + return sieve_generate_argument(cgenv, arg2, tst); +} + +/* + * Code dump + */ + +static bool +tst_specialuse_exists_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + struct sieve_operand oprnd; + + sieve_code_dumpf(denv, "SPECIALUSE_EXISTS"); + sieve_code_descend(denv); + + sieve_code_mark(denv); + if (!sieve_operand_read(denv->sblock, address, NULL, &oprnd)) { + sieve_code_dumpf(denv, "ERROR: INVALID OPERAND"); + return FALSE; + } + + if (!sieve_operand_is_omitted(&oprnd)) { + return (sieve_opr_string_dump_data(denv, &oprnd, + address, "mailbox") && + sieve_opr_stringlist_dump(denv, address, + "special-use-flags")); + } + + return sieve_opr_stringlist_dump(denv, address, "special-use-flags"); +} + +/* + * Code execution + */ + +static int +tst_specialuse_find_mailbox(const struct sieve_runtime_env *renv, + const char *mailbox, struct mailbox **box_r) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct mail_user *user = eenv->scriptenv->user; + struct mailbox *box; + bool trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); + enum mail_error error_code; + const char *error; + + *box_r = NULL; + + if (user == NULL) + return 0; + + /* Open the box */ + box = mailbox_alloc_for_user(user, mailbox, MAILBOX_FLAG_POST_SESSION); + if (mailbox_open(box) < 0) { + error = mailbox_get_last_internal_error(box, &error_code); + + if (trace) { + sieve_runtime_trace( + renv, 0, "mailbox `%s' cannot be opened: %s", + str_sanitize(mailbox, 256), error); + } + + mailbox_free(&box); + + if (error_code == MAIL_ERROR_TEMP) { + sieve_runtime_error( + renv, NULL, "specialuse_exists test: " + "failed to open mailbox `%s': %s", + str_sanitize(mailbox, 256), error); + return -1; + } + return 0; + } + + /* Also fail when it is readonly */ + if (mailbox_is_readonly(box)) { + if (trace) { + sieve_runtime_trace( + renv, 0, "mailbox `%s' is read-only", + str_sanitize(mailbox, 256)); + } + + mailbox_free(&box); + return 0; + } + + *box_r = box; + return 1; +} + +static int +tst_specialuse_find_specialuse(const struct sieve_runtime_env *renv, + const char *special_use) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct mail_user *user = eenv->scriptenv->user; + struct mailbox *box; + bool trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); + enum mail_error error_code; + const char *error; + + if (user == NULL) + return 0; + + /* Open the box */ + box = mailbox_alloc_for_user(user, special_use, + (MAILBOX_FLAG_POST_SESSION | + MAILBOX_FLAG_SPECIAL_USE)); + if (mailbox_open(box) < 0) { + error = mailbox_get_last_internal_error(box, &error_code); + + if (trace) { + sieve_runtime_trace( + renv, 0, "mailbox with special-use flag `%s' " + "cannot be opened: %s", + str_sanitize(special_use, 64), error); + } + + mailbox_free(&box); + + if (error_code == MAIL_ERROR_TEMP) { + sieve_runtime_error( + renv, NULL, "specialuse_exists test: " + "failed to open mailbox with special-use flag`%s': %s", + str_sanitize(special_use, 64), error); + return -1; + } + return 0; + } + + /* Also fail when it is readonly */ + if (mailbox_is_readonly(box)) { + if (trace) { + sieve_runtime_trace( + renv, 0, + "mailbox with special-use flag `%s' is read-only", + str_sanitize(special_use, 64)); + } + + mailbox_free(&box); + return 0; + } + + mailbox_free(&box); + return 1; +} + +static int +tst_specialuse_exists_check_flag(const struct sieve_runtime_env *renv, + struct mailbox *box, const char *use_flag, + bool trace, bool *all_exist_r) +{ + int ret; + + if (!ext_special_use_flag_valid(use_flag)) { + sieve_runtime_error( + renv, NULL, "specialuse_exists test: " + "invalid special-use flag `%s' specified", + str_sanitize(use_flag, 64)); + return SIEVE_EXEC_FAILURE; + } + + if (box != NULL) { + /* Mailbox has this SPECIAL-USE flag? */ + if (!mailbox_has_special_use(box, use_flag)) { + *all_exist_r = FALSE; + return SIEVE_EXEC_OK; + } + } else { + /* Is there mailbox with this SPECIAL-USE flag? */ + ret = tst_specialuse_find_specialuse(renv, use_flag); + if (ret < 0) + return SIEVE_EXEC_TEMP_FAILURE; + if (ret == 0) { + *all_exist_r = FALSE; + return SIEVE_EXEC_OK; + } + } + + if (trace) { + sieve_runtime_trace( + renv, 0, "special-use flag `%s' exists", + str_sanitize(use_flag, 80)); + } + + return SIEVE_EXEC_OK; +} + +static int +tst_specialuse_exists_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + struct sieve_operand oprnd; + struct sieve_stringlist *special_use_flags; + string_t *mailbox, *special_use_flag; + struct mailbox *box = NULL; + const char *error; + bool trace = FALSE, all_exist = TRUE; + int ret; + + /* + * Read operands + */ + + /* Read bare operand (two types possible) */ + ret = sieve_operand_runtime_read(renv, address, NULL, &oprnd); + if (ret <= 0) + return ret; + + /* Mailbox operand (optional) */ + mailbox = NULL; + if (!sieve_operand_is_omitted(&oprnd)) { + /* Read the mailbox operand */ + ret = sieve_opr_string_read_data(renv, &oprnd, address, + "mailbox", &mailbox); + if (ret <= 0) + return ret; + + /* Read flag list */ + ret = sieve_opr_stringlist_read(renv, address, + "special-use-flags", + &special_use_flags); + if (ret <= 0) + return ret; + + /* Flag-list operand */ + } else { + /* Read flag list */ + ret = sieve_opr_stringlist_read(renv, address, + "special-use-flags", + &special_use_flags); + if (ret <= 0) + return ret; + } + + /* + * Perform operation + */ + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_TESTS)) { + sieve_runtime_trace(renv, 0, "specialuse_exists test"); + sieve_runtime_trace_descend(renv); + + trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); + } + + if (mailbox != NULL) { + if (!sieve_mailbox_check_name(str_c(mailbox), &error)) { + sieve_runtime_warning( + renv, NULL, "specialuse_exists test: " + "invalid mailbox name `%s' specified: %s", + str_sanitize(str_c(mailbox), 256), error); + sieve_interpreter_set_test_result(renv->interp, FALSE); + return SIEVE_EXEC_OK; + } + + if (tst_specialuse_find_mailbox(renv, str_c(mailbox), &box) < 0) + return SIEVE_EXEC_TEMP_FAILURE; + } + + if (box == NULL && mailbox != NULL) { + sieve_runtime_trace( + renv, 0, "mailbox `%s' is not accessible", + str_sanitize(str_c(mailbox), 80)); + sieve_interpreter_set_test_result(renv->interp, FALSE); + return SIEVE_EXEC_OK; + } + + if (mailbox != NULL) { + sieve_runtime_trace( + renv, 0, "mailbox `%s' is accessible", + str_sanitize(str_c(mailbox), 80)); + } + + ret = 0; + special_use_flag = NULL; + while (all_exist && + (ret = sieve_stringlist_next_item( + special_use_flags, &special_use_flag)) > 0) { + const char *use_flag = str_c(special_use_flag); + + ret = tst_specialuse_exists_check_flag( + renv, box, use_flag, trace, &all_exist); + if (ret <= 0) { + if (box != NULL) { + /* Close mailbox */ + mailbox_free(&box); + } + return ret; + } + } + + if (box != NULL) { + /* Close mailbox */ + mailbox_free(&box); + } + + if (ret < 0) { + sieve_runtime_trace_error( + renv, "invalid special-use flag item"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if (trace) { + if (all_exist) { + sieve_runtime_trace( + renv, 0, "all special-use flags are set"); + } else { + sieve_runtime_trace( + renv, 0, "some special-use are not set"); + } + } + + sieve_interpreter_set_test_result(renv->interp, all_exist); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/subaddress/Makefile.am b/pigeonhole/src/lib-sieve/plugins/subaddress/Makefile.am new file mode 100644 index 0000000..2bab53f --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/subaddress/Makefile.am @@ -0,0 +1,8 @@ +noinst_LTLIBRARIES = libsieve_ext_subaddress.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_subaddress_la_SOURCES = \ + ext-subaddress.c diff --git a/pigeonhole/src/lib-sieve/plugins/subaddress/Makefile.in b/pigeonhole/src/lib-sieve/plugins/subaddress/Makefile.in new file mode 100644 index 0000000..c5b6b7c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/subaddress/Makefile.in @@ -0,0 +1,673 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/subaddress +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_subaddress_la_LIBADD = +am_libsieve_ext_subaddress_la_OBJECTS = ext-subaddress.lo +libsieve_ext_subaddress_la_OBJECTS = \ + $(am_libsieve_ext_subaddress_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ext-subaddress.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_subaddress_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_subaddress_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_subaddress.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_subaddress_la_SOURCES = \ + ext-subaddress.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/subaddress/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/subaddress/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_subaddress.la: $(libsieve_ext_subaddress_la_OBJECTS) $(libsieve_ext_subaddress_la_DEPENDENCIES) $(EXTRA_libsieve_ext_subaddress_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_subaddress_la_OBJECTS) $(libsieve_ext_subaddress_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-subaddress.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-subaddress.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ext-subaddress.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/subaddress/ext-subaddress.c b/pigeonhole/src/lib-sieve/plugins/subaddress/ext-subaddress.c new file mode 100644 index 0000000..abaa7ae --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/subaddress/ext-subaddress.c @@ -0,0 +1,191 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension subaddress + * -------------------- + * + * Author: Stephan Bosch + * Specification: RFC 3598 + * Implementation: full + * Status: testing + * + */ + +#include "sieve-common.h" + +#include "sieve-settings.h" +#include "sieve-code.h" +#include "sieve-address.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" + +#include <string.h> + +/* + * Configuration + */ + +#define SUBADDRESS_DEFAULT_DELIM "+" + +struct ext_subaddress_config { + char *delimiter; +}; + +/* + * Forward declarations + */ + +const struct sieve_address_part_def user_address_part; +const struct sieve_address_part_def detail_address_part; + +static struct sieve_operand_def subaddress_operand; + +/* + * Extension + */ + +static bool ext_subaddress_load + (const struct sieve_extension *ext, void **context); +static void ext_subaddress_unload + (const struct sieve_extension *ext); +static bool ext_subaddress_validator_load + (const struct sieve_extension *ext, struct sieve_validator *validator); + +const struct sieve_extension_def subaddress_extension = { + .name = "subaddress", + .load = ext_subaddress_load, + .unload = ext_subaddress_unload, + .validator_load = ext_subaddress_validator_load, + SIEVE_EXT_DEFINE_OPERAND(subaddress_operand) +}; + +static bool ext_subaddress_load +(const struct sieve_extension *ext, void **context) +{ + struct ext_subaddress_config *config; + const char *delim; + + if ( *context != NULL ) { + ext_subaddress_unload(ext); + } + + delim = sieve_setting_get(ext->svinst, "recipient_delimiter"); + + if ( delim == NULL ) + delim = SUBADDRESS_DEFAULT_DELIM; + + config = i_new(struct ext_subaddress_config, 1); + config->delimiter = i_strdup(delim); + + *context = (void *) config; + + return TRUE; +} + +static void ext_subaddress_unload +(const struct sieve_extension *ext) +{ + struct ext_subaddress_config *config = + (struct ext_subaddress_config *) ext->context; + + i_free(config->delimiter); + i_free(config); +} + +static bool ext_subaddress_validator_load +(const struct sieve_extension *ext, struct sieve_validator *validator) +{ + sieve_address_part_register(validator, ext, &user_address_part); + sieve_address_part_register(validator, ext, &detail_address_part); + + return TRUE; +} + +/* + * Address parts + */ + +enum ext_subaddress_address_part { + SUBADDRESS_USER, + SUBADDRESS_DETAIL +}; + +/* Forward declarations */ + +static const char *subaddress_user_extract_from + (const struct sieve_address_part *addrp, const struct smtp_address *address); +static const char *subaddress_detail_extract_from + (const struct sieve_address_part *addrp, const struct smtp_address *address); + +/* Address part objects */ + +const struct sieve_address_part_def user_address_part = { + SIEVE_OBJECT("user", + &subaddress_operand, SUBADDRESS_USER), + subaddress_user_extract_from +}; + +const struct sieve_address_part_def detail_address_part = { + SIEVE_OBJECT("detail", + &subaddress_operand, SUBADDRESS_DETAIL), + .extract_from = subaddress_detail_extract_from +}; + +/* Address part implementation */ + +static const char *subaddress_user_extract_from +(const struct sieve_address_part *addrp, const struct smtp_address *address) +{ + struct ext_subaddress_config *config = + (struct ext_subaddress_config *) addrp->object.ext->context; + const char *delim; + size_t idx; + + idx = strcspn(address->localpart, config->delimiter); + delim = address->localpart[idx] != '\0' ? address->localpart + idx : NULL; + + if ( delim == NULL ) return address->localpart; + + return t_strdup_until(address->localpart, delim); +} + +static const char *subaddress_detail_extract_from +(const struct sieve_address_part *addrp, const struct smtp_address *address) +{ + struct ext_subaddress_config *config = + (struct ext_subaddress_config *) addrp->object.ext->context; + const char *delim; + size_t idx; + + idx = strcspn(address->localpart, config->delimiter); + delim = address->localpart[idx] != '\0' ? address->localpart + idx + 1: NULL; + + /* Just to be sure */ + if ( delim == NULL || + delim > (address->localpart + strlen(address->localpart)) ) + return NULL; + return delim; +} + +/* + * Operand + */ + +const struct sieve_address_part_def *ext_subaddress_parts[] = { + &user_address_part, &detail_address_part +}; + +static const struct sieve_extension_objects ext_address_parts = + SIEVE_EXT_DEFINE_ADDRESS_PARTS(ext_subaddress_parts); + +static struct sieve_operand_def subaddress_operand = { + .name = "address-part", + .ext_def = &subaddress_extension, + .class = &sieve_address_part_operand_class, + .interface = &ext_address_parts +}; + diff --git a/pigeonhole/src/lib-sieve/plugins/vacation/Makefile.am b/pigeonhole/src/lib-sieve/plugins/vacation/Makefile.am new file mode 100644 index 0000000..09df27b --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vacation/Makefile.am @@ -0,0 +1,19 @@ +noinst_LTLIBRARIES = libsieve_ext_vacation.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../util \ + $(LIBDOVECOT_INCLUDE) + +cmds = \ + cmd-vacation.c + +libsieve_ext_vacation_la_SOURCES = \ + $(cmds) \ + ext-vacation-common.c \ + ext-vacation.c \ + ext-vacation-seconds.c + +noinst_HEADERS = \ + ext-vacation-common.h + diff --git a/pigeonhole/src/lib-sieve/plugins/vacation/Makefile.in b/pigeonhole/src/lib-sieve/plugins/vacation/Makefile.in new file mode 100644 index 0000000..f18806a --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vacation/Makefile.in @@ -0,0 +1,700 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/vacation +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_vacation_la_LIBADD = +am__objects_1 = cmd-vacation.lo +am_libsieve_ext_vacation_la_OBJECTS = $(am__objects_1) \ + ext-vacation-common.lo ext-vacation.lo ext-vacation-seconds.lo +libsieve_ext_vacation_la_OBJECTS = \ + $(am_libsieve_ext_vacation_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/cmd-vacation.Plo \ + ./$(DEPDIR)/ext-vacation-common.Plo \ + ./$(DEPDIR)/ext-vacation-seconds.Plo \ + ./$(DEPDIR)/ext-vacation.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_vacation_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_vacation_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_vacation.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../util \ + $(LIBDOVECOT_INCLUDE) + +cmds = \ + cmd-vacation.c + +libsieve_ext_vacation_la_SOURCES = \ + $(cmds) \ + ext-vacation-common.c \ + ext-vacation.c \ + ext-vacation-seconds.c + +noinst_HEADERS = \ + ext-vacation-common.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/vacation/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/vacation/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_vacation.la: $(libsieve_ext_vacation_la_OBJECTS) $(libsieve_ext_vacation_la_DEPENDENCIES) $(EXTRA_libsieve_ext_vacation_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_vacation_la_OBJECTS) $(libsieve_ext_vacation_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-vacation.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-vacation-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-vacation-seconds.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-vacation.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-vacation.Plo + -rm -f ./$(DEPDIR)/ext-vacation-common.Plo + -rm -f ./$(DEPDIR)/ext-vacation-seconds.Plo + -rm -f ./$(DEPDIR)/ext-vacation.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/cmd-vacation.Plo + -rm -f ./$(DEPDIR)/ext-vacation-common.Plo + -rm -f ./$(DEPDIR)/ext-vacation-seconds.Plo + -rm -f ./$(DEPDIR)/ext-vacation.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/vacation/cmd-vacation.c b/pigeonhole/src/lib-sieve/plugins/vacation/cmd-vacation.c new file mode 100644 index 0000000..ddc14be --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vacation/cmd-vacation.c @@ -0,0 +1,1578 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "strfuncs.h" +#include "md5.h" +#include "hostpid.h" +#include "str-sanitize.h" +#include "ostream.h" +#include "message-address.h" +#include "message-date.h" +#include "var-expand.h" +#include "ioloop.h" +#include "mail-storage.h" + +#include "rfc2822.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-address.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-result.h" +#include "sieve-message.h" +#include "sieve-smtp.h" + +#include "ext-vacation-common.h" + +#include <stdio.h> + +/* + * Forward declarations + */ + +static const struct sieve_argument_def vacation_days_tag; +static const struct sieve_argument_def vacation_subject_tag; +static const struct sieve_argument_def vacation_from_tag; +static const struct sieve_argument_def vacation_addresses_tag; +static const struct sieve_argument_def vacation_mime_tag; +static const struct sieve_argument_def vacation_handle_tag; + +/* + * Vacation command + * + * Syntax: + * vacation [":days" number] [":subject" string] + * [":from" string] [":addresses" string-list] + * [":mime"] [":handle" string] <reason: string> + */ + +static bool +cmd_vacation_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool +cmd_vacation_pre_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd); +static bool +cmd_vacation_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd); +static bool +cmd_vacation_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd); + +const struct sieve_command_def vacation_command = { + .identifier = "vacation", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_vacation_registered, + .pre_validate = cmd_vacation_pre_validate, + .validate = cmd_vacation_validate, + .generate = cmd_vacation_generate, +}; + +/* + * Vacation command tags + */ + +/* Forward declarations */ + +static bool +cmd_vacation_validate_number_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +cmd_vacation_validate_string_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +cmd_vacation_validate_stringlist_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +cmd_vacation_validate_mime_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +/* Argument objects */ + +static const struct sieve_argument_def vacation_days_tag = { + .identifier = "days", + .validate = cmd_vacation_validate_number_tag +}; + +static const struct sieve_argument_def vacation_seconds_tag = { + .identifier = "seconds", + .validate = cmd_vacation_validate_number_tag +}; + +static const struct sieve_argument_def vacation_subject_tag = { + .identifier = "subject", + .validate = cmd_vacation_validate_string_tag +}; + +static const struct sieve_argument_def vacation_from_tag = { + .identifier = "from", + .validate = cmd_vacation_validate_string_tag +}; + +static const struct sieve_argument_def vacation_addresses_tag = { + .identifier = "addresses", + .validate = cmd_vacation_validate_stringlist_tag +}; + +static const struct sieve_argument_def vacation_mime_tag = { + .identifier = "mime", + .validate = cmd_vacation_validate_mime_tag +}; + +static const struct sieve_argument_def vacation_handle_tag = { + .identifier = "handle", + .validate = cmd_vacation_validate_string_tag +}; + +/* Codes for optional arguments */ + +enum cmd_vacation_optional { + OPT_END, + OPT_SECONDS, + OPT_SUBJECT, + OPT_FROM, + OPT_ADDRESSES, + OPT_MIME +}; + +/* + * Vacation operation + */ + +static bool +ext_vacation_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +ext_vacation_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def vacation_operation = { + .mnemonic = "VACATION", + .ext_def = &vacation_extension, + .dump = ext_vacation_operation_dump, + .execute = ext_vacation_operation_execute +}; + +/* + * Vacation action + */ + +/* Forward declarations */ + +static int +act_vacation_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other); +int act_vacation_check_conflict(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other); +static void +act_vacation_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep); +static int +act_vacation_commit(const struct sieve_action_exec_env *aenv, void *tr_context); + +/* Action object */ + +const struct sieve_action_def act_vacation = { + .name = "vacation", + .flags = SIEVE_ACTFLAG_SENDS_RESPONSE, + .check_duplicate = act_vacation_check_duplicate, + .check_conflict = act_vacation_check_conflict, + .print = act_vacation_print, + .commit = act_vacation_commit +}; + +/* Action context information */ + +struct act_vacation_context { + const char *reason; + + sieve_number_t seconds; + const char *subject; + const char *handle; + bool mime; + const char *from; + const struct smtp_address *from_address; + const struct smtp_address *const *addresses; +}; + +/* + * Command validation context + */ + +struct cmd_vacation_context_data { + string_t *from; + string_t *subject; + + bool mime; + + struct sieve_ast_argument *handle_arg; +}; + +/* + * Tag validation + */ + +static bool +cmd_vacation_validate_number_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + const struct sieve_extension *ext = sieve_argument_ext(*arg); + const struct ext_vacation_config *config = + (const struct ext_vacation_config *)ext->context; + struct sieve_ast_argument *tag = *arg; + sieve_number_t period, seconds; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :days number + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_NUMBER, FALSE)) + return FALSE; + + period = sieve_ast_argument_number(*arg); + if (sieve_argument_is(tag, vacation_days_tag)) + seconds = period * (24*60*60); + else if (sieve_argument_is(tag, vacation_seconds_tag)) + seconds = period; + else + i_unreached(); + + /* Enforce :seconds >= min_period */ + if (seconds < config->min_period) { + seconds = config->min_period; + + sieve_argument_validate_warning( + valdtr, *arg, + "specified :%s value '%llu' is under the minimum", + sieve_argument_identifier(tag), + (unsigned long long)period); + /* Enforce :days <= max_period */ + } else if (config->max_period > 0 && seconds > config->max_period) { + seconds = config->max_period; + + sieve_argument_validate_warning( + valdtr, *arg, + "specified :%s value '%llu' is over the maximum", + sieve_argument_identifier(tag), + (unsigned long long)period); + } + + sieve_ast_argument_number_set(*arg, seconds); + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +static bool +cmd_vacation_validate_string_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct cmd_vacation_context_data *ctx_data = + (struct cmd_vacation_context_data *)cmd->data; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :subject string + * :from string + * :handle string + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING, FALSE)) + return FALSE; + + if (sieve_argument_is(tag, vacation_from_tag)) { + if (sieve_argument_is_string_literal(*arg)) { + string_t *address = sieve_ast_argument_str(*arg); + const char *error; + bool result; + + T_BEGIN { + result = sieve_address_validate_str(address, + &error); + + if (!result) { + sieve_argument_validate_error( + valdtr, *arg, + "specified :from address '%s' is invalid for vacation action: %s", + str_sanitize(str_c(address), 128), + error); + } + } T_END; + + if (!result) + return FALSE; + } + + ctx_data->from = sieve_ast_argument_str(*arg); + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + } else if (sieve_argument_is(tag, vacation_subject_tag)) { + ctx_data->subject = sieve_ast_argument_str(*arg); + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + } else if (sieve_argument_is(tag, vacation_handle_tag)) { + ctx_data->handle_arg = *arg; + + /* Detach optional argument (emitted as mandatory) */ + *arg = sieve_ast_arguments_detach(*arg, 1); + } + return TRUE; +} + +static bool +cmd_vacation_validate_stringlist_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :addresses string-list + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING_LIST, FALSE)) + return FALSE; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +static bool +cmd_vacation_validate_mime_tag(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct cmd_vacation_context_data *ctx_data = + (struct cmd_vacation_context_data *)cmd->data; + + ctx_data->mime = TRUE; + + /* Skip tag */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Command registration + */ + +static bool +cmd_vacation_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &vacation_days_tag, OPT_SECONDS); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &vacation_subject_tag, OPT_SUBJECT); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &vacation_from_tag, OPT_FROM); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &vacation_addresses_tag, OPT_ADDRESSES); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &vacation_mime_tag, OPT_MIME); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &vacation_handle_tag, 0); + return TRUE; +} + +bool ext_vacation_register_seconds_tag( + struct sieve_validator *valdtr, + const struct sieve_extension *vacation_ext) +{ + sieve_validator_register_external_tag( + valdtr, vacation_command.identifier, vacation_ext, + &vacation_seconds_tag, OPT_SECONDS); + + return TRUE; +} + +/* + * Command validation + */ + +static bool +cmd_vacation_pre_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *cmd) +{ + struct cmd_vacation_context_data *ctx_data; + + /* Assign context */ + ctx_data = p_new(sieve_command_pool(cmd), + struct cmd_vacation_context_data, 1); + cmd->data = ctx_data; + + return TRUE; +} + +static const char _handle_empty_subject[] = "<default-subject>"; +static const char _handle_empty_from[] = "<default-from>"; +static const char _handle_mime_enabled[] = "<MIME>"; +static const char _handle_mime_disabled[] = "<NO-MIME>"; + +static bool +cmd_vacation_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + struct cmd_vacation_context_data *ctx_data = + (struct cmd_vacation_context_data *)cmd->data; + + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "reason", 1, + SAAT_STRING)) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE)) + return FALSE; + + /* Construct handle if not set explicitly */ + if (ctx_data->handle_arg == NULL) { + T_BEGIN { + string_t *handle; + string_t *reason = sieve_ast_argument_str(arg); + unsigned int size = str_len(reason); + + /* Precalculate the size of it all */ + size += (ctx_data->subject == NULL ? + sizeof(_handle_empty_subject) - 1 : + str_len(ctx_data->subject)); + size += (ctx_data->from == NULL ? + sizeof(_handle_empty_from) - 1 : + str_len(ctx_data->from)); + size += (ctx_data->mime ? + sizeof(_handle_mime_enabled) - 1 : + sizeof(_handle_mime_disabled) - 1); + + /* Construct the string */ + handle = t_str_new(size); + str_append_str(handle, reason); + + if (ctx_data->subject != NULL) + str_append_str(handle, ctx_data->subject); + else + str_append(handle, _handle_empty_subject); + + if (ctx_data->from != NULL) + str_append_str(handle, ctx_data->from); + else + str_append(handle, _handle_empty_from); + + str_append(handle, (ctx_data->mime ? + _handle_mime_enabled : + _handle_mime_disabled)); + + /* Create positional handle argument */ + ctx_data->handle_arg = + sieve_ast_argument_string_create( + cmd->ast_node, handle, + sieve_ast_node_line(cmd->ast_node)); + } T_END; + + if (!sieve_validator_argument_activate( + valdtr, cmd, ctx_data->handle_arg, TRUE)) + return FALSE; + } else { + /* Attach explicit handle argument as positional */ + (void)sieve_ast_argument_attach(cmd->ast_node, + ctx_data->handle_arg); + } + + return TRUE; +} + +/* + * Code generation + */ + +static bool +cmd_vacation_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &vacation_operation); + + /* Generate arguments */ + if (!sieve_generate_arguments(cgenv, cmd, NULL)) + return FALSE; + return TRUE; +} + +/* + * Code dump + */ + +static bool +ext_vacation_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "VACATION"); + sieve_code_descend(denv); + + /* Dump optional operands */ + + for (;;) { + int opt; + bool opok = TRUE; + + if ((opt = sieve_opr_optional_dump(denv, address, + &opt_code)) < 0) + return FALSE; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_SECONDS: + opok = sieve_opr_number_dump(denv, address, "seconds"); + break; + case OPT_SUBJECT: + opok = sieve_opr_string_dump(denv, address, "subject"); + break; + case OPT_FROM: + opok = sieve_opr_string_dump(denv, address, "from"); + break; + case OPT_ADDRESSES: + opok = sieve_opr_stringlist_dump(denv, address, + "addresses"); + break; + case OPT_MIME: + sieve_code_dumpf(denv, "mime"); + break; + default: + return FALSE; + } + + if (!opok) + return FALSE; + } + + /* Dump reason and handle operands */ + return (sieve_opr_string_dump(denv, address, "reason") && + sieve_opr_string_dump(denv, address, "handle")); +} + +/* + * Code execution + */ + +static int +ext_vacation_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + const struct ext_vacation_config *config = + (const struct ext_vacation_config *)this_ext->context; + struct sieve_side_effects_list *slist = NULL; + struct act_vacation_context *act; + pool_t pool; + int opt_code = 0; + sieve_number_t seconds = config->default_period; + bool mime = FALSE; + struct sieve_stringlist *addresses = NULL; + string_t *reason, *subject = NULL, *from = NULL, *handle = NULL; + const struct smtp_address *from_address = NULL; + int ret; + + /* + * Read code + */ + + /* Optional operands */ + + for (;;) { + int opt; + + if ((opt = sieve_opr_optional_read(renv, address, + &opt_code)) < 0) + return SIEVE_EXEC_BIN_CORRUPT; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_SECONDS: + ret = sieve_opr_number_read(renv, address, "seconds", + &seconds); + break; + case OPT_SUBJECT: + ret = sieve_opr_string_read(renv, address, "subject", + &subject); + break; + case OPT_FROM: + ret = sieve_opr_string_read(renv, address, "from", + &from); + break; + case OPT_ADDRESSES: + ret = sieve_opr_stringlist_read(renv, address, + "addresses", + &addresses); + break; + case OPT_MIME: + mime = TRUE; + ret = SIEVE_EXEC_OK; + break; + default: + sieve_runtime_trace_error( + renv, "unknown optional operand"); + ret = SIEVE_EXEC_BIN_CORRUPT; + } + + if (ret <= 0) + return ret; + } + + /* Fixed operands */ + + if ((ret =sieve_opr_string_read(renv, address, + "reason", &reason)) <= 0 || + (ret = sieve_opr_string_read(renv, address, + "handle", &handle)) <= 0) + return ret; + + /* + * Perform operation + */ + + /* Trace */ + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_ACTIONS)) { + sieve_runtime_trace(renv, 0, "vacation action"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace(renv, 0, "auto-reply with message `%s'", + str_sanitize(str_c(reason), 80)); + } + + /* Parse :from address */ + if (from != NULL) { + const char *error; + + from_address = sieve_address_parse_str(from, &error); + if (from_address == NULL) { + sieve_runtime_error( + renv, NULL, + "specified :from address '%s' is invalid for vacation action: %s", + str_sanitize(str_c(from), 128), error); + } + } + + /* Add vacation action to the result */ + + pool = sieve_result_pool(renv->result); + act = p_new(pool, struct act_vacation_context, 1); + act->reason = p_strdup(pool, str_c(reason)); + act->handle = p_strdup(pool, str_c(handle)); + act->seconds = seconds; + act->mime = mime; + if (subject != NULL) + act->subject = p_strdup(pool, str_c(subject)); + if (from != NULL) { + act->from = p_strdup(pool, str_c(from)); + act->from_address = smtp_address_clone(pool, from_address); + } + + /* Normalize all addresses */ + if (addresses != NULL) { + ARRAY_TYPE(smtp_address_const) addrs; + string_t *raw_address; + int ret; + + sieve_stringlist_reset(addresses); + + p_array_init(&addrs, pool, 4); + + raw_address = NULL; + while ((ret = sieve_stringlist_next_item(addresses, + &raw_address)) > 0) { + const struct smtp_address *addr; + const char *error; + + addr = sieve_address_parse_str(raw_address, &error); + if (addr != NULL) { + addr = smtp_address_clone(pool, addr); + array_append(&addrs, &addr, 1); + } else { + sieve_runtime_error( + renv, NULL, + "specified :addresses item '%s' is invalid: " + "%s for vacation action (ignored)", + str_sanitize(str_c(raw_address),128), + error); + } + } + + if (ret < 0) { + sieve_runtime_trace_error( + renv, "invalid addresses stringlist"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + (void)array_append_space(&addrs); + act->addresses = array_idx(&addrs, 0); + } + + if (sieve_result_add_action(renv, this_ext, "vacation", &act_vacation, + slist, (void *)act, 0, FALSE) < 0) + return SIEVE_EXEC_FAILURE; + + return SIEVE_EXEC_OK; +} + +/* + * Action + */ + +/* Runtime verification */ + +static int +act_vacation_check_duplicate(const struct sieve_runtime_env *renv ATTR_UNUSED, + const struct sieve_action *act, + const struct sieve_action *act_other) +{ + if (!sieve_action_is_executed(act_other, renv->result)) { + sieve_runtime_error( + renv, act->location, + "duplicate vacation action not allowed " + "(previously triggered one was here: %s)", + act_other->location); + return -1; + } + + /* Not an error if executed in preceeding script */ + return 1; +} + +int act_vacation_check_conflict(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other) +{ + if ((act_other->def->flags & SIEVE_ACTFLAG_SENDS_RESPONSE) > 0) { + if (!sieve_action_is_executed(act_other, renv->result)) { + sieve_runtime_error( + renv, act->location, + "vacation action conflicts with other action: " + "the %s action (%s) also sends a response back to the sender", + act_other->def->name, act_other->location); + return -1; + } else { + /* Not an error if executed in preceeding script */ + return 1; + } + } + + return 0; +} + +/* Result printing */ + +static void act_vacation_print(const struct sieve_action *action ATTR_UNUSED, + const struct sieve_result_print_env *rpenv, + bool *keep ATTR_UNUSED) +{ + struct act_vacation_context *ctx = + (struct act_vacation_context *)action->context; + + sieve_result_action_printf(rpenv, "send vacation message:"); + sieve_result_printf(rpenv, " => seconds : %llu\n", + (unsigned long long)ctx->seconds); + if (ctx->subject != NULL) { + sieve_result_printf(rpenv, " => subject : %s\n", + ctx->subject); + } + if (ctx->from != NULL) { + sieve_result_printf(rpenv, " => from : %s\n", + ctx->from); + } + if (ctx->handle != NULL) { + sieve_result_printf(rpenv, " => handle : %s\n", + ctx->handle); + } + sieve_result_printf(rpenv, "\nSTART MESSAGE\n%s\nEND MESSAGE\n", + ctx->reason); +} + +/* Result execution */ + +/* Headers known to be associated with mailing lists + */ +static const char * const _list_headers[] = { + "list-id", + "list-owner", + "list-subscribe", + "list-post", + "list-unsubscribe", + "list-help", + "list-archive", + NULL +}; + +/* Headers that should be searched for the user's own mail address(es) + */ + +static const char * const _my_address_headers[] = { + "to", + "cc", + "bcc", + "resent-to", + "resent-cc", + "resent-bcc", + NULL +}; + +/* Headers that should be searched for the full sender address + */ + +static const char * const _sender_headers[] = { + "sender", + "resent-from", + "from", + NULL +}; + +static inline bool _is_system_address(const struct smtp_address *address) +{ + if (strcasecmp(address->localpart, "MAILER-DAEMON") == 0) + return TRUE; + if (strcasecmp(address->localpart, "LISTSERV") == 0) + return TRUE; + if (strcasecmp(address->localpart, "majordomo") == 0) + return TRUE; + if (strstr(address->localpart, "-request") != NULL) + return TRUE; + if (str_begins(address->localpart, "owner-")) + return TRUE; + return FALSE; +} + +static bool +_msg_address_equals(const struct message_address *addr1, + const struct smtp_address *addr2) +{ + struct smtp_address saddr; + + i_assert(addr1->mailbox != NULL); + return (smtp_address_init_from_msg(&saddr, addr1) >= 0 && + smtp_address_equals_icase(addr2, &saddr)); +} + +static inline bool +_header_contains_my_address(const char *header_val, + const struct smtp_address *my_address) +{ + const struct message_address *msg_addr; + + msg_addr = message_address_parse(pool_datastack_create(), + (const unsigned char *)header_val, + strlen(header_val), 256, 0); + while (msg_addr != NULL) { + if (msg_addr->domain != NULL) { + if (_msg_address_equals(msg_addr, my_address)) + return TRUE; + } + + msg_addr = msg_addr->next; + } + + return FALSE; +} + +static inline bool +_contains_my_address(const char * const *headers, + const struct smtp_address *my_address) +{ + const char *const *hdsp = headers; + + while (*hdsp != NULL) { + bool result; + + T_BEGIN { + result = _header_contains_my_address(*hdsp, my_address); + } T_END; + + if (result) + return TRUE; + + hdsp++; + } + + return FALSE; +} + +static bool _contains_8bit(const char *text) +{ + const unsigned char *p = (const unsigned char *)text; + + for (; *p != '\0'; p++) { + if ((*p & 0x80) != 0) + return TRUE; + } + return FALSE; +} + +static bool +_header_get_full_reply_recipient(const struct ext_vacation_config *config, + const struct smtp_address *smtp_to, + const char *header, + struct message_address *reply_to_r) +{ + const struct message_address *addr; + + addr = message_address_parse( + pool_datastack_create(), + (const unsigned char *)header, + strlen(header), 256, 0); + + for (; addr != NULL; addr = addr->next) { + bool matched = config->to_header_ignore_envelope; + + if (addr->domain == NULL || addr->invalid_syntax) + continue; + + if (!matched) + matched = _msg_address_equals(addr, smtp_to); + + if (matched) { + *reply_to_r = *addr; + return TRUE; + } + } + return FALSE; +} + +static int +_get_full_reply_recipient(const struct sieve_action_exec_env *aenv, + const struct ext_vacation_config *config, + const struct smtp_address *smtp_to, + struct message_address *reply_to_r) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + const struct sieve_message_data *msgdata = eenv->msgdata; + const char *const *hdsp; + int ret; + + hdsp = _sender_headers; + for (; *hdsp != NULL; hdsp++) { + const char *header; + + if ((ret = mail_get_first_header(msgdata->mail, *hdsp, + &header)) < 0) { + return sieve_result_mail_error( + aenv, msgdata->mail, + "failed to read header field `%s'", *hdsp); + } + if (ret == 0 || header == NULL) + continue; + + if (_header_get_full_reply_recipient(config, smtp_to, + header, reply_to_r)) + return SIEVE_EXEC_OK; + } + + reply_to_r->mailbox = smtp_to->localpart; + reply_to_r->domain = smtp_to->domain; + return SIEVE_EXEC_OK; +} + +static const struct var_expand_table * +_get_var_expand_table(const struct sieve_action_exec_env *aenv ATTR_UNUSED, + const char *subject) +{ + const struct var_expand_table stack_tab[] = { + { '$', subject, "subject" }, + { '\0', NULL, NULL } + }; + + return p_memdup(unsafe_data_stack_pool, stack_tab, sizeof(stack_tab)); +} + +static int +act_vacation_get_default_subject(const struct sieve_action_exec_env *aenv, + const struct ext_vacation_config *config, + const char **subject_r) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + const struct sieve_message_data *msgdata = eenv->msgdata; + const char *header, *error; + string_t *str; + const struct var_expand_table *tab; + int ret; + + *subject_r = (config->default_subject == NULL ? + "Automated reply" : config->default_subject); + if ((ret = mail_get_first_header_utf8(msgdata->mail, "subject", + &header)) < 0) { + return sieve_result_mail_error( + aenv, msgdata->mail, + "failed to read header field `subject'"); + } + if (ret == 0) + return SIEVE_EXEC_OK; + if (config->default_subject_template == NULL) { + *subject_r = t_strconcat("Auto: ", header, NULL); + return SIEVE_EXEC_OK; + } + + str = t_str_new(256); + tab = _get_var_expand_table(aenv, header); + if (var_expand(str, config->default_subject_template, + tab, &error) <= 0) { + i_error("Failed to expand deliver_log_format=%s: %s", + config->default_subject_template, error); + *subject_r = t_strconcat("Auto: ", header, NULL); + return SIEVE_EXEC_OK; + } + + *subject_r = str_c(str); + return SIEVE_EXEC_OK; +} + +static int +act_vacation_send(const struct sieve_action_exec_env *aenv, + const struct ext_vacation_config *config, + struct act_vacation_context *ctx, + const struct smtp_address *smtp_to, + const struct smtp_address *smtp_from, + const struct message_address *reply_from) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + const struct sieve_message_data *msgdata = eenv->msgdata; + const struct sieve_script_env *senv = eenv->scriptenv; + struct sieve_smtp_context *sctx; + struct ostream *output; + string_t *msg; + struct message_address reply_to; + const char *header, *outmsgid, *subject, *error; + int ret; + + /* Check smpt functions just to be sure */ + + if (!sieve_smtp_available(senv)) { + sieve_result_global_warning( + aenv, "vacation action has no means to send mail"); + return SIEVE_EXEC_OK; + } + + /* Make sure we have a subject for our reply */ + + if (ctx->subject == NULL || *(ctx->subject) == '\0') { + if ((ret = act_vacation_get_default_subject(aenv, config, + &subject)) <= 0) + return ret; + } else { + subject = ctx->subject; + } + + subject = str_sanitize_utf8(subject, config->max_subject_codepoints); + + /* Obtain full To address for reply */ + + i_zero(&reply_to); + reply_to.mailbox = smtp_to->localpart; + reply_to.domain = smtp_to->domain; + if ((ret = _get_full_reply_recipient(aenv, config, smtp_to, + &reply_to)) <= 0) + return ret; + + /* Open smtp session */ + + sctx = sieve_smtp_start_single(senv, smtp_to, smtp_from, &output); + + outmsgid = sieve_message_get_new_id(eenv->svinst); + + /* Produce a proper reply */ + + msg = t_str_new(512); + rfc2822_header_write(msg, "X-Sieve", SIEVE_IMPLEMENTATION); + rfc2822_header_write(msg, "Message-ID", outmsgid); + rfc2822_header_write(msg, "Date", message_date_create(ioloop_time)); + + if (ctx->from != NULL && *(ctx->from) != '\0') { + rfc2822_header_write_address(msg, "From", ctx->from); + } else { + if (reply_from == NULL || reply_from->mailbox == NULL || + *reply_from->mailbox == '\0') + reply_from = sieve_get_postmaster(senv); + rfc2822_header_write( + msg, "From", + message_address_first_to_string(reply_from)); + } + + rfc2822_header_write(msg, "To", + message_address_first_to_string(&reply_to)); + + if (_contains_8bit(subject)) + rfc2822_header_utf8_printf(msg, "Subject", "%s", subject); + else + rfc2822_header_printf(msg, "Subject", "%s", subject); + + /* Compose proper in-reply-to and references headers */ + + if ((ret = mail_get_first_header(msgdata->mail, "references", + &header)) < 0) { + sieve_smtp_abort(sctx); + return sieve_result_mail_error( + aenv, msgdata->mail, + "failed to read header field `references'"); + } + + if (msgdata->id != NULL) { + rfc2822_header_write(msg, "In-Reply-To", msgdata->id); + + if (ret > 0 && header != NULL) { + rfc2822_header_write( + msg, "References", + t_strconcat(header, " ", msgdata->id, NULL)); + } else { + rfc2822_header_write(msg, "References", msgdata->id); + } + } else if (ret > 0 && header != NULL) { + rfc2822_header_write(msg, "References", header); + } + + rfc2822_header_write(msg, "Auto-Submitted", "auto-replied (vacation)"); + rfc2822_header_write(msg, "Precedence", "bulk"); + + /* Prevent older Microsoft products from replying to this message */ + rfc2822_header_write(msg, "X-Auto-Response-Suppress", "All"); + + rfc2822_header_write(msg, "MIME-Version", "1.0"); + + if (!ctx->mime) { + rfc2822_header_write(msg, "Content-Type", + "text/plain; charset=utf-8"); + rfc2822_header_write(msg, "Content-Transfer-Encoding", "8bit"); + str_append(msg, "\r\n"); + } + + str_printfa(msg, "%s\r\n", ctx->reason); + o_stream_nsend(output, str_data(msg), str_len(msg)); + + /* Close smtp session */ + if ((ret = sieve_smtp_finish(sctx, &error)) <= 0) { + if (ret < 0) { + sieve_result_global_error( + aenv, "failed to send vacation response to %s: " + "<%s> (temporary error)", + smtp_address_encode(smtp_to), + str_sanitize(error, 512)); + } else { + sieve_result_global_log_error( + aenv, "failed to send vacation response to %s: " + "<%s> (permanent error)", + smtp_address_encode(smtp_to), + str_sanitize(error, 512)); + } + /* This error will be ignored in the end */ + return SIEVE_EXEC_FAILURE; + } + + eenv->exec_status->significant_action_executed = TRUE; + return SIEVE_EXEC_OK; +} + +static void +act_vacation_hash(struct act_vacation_context *vctx, const char *sender, + unsigned char hash_r[]) +{ + const char *rpath = t_str_lcase(sender); + struct md5_context ctx; + + md5_init(&ctx); + md5_update(&ctx, rpath, strlen(rpath)); + + md5_update(&ctx, vctx->handle, strlen(vctx->handle)); + + md5_final(&ctx, hash_r); +} + +static int +act_vacation_commit(const struct sieve_action_exec_env *aenv, + void *tr_context ATTR_UNUSED) +{ + const struct sieve_action *action = aenv->action; + const struct sieve_extension *ext = action->ext; + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_instance *svinst = eenv->svinst; + const struct ext_vacation_config *config = + (const struct ext_vacation_config *)ext->context; + struct act_vacation_context *ctx = + (struct act_vacation_context *)action->context; + unsigned char dupl_hash[MD5_RESULTLEN]; + struct mail *mail = sieve_message_get_mail(aenv->msgctx); + const struct smtp_address *sender, *recipient; + const struct smtp_address *orig_recipient, *user_email; + const struct smtp_address *smtp_from; + struct message_address reply_from; + const char *const *hdsp, *const *headers; + int ret; + + if ((eenv->flags & SIEVE_EXECUTE_FLAG_SKIP_RESPONSES) != 0) { + sieve_result_global_log( + aenv, "not sending vacation reply (skipped)"); + return SIEVE_EXEC_OK; + } + + sender = sieve_message_get_sender(aenv->msgctx); + recipient = sieve_message_get_final_recipient(aenv->msgctx); + + i_zero(&reply_from); + smtp_from = orig_recipient = user_email = NULL; + + /* Is the recipient unset? + */ + if (smtp_address_isnull(recipient)) { + sieve_result_global_warning( + aenv, "vacation action aborted: " + "envelope recipient is <>"); + return SIEVE_EXEC_OK; + } + + /* Is the return path unset ? + */ + if (smtp_address_isnull(sender)) { + sieve_result_global_log(aenv, "discarded vacation reply to <>"); + return SIEVE_EXEC_OK; + } + + /* Are we perhaps trying to respond to ourselves ? + */ + if (smtp_address_equals_icase(sender, recipient)) { + sieve_result_global_log( + aenv, "discarded vacation reply to own address <%s>", + smtp_address_encode(sender)); + return SIEVE_EXEC_OK; + } + + /* Are we perhaps trying to respond to one of our alternative :addresses? + */ + if (ctx->addresses != NULL) { + const struct smtp_address * const *alt_address; + + alt_address = ctx->addresses; + while (*alt_address != NULL) { + if (smtp_address_equals_icase(sender, *alt_address)) { + sieve_result_global_log( + aenv, + "discarded vacation reply to own address <%s> " + "(as specified using :addresses argument)", + smtp_address_encode(sender)); + return SIEVE_EXEC_OK; + } + alt_address++; + } + } + + /* Did whe respond to this user before? */ + if (sieve_action_duplicate_check_available(aenv)) { + bool duplicate; + + act_vacation_hash(ctx, smtp_address_encode(sender), dupl_hash); + + ret = sieve_action_duplicate_check(aenv, dupl_hash, + sizeof(dupl_hash), + &duplicate); + if (ret < SIEVE_EXEC_OK) { + sieve_result_critical( + aenv, "failed to check for duplicate vacation response", + "failed to check for duplicate vacation response%s", + (ret == SIEVE_EXEC_TEMP_FAILURE ? + " (temporaty failure)" : "")); + return ret; + } + if (duplicate) { + sieve_result_global_log( + aenv, + "discarded duplicate vacation response to <%s>", + smtp_address_encode(sender)); + return SIEVE_EXEC_OK; + } + } + + /* Are we trying to respond to a mailing list ? */ + hdsp = _list_headers; + while (*hdsp != NULL) { + if ((ret = mail_get_headers(mail, *hdsp, &headers)) < 0) { + return sieve_result_mail_error( + aenv, mail, + "failed to read header field `%s'", *hdsp); + } + + if (ret > 0 && headers[0] != NULL) { + /* Yes, bail out */ + sieve_result_global_log( + aenv, "discarding vacation response " + "to mailinglist recipient <%s>", + smtp_address_encode(sender)); + return SIEVE_EXEC_OK; + } + hdsp++; + } + + /* Is the message that we are replying to an automatic reply ? */ + if ((ret = mail_get_headers(mail, "auto-submitted", &headers)) < 0) { + return sieve_result_mail_error( + aenv, mail, + "failed to read header field `auto-submitted'"); + } + /* Theoretically multiple headers could exist, so lets make sure */ + if (ret > 0) { + hdsp = headers; + while (*hdsp != NULL) { + if (strcasecmp(*hdsp, "no") != 0) { + sieve_result_global_log( + aenv, "discarding vacation response " + "to auto-submitted message from <%s>", + smtp_address_encode(sender)); + return SIEVE_EXEC_OK; + } + hdsp++; + } + } + + /* Check for the (non-standard) precedence header */ + if ((ret = mail_get_headers(mail, "precedence", &headers)) < 0) { + return sieve_result_mail_error( + aenv, mail, "failed to read header field `precedence'"); + } + /* Theoretically multiple headers could exist, so lets make sure */ + if (ret > 0) { + hdsp = headers; + while (*hdsp != NULL) { + if (strcasecmp(*hdsp, "junk") == 0 || + strcasecmp(*hdsp, "bulk") == 0 || + strcasecmp(*hdsp, "list") == 0) { + sieve_result_global_log( + aenv, "discarding vacation response " + "to precedence=%s message from <%s>", + *hdsp, smtp_address_encode(sender)); + return SIEVE_EXEC_OK; + } + hdsp++; + } + } + + /* Check for the (non-standard) Microsoft X-Auto-Response-Suppress header */ + if ((ret = mail_get_headers(mail, "x-auto-response-suppress", + &headers)) < 0) { + return sieve_result_mail_error( + aenv, mail, + "failed to read header field `x-auto-response-suppress'"); + } + /* Theoretically multiple headers could exist, so lets make sure */ + if (ret > 0) { + hdsp = headers; + while (*hdsp != NULL) { + const char *const *flags = t_strsplit(*hdsp, ","); + + while (*flags != NULL) { + const char *flag = t_str_trim(*flags, " \t"); + + if (strcasecmp(flag, "All") == 0 || + strcasecmp(flag, "OOF") == 0) { + sieve_result_global_log( + aenv, "discarding vacation response to message from <%s> " + "(`%s' flag found in x-auto-response-suppress header)", + smtp_address_encode(sender), flag); + return SIEVE_EXEC_OK; + } + flags++; + } + hdsp++; + } + } + + /* Do not reply to system addresses */ + if (_is_system_address(sender)) { + sieve_result_global_log( + aenv, "not sending vacation response to system address <%s>", + smtp_address_encode(sender)); + return SIEVE_EXEC_OK; + } + + /* Fetch original recipient if necessary */ + if (config->use_original_recipient) + orig_recipient = sieve_message_get_orig_recipient(aenv->msgctx); + /* Fetch explicitly configured user email address */ + if (svinst->user_email != NULL) + user_email = svinst->user_email; + + /* Is the original message directly addressed to the user or the addresses + * specified using the :addresses tag? + */ + hdsp = _my_address_headers; + while (*hdsp != NULL) { + if ((ret = mail_get_headers(mail, *hdsp, &headers)) < 0) { + return sieve_result_mail_error( + aenv, mail, "failed to read header field `%s'", + *hdsp); + } + if (ret > 0 && headers[0] != NULL) { + /* Final recipient directly listed in headers? */ + if (_contains_my_address(headers, recipient)) { + smtp_from = recipient; + message_address_init_from_smtp( + &reply_from, NULL, recipient); + break; + } + + /* Original recipient directly listed in headers? */ + if (!smtp_address_isnull(orig_recipient) && + _contains_my_address(headers, orig_recipient)) { + smtp_from = orig_recipient; + message_address_init_from_smtp( + &reply_from, NULL, orig_recipient); + break; + } + + /* User-provided :addresses listed in headers? */ + if (ctx->addresses != NULL) { + bool found = FALSE; + const struct smtp_address * const *my_address; + + my_address = ctx->addresses; + while (!found && *my_address != NULL) { + if ((found = _contains_my_address(headers, *my_address))) { + /* Avoid letting user determine SMTP sender directly */ + smtp_from = (orig_recipient == NULL ? + recipient : orig_recipient); + message_address_init_from_smtp( + &reply_from, NULL, *my_address); + } + my_address++; + } + + if (found) break; + } + + /* Explicitly-configured user email address directly listed in + headers? */ + if (user_email != NULL && + _contains_my_address(headers, user_email)) { + smtp_from = user_email; + message_address_init_from_smtp( + &reply_from, NULL, smtp_from); + break; + } + } + hdsp++; + } + + /* My address not found in the headers; we got an implicit delivery */ + if (*hdsp == NULL) { + if (config->dont_check_recipient) { + /* Send reply from envelope recipient address */ + smtp_from = (orig_recipient == NULL ? + recipient : orig_recipient); + if (user_email == NULL) + user_email = sieve_get_user_email(svinst); + message_address_init_from_smtp(&reply_from, + NULL, user_email); + } else { + const char *orig_rcpt_str = "", *user_email_str = ""; + + /* Bail out */ + if (config->use_original_recipient) { + orig_rcpt_str = + t_strdup_printf("original-recipient=<%s>, ", + (orig_recipient == NULL ? "UNAVAILABLE" : + smtp_address_encode(orig_recipient))); + } + + if (user_email != NULL) { + user_email_str = t_strdup_printf( + "user-email=<%s>, ", + smtp_address_encode(user_email)); + } + + sieve_result_global_log( + aenv, "discarding vacation response for implicitly delivered message; " + "no known (envelope) recipient address found in message headers " + "(recipient=<%s>, %s%sand%s additional `:addresses' are specified)", + smtp_address_encode(recipient), + orig_rcpt_str, user_email_str, + (ctx->addresses == NULL || *ctx->addresses == NULL ? + " no" : "")); + return SIEVE_EXEC_OK; + } + } + + /* Send the message */ + + T_BEGIN { + ret = act_vacation_send( + aenv, config, ctx, sender, + (config->send_from_recipient ? smtp_from : NULL), + &reply_from); + } T_END; + + if (ret == SIEVE_EXEC_OK) { + sieve_number_t seconds; + + eenv->exec_status->significant_action_executed = TRUE; + + struct event_passthrough *e = + sieve_action_create_finish_event(aenv); + + sieve_result_event_log(aenv, e->event(), + "sent vacation response to <%s>", + smtp_address_encode(sender)); + + /* Check period limits once more */ + seconds = ctx->seconds; + if (seconds < config->min_period) + seconds = config->min_period; + else if (config->max_period > 0 && seconds > config->max_period) + seconds = config->max_period; + + /* Mark as replied */ + if (seconds > 0) { + sieve_action_duplicate_mark(aenv, dupl_hash, + sizeof(dupl_hash), + ioloop_time + seconds); + } + } + + if (ret == SIEVE_EXEC_TEMP_FAILURE) + return SIEVE_EXEC_TEMP_FAILURE; + + /* Ignore all other errors */ + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation-common.c b/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation-common.c new file mode 100644 index 0000000..97be3a5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation-common.c @@ -0,0 +1,114 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-settings.h" +#include "sieve-extensions.h" + +#include "ext-vacation-common.h" + +bool ext_vacation_load +(const struct sieve_extension *ext, void **context) +{ + struct sieve_instance *svinst = ext->svinst; + struct ext_vacation_config *config; + sieve_number_t min_period, max_period, default_period; + bool use_original_recipient, dont_check_recipient, send_from_recipient, + to_header_ignore_envelope; + unsigned long long max_subject_codepoints; + const char *default_subject, *default_subject_template; + + if ( *context != NULL ) { + ext_vacation_unload(ext); + } + + if ( !sieve_setting_get_duration_value + (svinst, "sieve_vacation_min_period", &min_period) ) { + min_period = EXT_VACATION_DEFAULT_MIN_PERIOD; + } + + if ( !sieve_setting_get_duration_value + (svinst, "sieve_vacation_max_period", &max_period) ) { + max_period = EXT_VACATION_DEFAULT_MAX_PERIOD; + } + + if ( !sieve_setting_get_duration_value + (svinst, "sieve_vacation_default_period", &default_period) ) { + default_period = EXT_VACATION_DEFAULT_PERIOD; + } + + if ( max_period > 0 + && (min_period > max_period || default_period < min_period + || default_period > max_period) ) { + min_period = EXT_VACATION_DEFAULT_MIN_PERIOD; + max_period = EXT_VACATION_DEFAULT_MAX_PERIOD; + default_period = EXT_VACATION_DEFAULT_PERIOD; + + e_warning(svinst->event, "vacation extension: " + "invalid settings: violated " + "sieve_vacation_min_period < " + "sieve_vacation_default_period < " + "sieve_vacation_max_period"); + } + + default_subject = sieve_setting_get( + svinst, "sieve_vacation_default_subject"); + default_subject_template = sieve_setting_get( + svinst, "sieve_vacation_default_subject_template"); + + if ( !sieve_setting_get_uint_value + (svinst, "sieve_vacation_max_subject_codepoints", &max_subject_codepoints) ) { + max_subject_codepoints = EXT_VACATION_DEFAULT_MAX_SUBJECT_CODEPOINTS; + } + + if ( !sieve_setting_get_bool_value + (svinst, "sieve_vacation_use_original_recipient", &use_original_recipient) ) { + use_original_recipient = FALSE; + } + + if ( !sieve_setting_get_bool_value + (svinst, "sieve_vacation_dont_check_recipient", &dont_check_recipient) ) { + dont_check_recipient = FALSE; + } + + if ( !sieve_setting_get_bool_value + (svinst, "sieve_vacation_send_from_recipient", &send_from_recipient) ) { + send_from_recipient = FALSE; + } + + if ( !sieve_setting_get_bool_value(svinst, + "sieve_vacation_to_header_ignore_envelope", + &to_header_ignore_envelope) ) { + to_header_ignore_envelope = FALSE; + } + + config = i_new(struct ext_vacation_config, 1); + config->min_period = min_period; + config->max_period = max_period; + config->default_period = default_period; + config->max_subject_codepoints = max_subject_codepoints; + config->default_subject = i_strdup_empty(default_subject); + config->default_subject_template = i_strdup_empty(default_subject_template); + config->use_original_recipient = use_original_recipient; + config->dont_check_recipient = dont_check_recipient; + config->send_from_recipient = send_from_recipient; + config->to_header_ignore_envelope = to_header_ignore_envelope; + + *context = (void *) config; + + return TRUE; +} + +void ext_vacation_unload +(const struct sieve_extension *ext) +{ + struct ext_vacation_config *config = + (struct ext_vacation_config *) ext->context; + + i_free(config->default_subject); + i_free(config->default_subject_template); + i_free(config); +} diff --git a/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation-common.h b/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation-common.h new file mode 100644 index 0000000..3a38cf6 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation-common.h @@ -0,0 +1,60 @@ +#ifndef EXT_VACATION_COMMON_H +#define EXT_VACATION_COMMON_H + +#include "sieve-common.h" + +/* + * Extension configuration + */ + +#define EXT_VACATION_DEFAULT_PERIOD (7*24*60*60) +#define EXT_VACATION_DEFAULT_MIN_PERIOD (24*60*60) +#define EXT_VACATION_DEFAULT_MAX_PERIOD 0 +#define EXT_VACATION_DEFAULT_MAX_SUBJECT_CODEPOINTS 256 + +struct ext_vacation_config { + unsigned int min_period; + unsigned int max_period; + unsigned int default_period; + unsigned long long max_subject_codepoints; + char *default_subject; + char *default_subject_template; + bool use_original_recipient; + bool dont_check_recipient; + bool send_from_recipient; + bool to_header_ignore_envelope; +}; + +/* + * Commands + */ + +extern const struct sieve_command_def vacation_command; + +/* + * Operations + */ + +extern const struct sieve_operation_def vacation_operation; + +/* + * Extensions + */ + +/* Vacation */ + +extern const struct sieve_extension_def vacation_extension; + +bool ext_vacation_load + (const struct sieve_extension *ext, void **context); +void ext_vacation_unload + (const struct sieve_extension *ext); + +/* Vacation-seconds */ + +extern const struct sieve_extension_def vacation_seconds_extension; + +bool ext_vacation_register_seconds_tag + (struct sieve_validator *valdtr, const struct sieve_extension *vacation_ext); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation-seconds.c b/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation-seconds.c new file mode 100644 index 0000000..41c0f06 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation-seconds.c @@ -0,0 +1,66 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension vacation-seconds + * -------------------------- + * + * Authors: Stephan Bosch <stephan@rename-it.nl> + * Specification: RFC 6131 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" + +#include "sieve-common.h" + +#include "sieve-extensions.h" +#include "sieve-validator.h" + +#include "ext-vacation-common.h" + +/* + * Extension + */ + +bool ext_vacation_seconds_load + (const struct sieve_extension *ext, void **context); +static bool ext_vacation_seconds_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def vacation_seconds_extension = { + .name = "vacation-seconds", + .load = ext_vacation_seconds_load, + .validator_load = ext_vacation_seconds_validator_load, +}; + +bool ext_vacation_seconds_load +(const struct sieve_extension *ext, void **context) +{ + if ( *context == NULL ) { + /* Make sure vacation extension is registered */ + *context = (void *) + sieve_extension_require(ext->svinst, &vacation_extension, TRUE); + } + + return TRUE; +} + +static bool ext_vacation_seconds_validator_load +(const struct sieve_extension *ext ATTR_UNUSED, struct sieve_validator *valdtr) +{ + const struct sieve_extension *vacation_ext; + + /* Load vacation extension implicitly */ + + vacation_ext = sieve_validator_extension_load_implicit + (valdtr, vacation_extension.name); + + if ( vacation_ext == NULL ) + return FALSE; + + /* Add seconds tag to vacation command */ + + return ext_vacation_register_seconds_tag(valdtr, vacation_ext); +} diff --git a/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation.c b/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation.c new file mode 100644 index 0000000..8d3d9a7 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation.c @@ -0,0 +1,131 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension vacation + * ------------------ + * + * Authors: Stephan Bosch <stephan@rename-it.nl> + * Specification: RFC 5230 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" + +#include "sieve-common.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-vacation-common.h" + +/* + * Extension + */ + +static bool +ext_vacation_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr); +static bool +ext_vacation_interpreter_load(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + sieve_size_t *address); + +static bool +ext_vacation_validator_validate(const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + bool required); +static int +ext_vacation_interpreter_run(const struct sieve_extension *this_ext, + const struct sieve_runtime_env *renv, + void *context, bool deferred); + +const struct sieve_extension_def vacation_extension = { + .name = "vacation", + .load = ext_vacation_load, + .unload = ext_vacation_unload, + .validator_load = ext_vacation_validator_load, + .interpreter_load = ext_vacation_interpreter_load, + SIEVE_EXT_DEFINE_OPERATION(vacation_operation) +}; +const struct sieve_validator_extension +vacation_validator_extension = { + .ext = &vacation_extension, + .validate = ext_vacation_validator_validate +}; +const struct sieve_interpreter_extension +vacation_interpreter_extension = { + .ext_def = &vacation_extension, + .run = ext_vacation_interpreter_run +}; + +static bool +ext_vacation_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr) +{ + /* Register new command */ + sieve_validator_register_command(valdtr, ext, &vacation_command); + + sieve_validator_extension_register(valdtr, ext, + &vacation_validator_extension, NULL); + return TRUE; +} + +static bool +ext_vacation_interpreter_load(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + sieve_interpreter_extension_register( + renv->interp, ext, &vacation_interpreter_extension, NULL); + return TRUE; +} + +static bool +ext_vacation_validator_validate(const struct sieve_extension *ext, + struct sieve_validator *valdtr, + void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg, + bool required) +{ + if (required) { + enum sieve_compile_flags flags = + sieve_validator_compile_flags(valdtr); + + if ((flags & SIEVE_COMPILE_FLAG_NO_ENVELOPE) != 0) { + sieve_argument_validate_error( + valdtr, require_arg, + "the %s extension cannot be used in this context " + "(needs access to message envelope)", + sieve_extension_name(ext)); + return FALSE; + } + } + return TRUE; +} + +static int +ext_vacation_interpreter_run(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + void *context ATTR_UNUSED, bool deferred) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + if ((eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) != 0) { + if (!deferred) { + sieve_runtime_error( + renv, NULL, + "the %s extension cannot be used in this context " + "(needs access to message envelope)", + sieve_extension_name(ext)); + } + return SIEVE_EXEC_FAILURE; + } + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/variables/Makefile.am b/pigeonhole/src/lib-sieve/plugins/variables/Makefile.am new file mode 100644 index 0000000..354bad2 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/Makefile.am @@ -0,0 +1,41 @@ +noinst_LTLIBRARIES = libsieve_ext_variables.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +cmds = \ + cmd-set.c + +tsts = \ + tst-string.c + +libsieve_ext_variables_la_SOURCES = \ + ext-variables-common.c \ + ext-variables-name.c \ + ext-variables-namespaces.c \ + ext-variables-arguments.c \ + ext-variables-operands.c \ + ext-variables-modifiers.c \ + ext-variables-dump.c \ + $(cmds) \ + $(tsts) \ + ext-variables.c + +public_headers = \ + sieve-ext-variables.h + +headers = \ + ext-variables-common.h \ + ext-variables-limits.h \ + ext-variables-name.h \ + ext-variables-namespaces.h \ + ext-variables-arguments.h \ + ext-variables-operands.h \ + ext-variables-modifiers.h \ + ext-variables-dump.h + +pkginc_libdir=$(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) + diff --git a/pigeonhole/src/lib-sieve/plugins/variables/Makefile.in b/pigeonhole/src/lib-sieve/plugins/variables/Makefile.in new file mode 100644 index 0000000..701d574 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/Makefile.in @@ -0,0 +1,801 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/variables +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(pkginc_lib_HEADERS) $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_variables_la_LIBADD = +am__objects_1 = cmd-set.lo +am__objects_2 = tst-string.lo +am_libsieve_ext_variables_la_OBJECTS = ext-variables-common.lo \ + ext-variables-name.lo ext-variables-namespaces.lo \ + ext-variables-arguments.lo ext-variables-operands.lo \ + ext-variables-modifiers.lo ext-variables-dump.lo \ + $(am__objects_1) $(am__objects_2) ext-variables.lo +libsieve_ext_variables_la_OBJECTS = \ + $(am_libsieve_ext_variables_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/cmd-set.Plo \ + ./$(DEPDIR)/ext-variables-arguments.Plo \ + ./$(DEPDIR)/ext-variables-common.Plo \ + ./$(DEPDIR)/ext-variables-dump.Plo \ + ./$(DEPDIR)/ext-variables-modifiers.Plo \ + ./$(DEPDIR)/ext-variables-name.Plo \ + ./$(DEPDIR)/ext-variables-namespaces.Plo \ + ./$(DEPDIR)/ext-variables-operands.Plo \ + ./$(DEPDIR)/ext-variables.Plo ./$(DEPDIR)/tst-string.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_variables_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_variables_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkginc_libdir)" +HEADERS = $(noinst_HEADERS) $(pkginc_lib_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_variables.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +cmds = \ + cmd-set.c + +tsts = \ + tst-string.c + +libsieve_ext_variables_la_SOURCES = \ + ext-variables-common.c \ + ext-variables-name.c \ + ext-variables-namespaces.c \ + ext-variables-arguments.c \ + ext-variables-operands.c \ + ext-variables-modifiers.c \ + ext-variables-dump.c \ + $(cmds) \ + $(tsts) \ + ext-variables.c + +public_headers = \ + sieve-ext-variables.h + +headers = \ + ext-variables-common.h \ + ext-variables-limits.h \ + ext-variables-name.h \ + ext-variables-namespaces.h \ + ext-variables-arguments.h \ + ext-variables-operands.h \ + ext-variables-modifiers.h \ + ext-variables-dump.h + +pkginc_libdir = $(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/variables/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/variables/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_variables.la: $(libsieve_ext_variables_la_OBJECTS) $(libsieve_ext_variables_la_DEPENDENCIES) $(EXTRA_libsieve_ext_variables_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_variables_la_OBJECTS) $(libsieve_ext_variables_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-set.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-variables-arguments.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-variables-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-variables-dump.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-variables-modifiers.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-variables-name.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-variables-namespaces.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-variables-operands.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-variables.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-string.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkginc_libHEADERS: $(pkginc_lib_HEADERS) + @$(NORMAL_INSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkginc_libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkginc_libdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkginc_libdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkginc_libdir)" || exit $$?; \ + done + +uninstall-pkginc_libHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkginc_libdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(pkginc_libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-set.Plo + -rm -f ./$(DEPDIR)/ext-variables-arguments.Plo + -rm -f ./$(DEPDIR)/ext-variables-common.Plo + -rm -f ./$(DEPDIR)/ext-variables-dump.Plo + -rm -f ./$(DEPDIR)/ext-variables-modifiers.Plo + -rm -f ./$(DEPDIR)/ext-variables-name.Plo + -rm -f ./$(DEPDIR)/ext-variables-namespaces.Plo + -rm -f ./$(DEPDIR)/ext-variables-operands.Plo + -rm -f ./$(DEPDIR)/ext-variables.Plo + -rm -f ./$(DEPDIR)/tst-string.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pkginc_libHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/cmd-set.Plo + -rm -f ./$(DEPDIR)/ext-variables-arguments.Plo + -rm -f ./$(DEPDIR)/ext-variables-common.Plo + -rm -f ./$(DEPDIR)/ext-variables-dump.Plo + -rm -f ./$(DEPDIR)/ext-variables-modifiers.Plo + -rm -f ./$(DEPDIR)/ext-variables-name.Plo + -rm -f ./$(DEPDIR)/ext-variables-namespaces.Plo + -rm -f ./$(DEPDIR)/ext-variables-operands.Plo + -rm -f ./$(DEPDIR)/ext-variables.Plo + -rm -f ./$(DEPDIR)/tst-string.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkginc_libHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-pkginc_libHEADERS install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pkginc_libHEADERS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/variables/cmd-set.c b/pigeonhole/src/lib-sieve/plugins/variables/cmd-set.c new file mode 100644 index 0000000..d0fdc97 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/cmd-set.c @@ -0,0 +1,235 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" + +#include "sieve-code.h" +#include "sieve-ast.h" +#include "sieve-commands.h" +#include "sieve-binary.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-variables-common.h" + +/* + * Set command + * + * Syntax: + * set [MODIFIER] <name: string> <value: string> + */ + +static bool cmd_set_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool cmd_set_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_set_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def cmd_set = { + .identifier = "set", + .type = SCT_COMMAND, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_set_registered, + .validate = cmd_set_validate, + .generate = cmd_set_generate, +}; + +/* + * Set operation + */ + +static bool cmd_set_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_set_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def cmd_set_operation = { + .mnemonic = "SET", + .ext_def = &variables_extension, + .code = EXT_VARIABLES_OPERATION_SET, + .dump = cmd_set_operation_dump, + .execute = cmd_set_operation_execute +}; + +/* + * Compiler context + */ + +struct cmd_set_context { + ARRAY_TYPE(sieve_variables_modifier) modifiers; +}; + +/* Command registration */ + +static bool cmd_set_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_variables_modifiers_link_tag(valdtr, ext, cmd_reg); + + return TRUE; +} + +/* + * Command validation + */ + +static bool cmd_set_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct sieve_ast_argument *arg = cmd->first_positional; + pool_t pool = sieve_command_pool(cmd); + struct cmd_set_context *sctx; + + /* Create command context */ + sctx = p_new(pool, struct cmd_set_context, 1); + p_array_init(&sctx->modifiers, pool, 4); + cmd->data = (void *) sctx; + + /* Validate modifiers */ + if ( !sieve_variables_modifiers_validate + (valdtr, cmd, &sctx->modifiers) ) + return FALSE; + + /* Validate name argument */ + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "name", 1, SAAT_STRING) ) { + return FALSE; + } + if ( !sieve_variable_argument_activate + (this_ext, this_ext, valdtr, cmd, arg, TRUE) ) { + return FALSE; + } + arg = sieve_ast_argument_next(arg); + + /* Validate value argument */ + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "value", 2, SAAT_STRING) ) { + return FALSE; + } + return sieve_validator_argument_activate + (valdtr, cmd, arg, FALSE); +} + +/* + * Code generation + */ + +static bool cmd_set_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct sieve_binary_block *sblock = cgenv->sblock; + struct cmd_set_context *sctx = (struct cmd_set_context *) cmd->data; + + sieve_operation_emit(sblock, this_ext, &cmd_set_operation); + + /* Generate arguments */ + if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) + return FALSE; + + /* Generate modifiers */ + if ( !sieve_variables_modifiers_generate + (cgenv, &sctx->modifiers) ) + return FALSE; + + return TRUE; +} + +/* + * Code dump + */ + +static bool cmd_set_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "SET"); + sieve_code_descend(denv); + + /* Print both variable name and string value */ + if ( !sieve_opr_string_dump(denv, address, "variable") || + !sieve_opr_string_dump(denv, address, "value") ) + return FALSE; + + return sieve_variables_modifiers_code_dump(denv, address); +} + +/* + * Code execution + */ + +static int cmd_set_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct sieve_variable_storage *storage; + ARRAY_TYPE(sieve_variables_modifier) modifiers; + unsigned int var_index; + string_t *value; + int ret = SIEVE_EXEC_OK; + + /* + * Read the normal operands + */ + + if ( (ret=sieve_variable_operand_read + (renv, address, "variable", &storage, &var_index)) <= 0 ) + return ret; + + if ( (ret=sieve_opr_string_read(renv, address, "string", &value)) <= 0 ) + return ret; + + if ( (ret=sieve_variables_modifiers_code_read + (renv, this_ext, address, &modifiers)) <= 0 ) + return ret; + + /* + * Determine and assign the value + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "set command"); + sieve_runtime_trace_descend(renv); + + /* Apply modifiers */ + if ( (ret=sieve_variables_modifiers_apply + (renv, this_ext, &modifiers, &value)) <= 0 ) + return ret; + + /* Actually assign the value if all is well */ + i_assert ( value != NULL ); + if ( !sieve_variable_assign(storage, var_index, value) ) + return SIEVE_EXEC_BIN_CORRUPT; + + /* Trace */ + if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) { + const char *var_name, *var_id; + + (void)sieve_variable_get_identifier(storage, var_index, &var_name); + var_id = sieve_variable_get_varid(storage, var_index); + + sieve_runtime_trace_here(renv, 0, "assign `%s' [%s] = \"%s\"", + var_name, var_id, str_c(value)); + } + + return SIEVE_EXEC_OK; +} + + + + + + diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-arguments.c b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-arguments.c new file mode 100644 index 0000000..2ac773c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-arguments.c @@ -0,0 +1,420 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-ast.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-dump.h" + +#include "ext-variables-common.h" +#include "ext-variables-limits.h" +#include "ext-variables-name.h" +#include "ext-variables-operands.h" +#include "ext-variables-namespaces.h" +#include "ext-variables-arguments.h" + +/* + * Variable argument implementation + */ + +static bool arg_variable_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *context); + +const struct sieve_argument_def variable_argument = { + .identifier = "@variable", + .generate = arg_variable_generate +}; + +static bool ext_variables_variable_argument_activate +(const struct sieve_extension *var_ext, + const struct sieve_extension *this_ext, + struct sieve_validator *valdtr, struct sieve_ast_argument *arg, + const char *variable) +{ + struct sieve_ast *ast = arg->ast; + struct sieve_variable *var; + + var = ext_variables_validator_declare_variable(this_ext, valdtr, variable); + + if ( var == NULL ) { + sieve_argument_validate_error(valdtr, arg, + "(implicit) declaration of new variable '%s' exceeds the limit " + "(max variables: %u)", variable, + sieve_variables_get_max_scope_size(var_ext)); + return FALSE; + } + + arg->argument = sieve_argument_create(ast, &variable_argument, this_ext, 0); + arg->argument->data = (void *) var; + return TRUE; +} + +static struct sieve_ast_argument *ext_variables_variable_argument_create +(const struct sieve_extension *this_ext, struct sieve_validator *valdtr, + struct sieve_ast_argument *parent_arg, const char *variable) +{ + struct sieve_ast *ast = parent_arg->ast; + struct sieve_ast_argument *new_arg; + + new_arg = sieve_ast_argument_create(ast, sieve_ast_argument_line(parent_arg)); + new_arg->type = SAAT_STRING; + + if ( !ext_variables_variable_argument_activate + (this_ext, this_ext, valdtr, new_arg, variable) ) + return NULL; + + return new_arg; +} + +static bool arg_variable_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *context ATTR_UNUSED) +{ + struct sieve_argument *argument = arg->argument; + struct sieve_variable *var = (struct sieve_variable *) argument->data; + + sieve_variables_opr_variable_emit(cgenv->sblock, argument->ext, var); + + return TRUE; +} + +/* + * Match value argument implementation + */ + +static bool arg_match_value_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *context ATTR_UNUSED); + +const struct sieve_argument_def match_value_argument = { + .identifier = "@match_value", + .generate = arg_match_value_generate +}; + +static bool ext_variables_match_value_argument_activate +(const struct sieve_extension *this_ext, + struct sieve_validator *valdtr, struct sieve_ast_argument *arg, + unsigned int index, bool assignment) +{ + struct sieve_ast *ast = arg->ast; + + if ( assignment ) { + sieve_argument_validate_error(valdtr, arg, + "cannot assign to match variable"); + return FALSE; + } + + if ( index > EXT_VARIABLES_MAX_MATCH_INDEX ) { + sieve_argument_validate_error(valdtr, arg, + "match value index %u out of range (max: %u)", index, + EXT_VARIABLES_MAX_MATCH_INDEX); + return FALSE; + } + + arg->argument = sieve_argument_create + (ast, &match_value_argument, this_ext, 0); + arg->argument->data = (void *) POINTER_CAST(index); + return TRUE; +} + +static struct sieve_ast_argument *ext_variables_match_value_argument_create +(const struct sieve_extension *this_ext, struct sieve_validator *valdtr, + struct sieve_ast_argument *parent_arg, unsigned int index) +{ + struct sieve_ast *ast = parent_arg->ast; + struct sieve_ast_argument *new_arg; + + new_arg = sieve_ast_argument_create(ast, sieve_ast_argument_line(parent_arg)); + new_arg->type = SAAT_STRING; + + if ( !ext_variables_match_value_argument_activate + (this_ext, valdtr, new_arg, index, FALSE) ) { + return NULL; + } + + return new_arg; +} + +static bool arg_match_value_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *context ATTR_UNUSED) +{ + struct sieve_argument *argument = arg->argument; + unsigned int index = POINTER_CAST_TO(argument->data, unsigned int); + + sieve_variables_opr_match_value_emit(cgenv->sblock, argument->ext, index); + + return TRUE; +} + +/* + * Variable string argument implementation + */ + +static bool arg_variable_string_validate + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +const struct sieve_argument_def variable_string_argument = { + .identifier = "@variable-string", + .validate = arg_variable_string_validate, + .generate = sieve_arg_catenated_string_generate, +}; + +static bool arg_variable_string_validate +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + const struct sieve_extension *this_ext = (*arg)->argument->ext; + enum { ST_NONE, ST_OPEN, ST_VARIABLE, ST_CLOSE } state = ST_NONE; + pool_t pool = sieve_ast_pool((*arg)->ast); + struct sieve_arg_catenated_string *catstr = NULL; + string_t *str = sieve_ast_argument_str(*arg); + const char *p, *strstart, *substart = NULL; + const char *strval = (const char *) str_data(str); + const char *strend = strval + str_len(str); + bool result = TRUE; + ARRAY_TYPE(sieve_variable_name) substitution; + int nelements = 0; + + T_BEGIN { + /* Initialize substitution structure */ + t_array_init(&substitution, 2); + + p = strval; + strstart = p; + while ( result && p < strend ) { + switch ( state ) { + + /* Nothing found yet */ + case ST_NONE: + if ( *p == '$' ) { + substart = p; + state = ST_OPEN; + } + p++; + break; + + /* Got '$' */ + case ST_OPEN: + if ( *p == '{' ) { + state = ST_VARIABLE; + p++; + } else + state = ST_NONE; + break; + + /* Got '${' */ + case ST_VARIABLE: + nelements = ext_variable_name_parse(&substitution, &p, strend); + + if ( nelements < 0 ) + state = ST_NONE; + else + state = ST_CLOSE; + + break; + + /* Finished parsing name, expecting '}' */ + case ST_CLOSE: + if ( *p == '}' ) { + struct sieve_ast_argument *strarg; + + /* We now know that the substitution is valid */ + + if ( catstr == NULL ) { + catstr = sieve_arg_catenated_string_create(*arg); + } + + /* Add the substring that is before the substitution to the + * variable-string AST. + * + * FIXME: For efficiency, if the variable is not found we should + * coalesce this substring with the one after the substitution. + */ + if ( substart > strstart ) { + string_t *newstr = str_new(pool, substart - strstart); + str_append_data(newstr, strstart, substart - strstart); + + strarg = sieve_ast_argument_string_create_raw + ((*arg)->ast, newstr, (*arg)->source_line); + sieve_arg_catenated_string_add_element(catstr, strarg); + + /* Give other substitution extensions a chance to do their work */ + if ( !sieve_validator_argument_activate_super + (valdtr, cmd, strarg, FALSE) ) { + result = FALSE; + break; + } + } + + /* Find the variable */ + if ( nelements == 1 ) { + const struct sieve_variable_name *cur_element = + array_idx(&substitution, 0); + + if ( cur_element->num_variable == -1 ) { + /* Add variable argument '${identifier}' */ + + strarg = ext_variables_variable_argument_create + (this_ext, valdtr, *arg, str_c(cur_element->identifier)); + + } else { + /* Add match value argument '${000}' */ + + strarg = ext_variables_match_value_argument_create + (this_ext, valdtr, *arg, cur_element->num_variable); + } + } else { + strarg = ext_variables_namespace_argument_create + (this_ext, valdtr, *arg, cmd, &substitution); + } + + if ( strarg != NULL ) + sieve_arg_catenated_string_add_element(catstr, strarg); + + strstart = p + 1; + substart = strstart; + + p++; + } + + /* Finished, reset for the next substitution */ + state = ST_NONE; + } + } + } T_END; + + /* Bail out early if substitution is invalid */ + if ( !result ) return FALSE; + + /* Check whether any substitutions were found */ + if ( catstr == NULL ) { + /* No substitutions in this string, pass it on to any other substution + * extension. + */ + return sieve_validator_argument_activate_super(valdtr, cmd, *arg, TRUE); + } + + /* Add the final substring that comes after the last substitution to the + * variable-string AST. + */ + if ( strend > strstart ) { + struct sieve_ast_argument *strarg; + string_t *newstr = str_new(pool, strend - strstart); + str_append_data(newstr, strstart, strend - strstart); + + strarg = sieve_ast_argument_string_create_raw + ((*arg)->ast, newstr, (*arg)->source_line); + sieve_arg_catenated_string_add_element(catstr, strarg); + + /* Give other substitution extensions a chance to do their work */ + if ( !sieve_validator_argument_activate_super + (valdtr, cmd, strarg, FALSE) ) + return FALSE; + } + + return TRUE; +} + +/* + * Variable argument interface + */ + +static bool _sieve_variable_argument_activate +(const struct sieve_extension *var_ext, + const struct sieve_extension *this_ext, + struct sieve_validator *valdtr, struct sieve_command *cmd, + struct sieve_ast_argument *arg, bool assignment) +{ + bool result = FALSE; + string_t *variable; + const char *varstr, *varend; + ARRAY_TYPE(sieve_variable_name) vname; + int nelements = 0; + + T_BEGIN { + t_array_init(&vname, 2); + + variable = sieve_ast_argument_str(arg); + varstr = str_c(variable); + varend = PTR_OFFSET(varstr, str_len(variable)); + nelements = ext_variable_name_parse(&vname, &varstr, varend); + + /* Check whether name parsing succeeded */ + if ( nelements <= 0 || varstr != varend ) { + /* Parse failed */ + sieve_argument_validate_error(valdtr, arg, + "invalid variable name '%s'", str_sanitize(str_c(variable),80)); + } else if ( nelements == 1 ) { + /* Normal (match) variable */ + + const struct sieve_variable_name *cur_element = + array_idx(&vname, 0); + + if ( cur_element->num_variable < 0 ) { + /* Variable */ + result = ext_variables_variable_argument_activate(var_ext, + this_ext, valdtr, arg, str_c(cur_element->identifier)); + + } else { + /* Match value */ + result = ext_variables_match_value_argument_activate + (this_ext, valdtr, arg, cur_element->num_variable, assignment); + } + + } else { + /* Namespace variable */ + result = ext_variables_namespace_argument_activate + (this_ext, valdtr, arg, cmd, &vname, assignment); + } + } T_END; + + return result; +} + +bool sieve_variable_argument_activate +(const struct sieve_extension *var_ext, + const struct sieve_extension *this_ext, + struct sieve_validator *valdtr, struct sieve_command *cmd, + struct sieve_ast_argument *arg, bool assignment) +{ + if ( sieve_ast_argument_type(arg) == SAAT_STRING ) { + /* Single string */ + return _sieve_variable_argument_activate(var_ext, + this_ext, valdtr, cmd, arg, assignment); + + } else if ( sieve_ast_argument_type(arg) == SAAT_STRING_LIST ) { + /* String list */ + struct sieve_ast_argument *stritem; + + i_assert ( !assignment ); + + stritem = sieve_ast_strlist_first(arg); + while ( stritem != NULL ) { + if ( !_sieve_variable_argument_activate(var_ext, + this_ext, valdtr, cmd, stritem, assignment) ) + return FALSE; + + stritem = sieve_ast_strlist_next(stritem); + } + + arg->argument = sieve_argument_create + (arg->ast, &string_list_argument, NULL, 0); + + return TRUE; + } + + return FALSE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-arguments.h b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-arguments.h new file mode 100644 index 0000000..87413c8 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-arguments.h @@ -0,0 +1,24 @@ +#ifndef EXT_VARIABLES_ARGUMENTS_H +#define EXT_VARIABLES_ARGUMENTS_H + +#include "sieve-common.h" + +/* + * Variable argument + */ + +extern const struct sieve_argument_def variable_argument; + +/* + * Match value argument + */ + +extern const struct sieve_argument_def match_value_argument; + +/* + * Variable string argument + */ + +extern const struct sieve_argument_def variable_string_argument; + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-common.c b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-common.c new file mode 100644 index 0000000..be9f677 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-common.c @@ -0,0 +1,950 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "hash.h" +#include "str.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-settings.h" + +#include "sieve-ast.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-objects.h" +#include "sieve-match-types.h" + +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-dump.h" +#include "sieve-interpreter.h" + +#include "ext-variables-common.h" +#include "ext-variables-limits.h" +#include "ext-variables-name.h" +#include "ext-variables-modifiers.h" + +/* + * Limits + */ + +unsigned int +sieve_variables_get_max_scope_size(const struct sieve_extension *var_ext) +{ + const struct ext_variables_config *config = + ext_variables_get_config(var_ext); + + return config->max_scope_size; +} + +size_t +sieve_variables_get_max_variable_size(const struct sieve_extension *var_ext) +{ + const struct ext_variables_config *config = + ext_variables_get_config(var_ext); + + return config->max_variable_size; +} + +/* + * Extension configuration + */ + +bool +ext_variables_load(const struct sieve_extension *ext, void **context) +{ + struct sieve_instance *svinst = ext->svinst; + struct ext_variables_config *config; + unsigned long long int uint_setting; + size_t size_setting; + + if (*context != NULL) + ext_variables_unload(ext); + + config = i_new(struct ext_variables_config, 1); + + /* Get limits */ + config->max_scope_size = EXT_VARIABLES_DEFAULT_MAX_SCOPE_SIZE; + config->max_variable_size = EXT_VARIABLES_DEFAULT_MAX_VARIABLE_SIZE; + + if (sieve_setting_get_uint_value( + svinst, "sieve_variables_max_scope_size", &uint_setting)) { + if (uint_setting < EXT_VARIABLES_REQUIRED_MAX_SCOPE_SIZE) { + e_warning(svinst->event, "variables: " + "setting sieve_variables_max_scope_size " + "is lower than required by standards " + "(>= %llu items)", + (unsigned long long)EXT_VARIABLES_REQUIRED_MAX_SCOPE_SIZE); + } else { + config->max_scope_size = (unsigned int)uint_setting; + } + } + + if (sieve_setting_get_size_value( + svinst, "sieve_variables_max_variable_size", &size_setting)) { + if (size_setting < EXT_VARIABLES_REQUIRED_MAX_VARIABLE_SIZE) { + e_warning(svinst->event, "variables: " + "setting sieve_variables_max_variable_size " + "is lower than required by standards " + "(>= %zu bytes)", + (size_t)EXT_VARIABLES_REQUIRED_MAX_VARIABLE_SIZE); + } else { + config->max_variable_size = size_setting; + } + } + + *context = (void *)config; + return TRUE; +} + +void ext_variables_unload(const struct sieve_extension *ext) +{ + struct ext_variables_config *config = + (struct ext_variables_config *)ext->context; + + i_free(config); +} + +const struct ext_variables_config * +ext_variables_get_config(const struct sieve_extension *var_ext) +{ + const struct ext_variables_config *config = + (const struct ext_variables_config *)var_ext->context; + + i_assert(var_ext->def == &variables_extension); + return config; +} + +/* + * Variable scope + */ + +struct sieve_variable_scope { + pool_t pool; + int refcount; + + struct sieve_instance *svinst; + const struct sieve_extension *var_ext; + const struct sieve_extension *ext; + + struct sieve_variable *error_var; + + HASH_TABLE(const char *, struct sieve_variable *) variables; + ARRAY(struct sieve_variable *) variable_index; +}; + +struct sieve_variable_scope_binary { + struct sieve_variable_scope *scope; + + unsigned int size; + struct sieve_binary_block *sblock; + sieve_size_t address; +}; + +struct sieve_variable_scope_iter { + struct sieve_variable_scope *scope; + struct hash_iterate_context *hctx; +}; + +struct sieve_variable_scope * +sieve_variable_scope_create(struct sieve_instance *svinst, + const struct sieve_extension *var_ext, + const struct sieve_extension *ext) +{ + struct sieve_variable_scope *scope; + pool_t pool; + + i_assert(var_ext->def == &variables_extension); + + pool = pool_alloconly_create("sieve_variable_scope", 4096); + scope = p_new(pool, struct sieve_variable_scope, 1); + scope->pool = pool; + scope->refcount = 1; + + scope->svinst = svinst; + scope->var_ext = var_ext; + scope->ext = ext; + + hash_table_create(&scope->variables, pool, 0, strcase_hash, strcasecmp); + p_array_init(&scope->variable_index, pool, 128); + + return scope; +} + +void sieve_variable_scope_ref(struct sieve_variable_scope *scope) +{ + scope->refcount++; +} + +void sieve_variable_scope_unref(struct sieve_variable_scope **_scope) +{ + struct sieve_variable_scope *scope = *_scope; + + i_assert(scope->refcount > 0); + + if (--scope->refcount != 0) + return; + + hash_table_destroy(&scope->variables); + + *_scope = NULL; + pool_unref(&scope->pool); +} + +pool_t sieve_variable_scope_pool(struct sieve_variable_scope *scope) +{ + return scope->pool; +} + +struct sieve_variable * +sieve_variable_scope_declare(struct sieve_variable_scope *scope, + const char *identifier) +{ + unsigned int max_scope_size; + struct sieve_variable *var; + + var = hash_table_lookup(scope->variables, identifier); + if (var != NULL) + return var; + + max_scope_size = sieve_variables_get_max_scope_size(scope->var_ext); + if (array_count(&scope->variable_index) >= max_scope_size) { + if (scope->error_var == NULL) { + var = p_new(scope->pool, struct sieve_variable, 1); + var->identifier = "@ERROR@"; + var->index = 0; + + scope->error_var = var; + return NULL; + } + + return scope->error_var; + } + + var = p_new(scope->pool, struct sieve_variable, 1); + var->ext = scope->ext; + var->identifier = p_strdup(scope->pool, identifier); + var->index = array_count(&scope->variable_index); + + hash_table_insert(scope->variables, var->identifier, var); + array_append(&scope->variable_index, &var, 1); + return var; +} + +struct sieve_variable * +sieve_variable_scope_get_variable(struct sieve_variable_scope *scope, + const char *identifier) +{ + return hash_table_lookup(scope->variables, identifier); +} + +struct sieve_variable * +sieve_variable_scope_import(struct sieve_variable_scope *scope, + struct sieve_variable *var) +{ + struct sieve_variable *old_var, *new_var; + + old_var = sieve_variable_scope_get_variable(scope, var->identifier); + if (old_var != NULL) { + i_assert(memcmp(old_var, var, sizeof(*var)) == 0); + return old_var; + } + + new_var = p_new(scope->pool, struct sieve_variable, 1); + memcpy(new_var, var, sizeof(*new_var)); + + hash_table_insert(scope->variables, new_var->identifier, new_var); + + /* Not entered into the index because it is an external variable + (This can be done unlimited; only limited by the size of the external + scope) + */ + return new_var; +} + +struct sieve_variable_scope_iter * +sieve_variable_scope_iterate_init(struct sieve_variable_scope *scope) +{ + struct sieve_variable_scope_iter *iter; + + iter = t_new(struct sieve_variable_scope_iter, 1); + iter->scope = scope; + iter->hctx = hash_table_iterate_init(scope->variables); + + return iter; +} + +bool sieve_variable_scope_iterate(struct sieve_variable_scope_iter *iter, + struct sieve_variable **var_r) +{ + const char *key; + + return hash_table_iterate(iter->hctx, iter->scope->variables, + &key, var_r); +} + +void sieve_variable_scope_iterate_deinit( + struct sieve_variable_scope_iter **iter) +{ + hash_table_iterate_deinit(&(*iter)->hctx); + *iter = NULL; +} + +unsigned int +sieve_variable_scope_declarations(struct sieve_variable_scope *scope) +{ + return hash_table_count(scope->variables); +} + +unsigned int sieve_variable_scope_size(struct sieve_variable_scope *scope) +{ + return array_count(&scope->variable_index); +} + +struct sieve_variable * const * +sieve_variable_scope_get_variables(struct sieve_variable_scope *scope, + unsigned int *size_r) +{ + return array_get(&scope->variable_index, size_r); +} + +struct sieve_variable * +sieve_variable_scope_get_indexed(struct sieve_variable_scope *scope, + unsigned int index) +{ + struct sieve_variable * const *var; + + if (index >= array_count(&scope->variable_index)) + return NULL; + + var = array_idx(&scope->variable_index, index); + return *var; +} + +/* Scope binary */ + +struct sieve_variable_scope * +sieve_variable_scope_binary_dump(struct sieve_instance *svinst, + const struct sieve_extension *var_ext, + const struct sieve_extension *ext, + const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + struct sieve_variable_scope *local_scope; + unsigned int i, scope_size; + sieve_size_t pc; + sieve_offset_t end_offset; + + /* Read scope size */ + sieve_code_mark(denv); + if (!sieve_binary_read_unsigned(denv->sblock, address, &scope_size)) + return NULL; + + /* Read offset */ + pc = *address; + if (!sieve_binary_read_offset(denv->sblock, address, &end_offset)) + return NULL; + + /* Create scope */ + local_scope = sieve_variable_scope_create(svinst, var_ext, ext); + + /* Read and dump scope itself */ + + sieve_code_dumpf(denv, "VARIABLES SCOPE [%u] (end: %08x)", + scope_size, (unsigned int)(pc + end_offset)); + + for (i = 0; i < scope_size; i++) { + string_t *identifier; + + sieve_code_mark(denv); + if (!sieve_binary_read_string(denv->sblock, address, + &identifier)) + return NULL; + + sieve_code_dumpf(denv, "%3d: '%s'", i, str_c(identifier)); + + (void)sieve_variable_scope_declare(local_scope, + str_c(identifier)); + } + + return local_scope; +} + +struct sieve_variable_scope_binary * +sieve_variable_scope_binary_create(struct sieve_variable_scope *scope) +{ + struct sieve_variable_scope_binary *scpbin; + + scpbin = p_new(scope->pool, struct sieve_variable_scope_binary, 1); + scpbin->scope = scope; + + return scpbin; +} + +void sieve_variable_scope_binary_ref(struct sieve_variable_scope_binary *scpbin) +{ + sieve_variable_scope_ref(scpbin->scope); +} + +void sieve_variable_scope_binary_unref( + struct sieve_variable_scope_binary **scpbin) +{ + sieve_variable_scope_unref(&(*scpbin)->scope); + *scpbin = NULL; +} + +struct sieve_variable_scope_binary * +sieve_variable_scope_binary_read(struct sieve_instance *svinst, + const struct sieve_extension *var_ext, + const struct sieve_extension *ext, + struct sieve_binary_block *sblock, + sieve_size_t *address) +{ + struct sieve_variable_scope *scope; + struct sieve_variable_scope_binary *scpbin; + unsigned int scope_size, max_scope_size; + const char *ext_name = (ext == NULL ? "variables" : + sieve_extension_name(ext)); + sieve_size_t pc; + sieve_offset_t end_offset; + + /* Read scope size */ + if (!sieve_binary_read_unsigned(sblock, address, &scope_size)) { + e_error(svinst->event, "%s: " + "variable scope: failed to read size", ext_name); + return NULL; + } + + /* Check size limit */ + max_scope_size = sieve_variables_get_max_scope_size(var_ext); + if (scope_size > max_scope_size) { + e_error(svinst->event, "%s: " + "variable scope: size exceeds the limit (%u > %u)", + ext_name, scope_size, max_scope_size); + return NULL; + } + + /* Read offset */ + pc = *address; + if (!sieve_binary_read_offset(sblock, address, &end_offset)) { + e_error(svinst->event, "%s: " + "variable scope: failed to read end offset", ext_name); + return NULL; + } + + /* Create scope */ + scope = sieve_variable_scope_create(svinst, var_ext, ext); + + scpbin = sieve_variable_scope_binary_create(scope); + scpbin->size = scope_size; + scpbin->sblock = sblock; + scpbin->address = *address; + + *address = pc + end_offset; + + return scpbin; +} + +struct sieve_variable_scope * +sieve_variable_scope_binary_get(struct sieve_variable_scope_binary *scpbin) +{ + const struct sieve_extension *ext = scpbin->scope->ext; + struct sieve_instance *svinst = scpbin->scope->svinst; + const char *ext_name = (ext == NULL ? "variables" : + sieve_extension_name(ext)); + unsigned int i; + + if (scpbin->sblock != NULL) { + sieve_size_t *address = &scpbin->address; + + /* Read scope itself */ + for (i = 0; i < scpbin->size; i++) { + struct sieve_variable *var; + string_t *identifier; + + if (!sieve_binary_read_string(scpbin->sblock, address, + &identifier)) { + e_error(svinst->event, "%s: variable scope: " + "failed to read variable name", + ext_name); + return NULL; + } + + var = sieve_variable_scope_declare(scpbin->scope, + str_c(identifier)); + + i_assert(var != NULL); + i_assert(var->index == i); + } + + scpbin->sblock = NULL; + } + + return scpbin->scope; +} + +unsigned int +sieve_variable_scope_binary_get_size( + struct sieve_variable_scope_binary *scpbin) +{ + if (scpbin->sblock != NULL) + return scpbin->size; + + return array_count(&scpbin->scope->variable_index); +} + +/* + * Variable storage + */ + +struct sieve_variable_storage { + pool_t pool; + const struct sieve_extension *var_ext; + struct sieve_variable_scope *scope; + struct sieve_variable_scope_binary *scope_bin; + unsigned int max_size; + ARRAY(string_t *) var_values; +}; + +struct sieve_variable_storage * +sieve_variable_storage_create(const struct sieve_extension *var_ext, + pool_t pool, + struct sieve_variable_scope_binary *scpbin) +{ + struct sieve_variable_storage *storage; + + storage = p_new(pool, struct sieve_variable_storage, 1); + storage->pool = pool; + storage->var_ext = var_ext; + storage->scope_bin = scpbin; + storage->scope = NULL; + + storage->max_size = sieve_variable_scope_binary_get_size(scpbin); + + p_array_init(&storage->var_values, pool, 4); + + return storage; +} + +static inline bool +sieve_variable_valid(struct sieve_variable_storage *storage, + unsigned int index) +{ + if (storage->scope_bin == NULL) + return TRUE; + + return (index < storage->max_size); +} + +bool sieve_variable_get_identifier(struct sieve_variable_storage *storage, + unsigned int index, const char **identifier) +{ + struct sieve_variable * const *var; + + *identifier = NULL; + + if (storage->scope_bin == NULL) + return TRUE; + + if (storage->scope == NULL) { + storage->scope = + sieve_variable_scope_binary_get(storage->scope_bin); + if (storage->scope == NULL) + return FALSE; + } + + /* FIXME: direct invasion of the scope object is a bit ugly */ + if (index >= array_count(&storage->scope->variable_index)) + return FALSE; + + var = array_idx(&storage->scope->variable_index, index); + if (*var != NULL) + *identifier = (*var)->identifier; + return TRUE; +} + +const char * +sieve_variable_get_varid(struct sieve_variable_storage *storage, + unsigned int index) +{ + if (storage->scope_bin == NULL) + return t_strdup_printf("%ld", (long)index); + + if (storage->scope == NULL) { + storage->scope = + sieve_variable_scope_binary_get(storage->scope_bin); + if (storage->scope == NULL) + return NULL; + } + + return sieve_ext_variables_get_varid(storage->scope->ext, index); +} + +bool sieve_variable_get(struct sieve_variable_storage *storage, + unsigned int index, string_t **value) +{ + *value = NULL; + + if (index < array_count(&storage->var_values)) { + string_t * const *varent; + + varent = array_idx(&storage->var_values, index); + + *value = *varent; + } else if (!sieve_variable_valid(storage, index)) { + return FALSE; + } + + return TRUE; +} + +bool sieve_variable_get_modifiable(struct sieve_variable_storage *storage, + unsigned int index, string_t **value) +{ + string_t *dummy; + + if (value == NULL) + value = &dummy; + + if (!sieve_variable_get(storage, index, value)) + return FALSE; + + if (*value == NULL) { + *value = str_new(storage->pool, 256); + array_idx_set(&storage->var_values, index, value); + } + return TRUE; +} + +bool sieve_variable_assign(struct sieve_variable_storage *storage, + unsigned int index, const string_t *value) +{ + const struct ext_variables_config *config = + ext_variables_get_config(storage->var_ext); + string_t *varval; + + if (!sieve_variable_get_modifiable(storage, index, &varval)) + return FALSE; + + str_truncate(varval, 0); + str_append_str(varval, value); + + /* Just a precaution, caller should prevent this in the first place */ + if (str_len(varval) > config->max_variable_size) + str_truncate_utf8(varval, config->max_variable_size); + + return TRUE; +} + +bool sieve_variable_assign_cstr(struct sieve_variable_storage *storage, + unsigned int index, const char *value) +{ + const struct ext_variables_config *config = + ext_variables_get_config(storage->var_ext); + string_t *varval; + + if (!sieve_variable_get_modifiable(storage, index, &varval)) + return FALSE; + + str_truncate(varval, 0); + str_append(varval, value); + + /* Just a precaution, caller should prevent this in the first place */ + if (str_len(varval) > config->max_variable_size) + str_truncate_utf8(varval, config->max_variable_size); + + return TRUE; +} + +/* + * AST Context + */ + +static void +ext_variables_ast_free(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_ast *ast ATTR_UNUSED, void *context) +{ + struct sieve_variable_scope *local_scope = + (struct sieve_variable_scope *)context; + + /* Unreference main variable scope */ + sieve_variable_scope_unref(&local_scope); +} + +static const struct sieve_ast_extension variables_ast_extension = { + &variables_extension, + ext_variables_ast_free +}; + +static struct sieve_variable_scope * +ext_variables_create_local_scope(const struct sieve_extension *this_ext, + struct sieve_ast *ast) +{ + struct sieve_variable_scope *scope; + + scope = sieve_variable_scope_create(this_ext->svinst, this_ext, NULL); + + sieve_ast_extension_register(ast, this_ext, &variables_ast_extension, + (void *)scope); + return scope; +} + +static struct sieve_variable_scope * +ext_variables_ast_get_local_scope(const struct sieve_extension *this_ext, + struct sieve_ast *ast) +{ + struct sieve_variable_scope *local_scope = + (struct sieve_variable_scope *) + sieve_ast_extension_get_context(ast, this_ext); + + return local_scope; +} + +/* + * Validator context + */ + +static struct ext_variables_validator_context * +ext_variables_validator_context_create(const struct sieve_extension *this_ext, + struct sieve_validator *valdtr) +{ + pool_t pool = sieve_validator_pool(valdtr); + struct ext_variables_validator_context *ctx; + struct sieve_ast *ast = sieve_validator_ast(valdtr); + + ctx = p_new(pool, struct ext_variables_validator_context, 1); + ctx->modifiers = sieve_validator_object_registry_create(valdtr); + ctx->namespaces = sieve_validator_object_registry_create(valdtr); + ctx->local_scope = ext_variables_create_local_scope(this_ext, ast); + + sieve_validator_extension_set_context(valdtr, this_ext, (void *)ctx); + return ctx; +} + +struct ext_variables_validator_context * +ext_variables_validator_context_get(const struct sieve_extension *this_ext, + struct sieve_validator *valdtr) +{ + struct ext_variables_validator_context *ctx; + + i_assert(sieve_extension_is(this_ext, variables_extension)); + ctx = (struct ext_variables_validator_context *) + sieve_validator_extension_get_context(valdtr, this_ext); + + if (ctx == NULL) + ctx = ext_variables_validator_context_create(this_ext, valdtr); + return ctx; +} + +void ext_variables_validator_initialize(const struct sieve_extension *this_ext, + struct sieve_validator *valdtr) +{ + struct ext_variables_validator_context *ctx; + + /* Create our context */ + ctx = ext_variables_validator_context_get(this_ext, valdtr); + + ext_variables_register_core_modifiers(this_ext, ctx); + + ctx->active = TRUE; +} + +struct sieve_variable *ext_variables_validator_get_variable( + const struct sieve_extension *this_ext, + struct sieve_validator *validator, const char *variable) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(this_ext, validator); + + return sieve_variable_scope_get_variable(ctx->local_scope, variable); +} + +struct sieve_variable * +ext_variables_validator_declare_variable(const struct sieve_extension *this_ext, + struct sieve_validator *validator, + const char *variable) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(this_ext, validator); + + return sieve_variable_scope_declare(ctx->local_scope, variable); +} + +struct sieve_variable_scope * +sieve_ext_variables_get_local_scope(const struct sieve_extension *var_ext, + struct sieve_validator *validator) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(var_ext, validator); + + return ctx->local_scope; +} + +bool sieve_ext_variables_is_active(const struct sieve_extension *var_ext, + struct sieve_validator *valdtr) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(var_ext, valdtr); + + return (ctx != NULL && ctx->active); +} + +/* + * Code generation + */ + +bool ext_variables_generator_load(const struct sieve_extension *ext, + const struct sieve_codegen_env *cgenv) +{ + struct sieve_variable_scope *local_scope = + ext_variables_ast_get_local_scope(ext, cgenv->ast); + unsigned int count = sieve_variable_scope_size(local_scope); + sieve_size_t jump; + + sieve_binary_emit_unsigned(cgenv->sblock, count); + + jump = sieve_binary_emit_offset(cgenv->sblock, 0); + + if (count > 0) { + unsigned int size, i; + struct sieve_variable *const *vars = + sieve_variable_scope_get_variables(local_scope, &size); + + for (i = 0; i < size; i++) { + sieve_binary_emit_cstring(cgenv->sblock, + vars[i]->identifier); + } + } + + sieve_binary_resolve_offset(cgenv->sblock, jump); + return TRUE; +} + +/* + * Interpreter context + */ + +struct ext_variables_interpreter_context { + pool_t pool; + + struct sieve_variable_scope *local_scope; + struct sieve_variable_scope_binary *local_scope_bin; + + struct sieve_variable_storage *local_storage; + ARRAY(struct sieve_variable_storage *) ext_storages; +}; + +static void +ext_variables_interpreter_free(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_interpreter *interp ATTR_UNUSED, + void *context) +{ + struct ext_variables_interpreter_context *ctx = + (struct ext_variables_interpreter_context *)context; + + sieve_variable_scope_binary_unref(&ctx->local_scope_bin); +} + +static struct sieve_interpreter_extension +variables_interpreter_extension = { + .ext_def = &variables_extension, + .free = ext_variables_interpreter_free +}; + +static struct ext_variables_interpreter_context * +ext_variables_interpreter_context_create( + const struct sieve_extension *this_ext, + struct sieve_interpreter *interp, + struct sieve_variable_scope_binary *scpbin) +{ + pool_t pool = sieve_interpreter_pool(interp); + struct ext_variables_interpreter_context *ctx; + + ctx = p_new(pool, struct ext_variables_interpreter_context, 1); + ctx->pool = pool; + ctx->local_scope = NULL; + ctx->local_scope_bin = scpbin; + ctx->local_storage = + sieve_variable_storage_create(this_ext, pool, scpbin); + p_array_init(&ctx->ext_storages, pool, + sieve_extensions_get_count(this_ext->svinst)); + + sieve_interpreter_extension_register(interp, this_ext, + &variables_interpreter_extension, + (void *)ctx); + return ctx; +} + +bool ext_variables_interpreter_load(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct sieve_variable_scope_binary *scpbin; + + scpbin = sieve_variable_scope_binary_read(eenv->svinst, ext, NULL, + renv->sblock, address); + if (scpbin == NULL) + return FALSE; + + /* Create our context */ + (void)ext_variables_interpreter_context_create(ext, renv->interp, + scpbin); + + /* Enable support for match values */ + (void)sieve_match_values_set_enabled(renv, TRUE); + + return TRUE; +} + +static inline struct ext_variables_interpreter_context * +ext_variables_interpreter_context_get(const struct sieve_extension *this_ext, + struct sieve_interpreter *interp) +{ + struct ext_variables_interpreter_context *ctx; + + i_assert(sieve_extension_is(this_ext, variables_extension)); + ctx = (struct ext_variables_interpreter_context *) + sieve_interpreter_extension_get_context(interp, this_ext); + return ctx; +} + +struct sieve_variable_storage * +sieve_ext_variables_runtime_get_storage(const struct sieve_extension *var_ext, + const struct sieve_runtime_env *renv, + const struct sieve_extension *ext) +{ + struct ext_variables_interpreter_context *ctx = + ext_variables_interpreter_context_get(var_ext, renv->interp); + struct sieve_variable_storage * const *storage; + + if (ext == NULL) + return ctx->local_storage; + + if (ext->id >= (int)array_count(&ctx->ext_storages)) + storage = NULL; + else + storage = array_idx(&ctx->ext_storages, ext->id); + + if (storage == NULL) + return NULL; + return *storage; +} + +void sieve_ext_variables_runtime_set_storage( + const struct sieve_extension *var_ext, + const struct sieve_runtime_env *renv, const struct sieve_extension *ext, + struct sieve_variable_storage *storage) +{ + struct ext_variables_interpreter_context *ctx = + ext_variables_interpreter_context_get(var_ext, renv->interp); + + if (ctx == NULL || ext == NULL || storage == NULL) + return; + if (ext->id < 0) + return; + + array_idx_set(&ctx->ext_storages, (unsigned int) ext->id, &storage); +} diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-common.h b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-common.h new file mode 100644 index 0000000..401d943 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-common.h @@ -0,0 +1,102 @@ +#ifndef EXT_VARIABLES_COMMON_H +#define EXT_VARIABLES_COMMON_H + +#include "sieve-common.h" +#include "sieve-validator.h" + +#include "sieve-ext-variables.h" + +/* + * Extension + */ + +struct ext_variables_config { + /* Maximum number of variables (in a scope) */ + unsigned int max_scope_size; + /* Maximum size of variable value */ + size_t max_variable_size; +}; + +extern const struct sieve_extension_def variables_extension; + +bool ext_variables_load(const struct sieve_extension *ext, void **context); +void ext_variables_unload(const struct sieve_extension *ext); + +const struct ext_variables_config * +ext_variables_get_config(const struct sieve_extension *var_ext); + +/* + * Commands + */ + +extern const struct sieve_command_def cmd_set; +extern const struct sieve_command_def tst_string; + +/* + * Operands + */ + +enum ext_variables_operand { + EXT_VARIABLES_OPERAND_VARIABLE, + EXT_VARIABLES_OPERAND_MATCH_VALUE, + EXT_VARIABLES_OPERAND_NAMESPACE_VARIABLE, + EXT_VARIABLES_OPERAND_MODIFIER +}; + +/* + * Operations + */ + +extern const struct sieve_operation_def cmd_set_operation; +extern const struct sieve_operation_def tst_string_operation; + +enum ext_variables_opcode { + EXT_VARIABLES_OPERATION_SET, + EXT_VARIABLES_OPERATION_STRING +}; + +/* + * Validator context + */ + +struct ext_variables_validator_context { + bool active; + + struct sieve_validator_object_registry *modifiers; + struct sieve_validator_object_registry *namespaces; + + struct sieve_variable_scope *local_scope; +}; + +void ext_variables_validator_initialize(const struct sieve_extension *this_ext, + struct sieve_validator *validator); + +struct ext_variables_validator_context * +ext_variables_validator_context_get(const struct sieve_extension *this_ext, + struct sieve_validator *valdtr); + +struct sieve_variable * +ext_variables_validator_get_variable(const struct sieve_extension *this_ext, + struct sieve_validator *validator, + const char *variable); +struct sieve_variable * +ext_variables_validator_declare_variable(const struct sieve_extension *this_ext, + struct sieve_validator *validator, + const char *variable); + +/* + * Code generation + */ + +bool ext_variables_generator_load(const struct sieve_extension *ext, + const struct sieve_codegen_env *cgenv); + +/* + * Interpreter context + */ + +bool ext_variables_interpreter_load(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + sieve_size_t *address); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-dump.c b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-dump.c new file mode 100644 index 0000000..26bd015 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-dump.c @@ -0,0 +1,137 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" +#include "sieve-dump.h" +#include "sieve-binary.h" +#include "sieve-code.h" + +#include "ext-variables-common.h" +#include "ext-variables-dump.h" + +/* + * Code dumper extension + */ + +static void ext_variables_code_dumper_free + (struct sieve_code_dumper *dumper, void *context); + +static const struct sieve_code_dumper_extension +variables_dump_extension = { + &variables_extension, + ext_variables_code_dumper_free +}; + +/* + * Code dump context + */ + +struct ext_variables_dump_context { + struct sieve_variable_scope *local_scope; + ARRAY(struct sieve_variable_scope *) ext_scopes; +}; + +static void ext_variables_code_dumper_free +(struct sieve_code_dumper *dumper ATTR_UNUSED, void *context) +{ + struct ext_variables_dump_context *dctx = + (struct ext_variables_dump_context *) context; + + if ( dctx == NULL || dctx->local_scope == NULL ) + return; + + sieve_variable_scope_unref(&dctx->local_scope); +} + +static struct ext_variables_dump_context *ext_variables_dump_get_context +(const struct sieve_extension *this_ext, const struct sieve_dumptime_env *denv) +{ + struct sieve_code_dumper *dumper = denv->cdumper; + struct ext_variables_dump_context *dctx; + pool_t pool; + + i_assert( sieve_extension_is(this_ext, variables_extension) ); + dctx = sieve_dump_extension_get_context(dumper, this_ext); + + if ( dctx == NULL ) { + /* Create dumper context */ + pool = sieve_code_dumper_pool(dumper); + dctx = p_new(pool, struct ext_variables_dump_context, 1); + p_array_init(&dctx->ext_scopes, pool, + sieve_extensions_get_count(this_ext->svinst)); + + sieve_dump_extension_register + (dumper, this_ext, &variables_dump_extension, dctx); + } + + return dctx; +} + +bool ext_variables_code_dump +(const struct sieve_extension *ext, + const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + struct ext_variables_dump_context *dctx; + struct sieve_variable_scope *local_scope; + + local_scope = sieve_variable_scope_binary_dump + (ext->svinst, ext, NULL, denv, address); + + dctx = ext_variables_dump_get_context(ext, denv); + dctx->local_scope = local_scope; + + return TRUE; +} + +/* + * Scope registry + */ + +void sieve_ext_variables_dump_set_scope +(const struct sieve_extension *var_ext, const struct sieve_dumptime_env *denv, + const struct sieve_extension *ext, struct sieve_variable_scope *scope) +{ + struct ext_variables_dump_context *dctx = + ext_variables_dump_get_context(var_ext, denv); + + if ( ext->id < 0 ) return; + + array_idx_set(&dctx->ext_scopes, (unsigned int) ext->id, &scope); +} + +/* + * Variable identifier dump + */ + +const char *ext_variables_dump_get_identifier +(const struct sieve_extension *var_ext, const struct sieve_dumptime_env *denv, + const struct sieve_extension *ext, unsigned int index) +{ + struct ext_variables_dump_context *dctx = + ext_variables_dump_get_context(var_ext, denv); + struct sieve_variable_scope *scope; + struct sieve_variable *var; + + if ( ext == NULL ) + scope = dctx->local_scope; + else { + struct sieve_variable_scope *const *ext_scope; + + if ( ext->id < 0 || ext->id >= (int) array_count(&dctx->ext_scopes) ) + return NULL; + + ext_scope = array_idx(&dctx->ext_scopes, (unsigned int) ext->id); + scope = *ext_scope; + } + + if ( scope == NULL ) + return NULL; + + var = sieve_variable_scope_get_indexed(scope, index); + + return var->identifier; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-dump.h b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-dump.h new file mode 100644 index 0000000..da72a5d --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-dump.h @@ -0,0 +1,22 @@ +#ifndef EXT_VARIABLES_DUMP_H +#define EXT_VARIABLES_DUMP_H + +#include "sieve-common.h" + +/* + * Code dump context + */ + +bool ext_variables_code_dump + (const struct sieve_extension *ext, const struct sieve_dumptime_env *denv, + sieve_size_t *address); + +/* + * Variable identifier dump + */ + +const char *ext_variables_dump_get_identifier +(const struct sieve_extension *var_ext, const struct sieve_dumptime_env *denv, + const struct sieve_extension *ext, unsigned int index); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-limits.h b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-limits.h new file mode 100644 index 0000000..61260c8 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-limits.h @@ -0,0 +1,35 @@ +#ifndef EXT_VARIABLES_LIMITS_H +#define EXT_VARIABLES_LIMITS_H + +#include "sieve-limits.h" + +/* From RFC 5229: + * + * 6. Implementation Limits + * + * An implementation of this document MUST support at least 128 distinct + * variables. The supported length of variable names MUST be at least + * 32 characters. Each variable MUST be able to hold at least 4000 + * characters. Attempts to set the variable to a value larger than what + * the implementation supports SHOULD be reported as an error at + * compile-time if possible. If the attempt is discovered during run- + * time, the value SHOULD be truncated, and it MUST NOT be treated as an + * error. + + * Match variables ${1} through ${9} MUST be supported. References to + * higher indices than those the implementation supports MUST be treated + * as a syntax error, which SHOULD be discovered at compile-time. + */ + +#define EXT_VARIABLES_DEFAULT_MAX_SCOPE_SIZE 255 +#define EXT_VARIABLES_DEFAULT_MAX_VARIABLE_SIZE (4 * 1024) + +#define EXT_VARIABLES_REQUIRED_MAX_SCOPE_SIZE 128 +#define EXT_VARIABLES_REQUIRED_MAX_VARIABLE_SIZE 4000 + +#define EXT_VARIABLES_MAX_VARIABLE_NAME_LEN 64 +#define EXT_VARIABLES_MAX_NAMESPACE_ELEMENTS 10 + +#define EXT_VARIABLES_MAX_MATCH_INDEX SIEVE_MAX_MATCH_VALUES + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-modifiers.c b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-modifiers.c new file mode 100644 index 0000000..dd21c88 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-modifiers.c @@ -0,0 +1,578 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "unichar.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-runtime.h" + +#include "ext-variables-common.h" +#include "ext-variables-limits.h" +#include "ext-variables-modifiers.h" + +#include <ctype.h> + +/* + * Core modifiers + */ + +extern const struct sieve_variables_modifier_def lower_modifier; +extern const struct sieve_variables_modifier_def upper_modifier; +extern const struct sieve_variables_modifier_def lowerfirst_modifier; +extern const struct sieve_variables_modifier_def upperfirst_modifier; +extern const struct sieve_variables_modifier_def quotewildcard_modifier; +extern const struct sieve_variables_modifier_def length_modifier; + +enum ext_variables_modifier_code { + EXT_VARIABLES_MODIFIER_LOWER, + EXT_VARIABLES_MODIFIER_UPPER, + EXT_VARIABLES_MODIFIER_LOWERFIRST, + EXT_VARIABLES_MODIFIER_UPPERFIRST, + EXT_VARIABLES_MODIFIER_QUOTEWILDCARD, + EXT_VARIABLES_MODIFIER_LENGTH +}; + +const struct sieve_variables_modifier_def *ext_variables_core_modifiers[] = { + &lower_modifier, + &upper_modifier, + &lowerfirst_modifier, + &upperfirst_modifier, + "ewildcard_modifier, + &length_modifier +}; + +const unsigned int ext_variables_core_modifiers_count = + N_ELEMENTS(ext_variables_core_modifiers); + +#define ext_variables_modifier_name(modf) \ + (modf)->object->def->name +#define ext_variables_modifiers_equal(modf1, modf2) \ + ( (modf1)->def == (modf2)->def ) +#define ext_variables_modifiers_equal_precedence(modf1, modf2) \ + ( (modf1)->def->precedence == (modf2)->def->precendence ) + +/* + * Modifier registry + */ + +void sieve_variables_modifier_register +(const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + const struct sieve_extension *ext, + const struct sieve_variables_modifier_def *smodf_def) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(var_ext, valdtr); + + sieve_validator_object_registry_add(ctx->modifiers, ext, &smodf_def->obj_def); +} + +bool ext_variables_modifier_exists +(const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + const char *identifier) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(var_ext, valdtr); + + return sieve_validator_object_registry_find(ctx->modifiers, identifier, NULL); +} + +const struct sieve_variables_modifier *ext_variables_modifier_create_instance +(const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + struct sieve_command *cmd, const char *identifier) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(var_ext, valdtr); + struct sieve_object object; + struct sieve_variables_modifier *modf; + pool_t pool; + + if ( !sieve_validator_object_registry_find + (ctx->modifiers, identifier, &object) ) + return NULL; + + pool = sieve_command_pool(cmd); + modf = p_new(pool, struct sieve_variables_modifier, 1); + modf->object = object; + modf->var_ext = var_ext; + modf->def = (const struct sieve_variables_modifier_def *) object.def; + + return modf; +} + +void ext_variables_register_core_modifiers +(const struct sieve_extension *ext, struct ext_variables_validator_context *ctx) +{ + unsigned int i; + + /* Register core modifiers*/ + for ( i = 0; i < ext_variables_core_modifiers_count; i++ ) { + sieve_validator_object_registry_add + (ctx->modifiers, ext, &(ext_variables_core_modifiers[i]->obj_def)); + } +} + +/* + * Core modifiers + */ + +/* Forward declarations */ + +static bool +mod_lower_modify(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result); +static bool +mod_upper_modify(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result); +static bool +mod_lowerfirst_modify(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result); +static bool +mod_upperfirst_modify(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result); +static bool +mod_length_modify(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result); +static bool +mod_quotewildcard_modify(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result); + +/* Modifier objects */ + +const struct sieve_variables_modifier_def lower_modifier = { + SIEVE_OBJECT("lower", &modifier_operand, EXT_VARIABLES_MODIFIER_LOWER), + 40, + mod_lower_modify +}; + +const struct sieve_variables_modifier_def upper_modifier = { + SIEVE_OBJECT("upper", &modifier_operand, EXT_VARIABLES_MODIFIER_UPPER), + 40, + mod_upper_modify +}; + +const struct sieve_variables_modifier_def lowerfirst_modifier = { + SIEVE_OBJECT + ("lowerfirst", &modifier_operand, EXT_VARIABLES_MODIFIER_LOWERFIRST), + 30, + mod_lowerfirst_modify +}; + +const struct sieve_variables_modifier_def upperfirst_modifier = { + SIEVE_OBJECT + ("upperfirst", &modifier_operand, EXT_VARIABLES_MODIFIER_UPPERFIRST), + 30, + mod_upperfirst_modify +}; + +const struct sieve_variables_modifier_def quotewildcard_modifier = { + SIEVE_OBJECT + ("quotewildcard", &modifier_operand, EXT_VARIABLES_MODIFIER_QUOTEWILDCARD), + 20, + mod_quotewildcard_modify +}; + +const struct sieve_variables_modifier_def length_modifier = { + SIEVE_OBJECT("length", &modifier_operand, EXT_VARIABLES_MODIFIER_LENGTH), + 10, + mod_length_modify +}; + +/* Modifier implementations */ + +static bool +mod_upperfirst_modify(const struct sieve_variables_modifier *modf ATTR_UNUSED, + string_t *in, string_t **result) +{ + char *content; + + if ( str_len(in) == 0 ) { + *result = in; + return TRUE; + } + + *result = t_str_new(str_len(in)); + str_append_str(*result, in); + + content = str_c_modifiable(*result); + content[0] = i_toupper(content[0]); + + return TRUE; +} + +static bool +mod_lowerfirst_modify(const struct sieve_variables_modifier *modf ATTR_UNUSED, + string_t *in, string_t **result) +{ + char *content; + + if ( str_len(in) == 0 ) { + *result = in; + return TRUE; + } + + *result = t_str_new(str_len(in)); + str_append_str(*result, in); + + content = str_c_modifiable(*result); + content[0] = i_tolower(content[0]); + + return TRUE; +} + +static bool +mod_upper_modify(const struct sieve_variables_modifier *modf ATTR_UNUSED, + string_t *in, string_t **result) +{ + char *content; + + if ( str_len(in) == 0 ) { + *result = in; + return TRUE; + } + + *result = t_str_new(str_len(in)); + str_append_str(*result, in); + + content = str_c_modifiable(*result); + (void)str_ucase(content); + + return TRUE; +} + +static bool +mod_lower_modify(const struct sieve_variables_modifier *modf ATTR_UNUSED, + string_t *in, string_t **result) +{ + char *content; + + if ( str_len(in) == 0 ) { + *result = in; + return TRUE; + } + + *result = t_str_new(str_len(in)); + str_append_str(*result, in); + + content = str_c_modifiable(*result); + (void)str_lcase(content); + + return TRUE; +} + +static bool +mod_length_modify(const struct sieve_variables_modifier *modf ATTR_UNUSED, + string_t *in, string_t **result) +{ + *result = t_str_new(64); + str_printfa(*result, "%llu", (unsigned long long) + uni_utf8_strlen_n(str_data(in), str_len(in))); + return TRUE; +} + +static bool +mod_quotewildcard_modify(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result) +{ + size_t max_var_size = + sieve_variables_get_max_variable_size(modf->var_ext); + const unsigned char *p, *poff, *pend; + size_t new_size; + + if ( str_len(in) == 0 ) { + /* empty string */ + *result = in; + return TRUE; + } + + /* allocate new string */ + new_size = str_len(in) + 16; + if (new_size > max_var_size) + new_size = max_var_size; + *result = t_str_new(new_size + 1); + + /* escape string */ + p = str_data(in); + pend = p + str_len(in); + poff = p; + while (p < pend) { + unsigned int n = uni_utf8_char_bytes((char)*p); + + if (n == 1 && (*p == '*' || *p == '?' || *p == '\\')) { + str_append_data(*result, poff, p - poff); + poff = p; + + if (str_len(*result) + 2 > max_var_size) + break; + + str_append_c(*result, '\\'); + } else if ((str_len(*result) + (p - poff) + n) > max_var_size) { + break; + } + if (p + n > pend) { + p = pend; + break; + } + p += n; + } + + str_append_data(*result, poff, p - poff); + + return TRUE; +} + +/* + * Modifier argument + */ + +/* [MODIFIER]: + * ":lower" / ":upper" / ":lowerfirst" / ":upperfirst" / + * ":quotewildcard" / ":length" + */ + +/* Forward declarations */ + +static bool tag_modifier_is_instance_of + (struct sieve_validator *valdtr, struct sieve_command *cmd, + const struct sieve_extension *ext, const char *identifier, void **context); + +/* Modifier tag object */ + +static const struct sieve_argument_def modifier_tag = { + .identifier = "MODIFIER", + .flags = SIEVE_ARGUMENT_FLAG_MULTIPLE, + .is_instance_of = tag_modifier_is_instance_of +}; + +/* Modifier tag implementation */ + +static bool tag_modifier_is_instance_of +(struct sieve_validator *valdtr, struct sieve_command *cmd, + const struct sieve_extension *ext, const char *identifier, void **data) +{ + const struct sieve_variables_modifier *modf; + + if ( data == NULL ) { + return ext_variables_modifier_exists(ext, valdtr, identifier); + } + + if ( (modf=ext_variables_modifier_create_instance + (ext, valdtr, cmd, identifier)) == NULL ) + return FALSE; + + *data = (void *) modf; + + return TRUE; +} + +/* Registration */ + +void sieve_variables_modifiers_link_tag +(struct sieve_validator *valdtr, const struct sieve_extension *var_ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag(valdtr, cmd_reg, var_ext, &modifier_tag, 0); +} + +/* Validation */ + +bool sieve_variables_modifiers_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd, + ARRAY_TYPE(sieve_variables_modifier) *modifiers) +{ + struct sieve_ast_argument *arg; + + arg = sieve_command_first_argument(cmd); + while ( arg != NULL && arg != cmd->first_positional ) { + const struct sieve_variables_modifier *modfs; + const struct sieve_variables_modifier *modf; + unsigned int i, modf_count; + bool inserted; + + if ( !sieve_argument_is(arg, modifier_tag) ) { + arg = sieve_ast_argument_next(arg); + continue; + } + modf = (const struct sieve_variables_modifier *) + arg->argument->data; + + inserted = FALSE; + modfs = array_get(modifiers, &modf_count); + for ( i = 0; i < modf_count && !inserted; i++ ) { + + if ( modfs[i].def->precedence == modf->def->precedence ) { + sieve_argument_validate_error(valdtr, arg, + "modifiers :%s and :%s specified for the set command conflict " + "having equal precedence", + modfs[i].def->obj_def.identifier, modf->def->obj_def.identifier); + return FALSE; + } + + if ( modfs[i].def->precedence < modf->def->precedence ) { + array_insert(modifiers, i, modf, 1); + inserted = TRUE; + } + } + + if ( !inserted ) + array_append(modifiers, modf, 1); + + /* Added to modifier list; + self-destruct to prevent implicit code generation */ + arg = sieve_ast_arguments_detach(arg, 1); + } + return TRUE; +} + +bool sieve_variables_modifiers_generate +(const struct sieve_codegen_env *cgenv, + ARRAY_TYPE(sieve_variables_modifier) *modifiers) +{ + struct sieve_binary_block *sblock = cgenv->sblock; + const struct sieve_variables_modifier *modfs; + unsigned int i, modf_count; + + sieve_binary_emit_byte(sblock, array_count(modifiers)); + + modfs = array_get(modifiers, &modf_count); + for ( i = 0; i < modf_count; i++ ) { + ext_variables_opr_modifier_emit(sblock, + modfs[i].object.ext, modfs[i].def); + } + return TRUE; +} + +/* + * Modifier coding + */ + +const struct sieve_operand_class sieve_variables_modifier_operand_class = + { "modifier" }; + +static const struct sieve_extension_objects core_modifiers = + SIEVE_VARIABLES_DEFINE_MODIFIERS(ext_variables_core_modifiers); + +const struct sieve_operand_def modifier_operand = { + .name = "modifier", + .ext_def = &variables_extension, + .code = EXT_VARIABLES_OPERAND_MODIFIER, + .class = &sieve_variables_modifier_operand_class, + .interface = &core_modifiers +}; + +bool sieve_variables_modifiers_code_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + unsigned int mdfs, i; + + /* Read the number of applied modifiers we need to read */ + if ( !sieve_binary_read_byte(denv->sblock, address, &mdfs) ) + return FALSE; + + /* Print all modifiers (sorted during code generation already) */ + for ( i = 0; i < mdfs; i++ ) { + if ( !ext_variables_opr_modifier_dump(denv, address) ) + return FALSE; + } + return TRUE; +} + +int sieve_variables_modifiers_code_read( + const struct sieve_runtime_env *renv, + const struct sieve_extension *var_ext, sieve_size_t *address, + ARRAY_TYPE(sieve_variables_modifier) *modifiers) +{ + unsigned int lprec, mdfs, i; + + if ( !sieve_binary_read_byte(renv->sblock, address, &mdfs) ) { + sieve_runtime_trace_error(renv, "invalid modifier count"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + t_array_init(modifiers, mdfs); + + lprec = (unsigned int)-1; + for ( i = 0; i < mdfs; i++ ) { + struct sieve_variables_modifier modf; + + if ( !ext_variables_opr_modifier_read(renv, var_ext, + address, &modf) ) + return SIEVE_EXEC_BIN_CORRUPT; + if ( modf.def != NULL ) { + if ( modf.def->precedence >= lprec ) { + sieve_runtime_trace_error(renv, + "unsorted modifier precedence"); + return SIEVE_EXEC_BIN_CORRUPT; + } + lprec = modf.def->precedence; + } + + array_append(modifiers, &modf, 1); + } + + return SIEVE_EXEC_OK; +} + +/* + * Modifier application + */ + +int sieve_variables_modifiers_apply +(const struct sieve_runtime_env *renv, + const struct sieve_extension *var_ext, + ARRAY_TYPE(sieve_variables_modifier) *modifiers, + string_t **value) +{ + const struct ext_variables_config *config = + ext_variables_get_config(var_ext); + const struct sieve_variables_modifier *modfs; + unsigned int i, modf_count; + + /* Hold value within limits */ + if ( str_len(*value) > config->max_variable_size ) { + /* assume variable originates from code, so copy it first */ + string_t *new_value = t_str_new(config->max_variable_size+3); + str_append_str(new_value, *value); + *value = new_value; + str_truncate_utf8(*value, config->max_variable_size); + } + + if ( !array_is_created(modifiers) ) + return SIEVE_EXEC_OK; + + modfs = array_get(modifiers, &modf_count); + if ( modf_count == 0 ) + return SIEVE_EXEC_OK; + + for ( i = 0; i < modf_count; i++ ) { + string_t *new_value; + const struct sieve_variables_modifier *modf = &modfs[i]; + + if ( modf->def != NULL && modf->def->modify != NULL ) { + if ( !modf->def->modify(modf, *value, &new_value) ) + return SIEVE_EXEC_FAILURE; + + *value = new_value; + if ( *value == NULL ) + return SIEVE_EXEC_FAILURE; + + sieve_runtime_trace_here + (renv, SIEVE_TRLVL_COMMANDS, + "modify :%s \"%s\" => \"%s\"", + sieve_variables_modifier_name(modf), + str_sanitize(str_c(*value), 256), + str_sanitize(str_c(new_value), 256)); + + /* Hold value within limits */ + if ( str_len(*value) > config->max_variable_size ) + str_truncate_utf8(*value, config->max_variable_size); + } + } + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-modifiers.h b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-modifiers.h new file mode 100644 index 0000000..50b4256 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-modifiers.h @@ -0,0 +1,66 @@ +#ifndef EXT_VARIABLES_MODIFIERS_H +#define EXT_VARIABLES_MODIFIERS_H + +#include "sieve-common.h" +#include "sieve-runtime-trace.h" + +#include "ext-variables-common.h" + +#define ext_variables_namespace_name(nspc) \ + (nspc)->object->def->name +#define ext_variables_namespaces_equal(nspc1, nspc2) \ + ( (nspc1)->def == (nspc2)->def )) + +/* + * Modifier registry + */ + +bool ext_variables_modifier_exists + (const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + const char *identifier); +const struct sieve_variables_modifier *ext_variables_modifier_create_instance + (const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + struct sieve_command *cmd, const char *identifier); + +void ext_variables_register_core_modifiers + (const struct sieve_extension *var_ext, + struct ext_variables_validator_context *ctx); + +/* + * Modifier operand + */ + +extern const struct sieve_operand_def modifier_operand; + +static inline void ext_variables_opr_modifier_emit +(struct sieve_binary_block *sblock, const struct sieve_extension *ext, + const struct sieve_variables_modifier_def *modf_def) +{ + sieve_opr_object_emit(sblock, ext, &modf_def->obj_def); +} + +static inline bool +ext_variables_opr_modifier_read(const struct sieve_runtime_env *renv, + const struct sieve_extension *var_ext, + sieve_size_t *address, + struct sieve_variables_modifier *modf) +{ + if ( !sieve_opr_object_read + (renv, &sieve_variables_modifier_operand_class, address, &modf->object) ) { + sieve_runtime_trace_error(renv, "invalid modifier operand"); + return FALSE; + } + + modf->def = (const struct sieve_variables_modifier_def *) modf->object.def; + modf->var_ext = var_ext; + return TRUE; +} + +static inline bool ext_variables_opr_modifier_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + return sieve_opr_object_dump + (denv, &sieve_variables_modifier_operand_class, address, NULL); +} + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-name.c b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-name.c new file mode 100644 index 0000000..fac0b71 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-name.c @@ -0,0 +1,110 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "array.h" + +#include "sieve-common.h" + +#include "ext-variables-common.h" +#include "ext-variables-limits.h" +#include "ext-variables-name.h" + +#include <ctype.h> + +bool sieve_variable_identifier_is_valid(const char *identifier) +{ + const char *p = identifier; + size_t plen = strlen(identifier); + const char *pend; + + if ( plen == 0 || plen >= EXT_VARIABLES_MAX_VARIABLE_NAME_LEN ) + return FALSE; + + pend = PTR_OFFSET(identifier, plen); + + if ( *p == '_' || i_isalpha(*p) ) { + p++; + + while ( p < pend && (*p == '_' || i_isalnum(*p)) ) { + p++; + } + } + + return ( p == pend ); +} + +int ext_variable_name_parse +(ARRAY_TYPE(sieve_variable_name) *vname, const char **str, const char *strend) +{ + const char *p = *str; + + array_clear(vname); + + while ( p < strend ) { + struct sieve_variable_name *cur_element; + string_t *cur_ident; + + /* Acquire current position in the array */ + + if ( array_count(vname) >= EXT_VARIABLES_MAX_NAMESPACE_ELEMENTS ) + return -1; + + cur_element = array_append_space(vname); + cur_ident = cur_element->identifier = t_str_new(32); + + /* Parse element */ + + /* Identifier */ + if ( *p == '_' || i_isalpha(*p) ) { + cur_element->num_variable = -1; + str_truncate(cur_ident, 0); + str_append_c(cur_ident, *p); + p++; + + while ( p < strend && (*p == '_' || i_isalnum(*p)) ) { + if ( str_len(cur_ident) >= EXT_VARIABLES_MAX_VARIABLE_NAME_LEN ) + return -1; + str_append_c(cur_ident, *p); + p++; + } + + /* Num-variable */ + } else if ( i_isdigit(*p) ) { + cur_element->num_variable = *p - '0'; + p++; + + while ( p < strend && i_isdigit(*p) ) { + cur_element->num_variable = cur_element->num_variable*10 + (*p - '0'); + p++; + } + + /* If a num-variable is first, no more elements can follow because no + * namespace is specified. + */ + if ( array_count(vname) == 1 ) { + *str = p; + return 1; + } + } else { + *str = p; + return -1; + } + + /* Check whether next name element is present */ + if ( p < strend && *p == '.' ) { + p++; + + /* It may not be empty */ + if ( p >= strend ) + return -1; + } else + break; + } + + *str = p; + return array_count(vname); +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-name.h b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-name.h new file mode 100644 index 0000000..289a978 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-name.h @@ -0,0 +1,43 @@ +#ifndef EXT_VARIABLES_NAME_H +#define EXT_VARIABLES_NAME_H + +/* Variable Substitution + * --------------------- + * + * The variable strings are preprocessed into an AST list consisting of variable + * substitutions and constant parts of the string. The variables to which + * the substitutions link are looked up and their index in their scope storage + * is what is added to the list and eventually emitted as byte code. So, in + * bytecode a variable string will look as a series of substrings interrupted by + * integer operands that refer to variables. During execution, the strings and + * the looked-up variables are concatenated to obtain the desired result. The + * the variable references are simple indexes into an array of variables, so + * looking these up during execution is a trivial process. + * + * However (RFC 5229): + * Tests or actions in future extensions may need to access the + * unexpanded version of the string argument and, e.g., do the expansion + * after setting variables in its namespace. The design of the + * implementation should allow this. + * + * Various options exist to provide this feature. If the extension is entirely + * namespace-based there is actually not very much of a problem. The variable + * list can easily be extended with new argument-types that refer to a variable + * identifier instead of an index in the variable's storage. + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-common.h" + +#include "ext-variables-common.h" + +/* + * Variable name parsing + */ + +int ext_variable_name_parse + (ARRAY_TYPE(sieve_variable_name) *vname, const char **str, const char *strend); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-namespaces.c b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-namespaces.c new file mode 100644 index 0000000..4df62e2 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-namespaces.c @@ -0,0 +1,236 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-dump.h" + +#include "ext-variables-common.h" +#include "ext-variables-namespaces.h" + +#include <ctype.h> + +/* + * Namespace registry + */ + +void sieve_variables_namespace_register +(const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + const struct sieve_extension *ext, + const struct sieve_variables_namespace_def *nspc_def) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(var_ext, valdtr); + + sieve_validator_object_registry_add(ctx->namespaces, ext, &nspc_def->obj_def); +} + +bool ext_variables_namespace_exists +(const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + const char *identifier) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(var_ext, valdtr); + + return sieve_validator_object_registry_find + (ctx->namespaces, identifier, NULL); +} + +const struct sieve_variables_namespace *ext_variables_namespace_create_instance +(const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + struct sieve_command *cmd, const char *identifier) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(var_ext, valdtr); + struct sieve_object object; + struct sieve_variables_namespace *nspc; + pool_t pool; + + if ( !sieve_validator_object_registry_find + (ctx->namespaces, identifier, &object) ) + return NULL; + + pool = sieve_command_pool(cmd); + nspc = p_new(pool, struct sieve_variables_namespace, 1); + nspc->object = object; + nspc->def = (const struct sieve_variables_namespace_def *) object.def; + + return nspc; +} + +/* + * Namespace variable argument + */ + +struct arg_namespace_variable { + const struct sieve_variables_namespace *namespace; + + void *data; +}; + +static bool arg_namespace_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *context ATTR_UNUSED); + +const struct sieve_argument_def namespace_argument = { + .identifier = "@namespace", + .generate = arg_namespace_generate +}; + +bool ext_variables_namespace_argument_activate +(const struct sieve_extension *this_ext, struct sieve_validator *valdtr, + struct sieve_ast_argument *arg, struct sieve_command *cmd, + ARRAY_TYPE(sieve_variable_name) *var_name, bool assignment) +{ + pool_t pool = sieve_command_pool(cmd); + struct sieve_ast *ast = arg->ast; + const struct sieve_variables_namespace *nspc; + struct arg_namespace_variable *var; + const struct sieve_variable_name *name_element = array_idx(var_name, 0); + void *var_data = NULL; + + nspc = ext_variables_namespace_create_instance + (this_ext, valdtr, cmd, str_c(name_element->identifier)); + if ( nspc == NULL ) { + sieve_argument_validate_error(valdtr, arg, + "referring to variable in unknown namespace '%s'", + str_c(name_element->identifier)); + return FALSE; + } + + if ( nspc->def != NULL && nspc->def->validate != NULL && + !nspc->def->validate + (valdtr, nspc, arg, cmd, var_name, &var_data, assignment) ) { + return FALSE; + } + + var = p_new(pool, struct arg_namespace_variable, 1); + var->namespace = nspc; + var->data = var_data; + + arg->argument = sieve_argument_create(ast, &namespace_argument, this_ext, 0); + arg->argument->data = (void *) var; + + return TRUE; +} + +struct sieve_ast_argument *ext_variables_namespace_argument_create +(const struct sieve_extension *this_ext, + struct sieve_validator *valdtr, struct sieve_ast_argument *parent_arg, + struct sieve_command *cmd, ARRAY_TYPE(sieve_variable_name) *var_name) +{ + struct sieve_ast *ast = parent_arg->ast; + struct sieve_ast_argument *new_arg; + + new_arg = sieve_ast_argument_create(ast, sieve_ast_argument_line(parent_arg)); + new_arg->type = SAAT_STRING; + + if ( !ext_variables_namespace_argument_activate + (this_ext, valdtr, new_arg, cmd, var_name, FALSE) ) + return NULL; + + return new_arg; +} + +static bool arg_namespace_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd) +{ + struct sieve_argument *argument = arg->argument; + struct arg_namespace_variable *var = + (struct arg_namespace_variable *) argument->data; + const struct sieve_variables_namespace *nspc = var->namespace; + + if ( nspc->def != NULL && nspc->def->generate != NULL ) + return nspc->def->generate(cgenv, nspc, arg, cmd, var->data); + + return TRUE; +} + +/* + * Namespace variable operands + */ + +const struct sieve_operand_class sieve_variables_namespace_operand_class = + { "variable-namespace" }; + +static bool opr_namespace_variable_dump + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); +static int opr_namespace_variable_read + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r); + +static const struct sieve_opr_string_interface namespace_variable_interface = { + opr_namespace_variable_dump, + opr_namespace_variable_read +}; + +const struct sieve_operand_def namespace_variable_operand = { + .name = "namespace", + .ext_def = &variables_extension, + .code = EXT_VARIABLES_OPERAND_NAMESPACE_VARIABLE, + .class = &string_class, + .interface = &namespace_variable_interface +}; + +void sieve_variables_opr_namespace_variable_emit +(struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, + const struct sieve_extension *ext, + const struct sieve_variables_namespace_def *nspc_def) +{ + i_assert( sieve_extension_is(var_ext, variables_extension) ); + sieve_operand_emit(sblock, var_ext, &namespace_variable_operand); + sieve_opr_object_emit(sblock, ext, &nspc_def->obj_def); +} + +static bool opr_namespace_variable_dump +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) +{ + struct sieve_variables_namespace nspc; + struct sieve_operand nsoprnd; + + if ( !sieve_operand_read(denv->sblock, address, NULL, &nsoprnd) ) { + return FALSE; + } + + if ( !sieve_opr_object_read_data + (denv->sblock, &nsoprnd, &sieve_variables_namespace_operand_class, address, + &nspc.object) ) { + return FALSE; + } + + nspc.def = (const struct sieve_variables_namespace_def *) nspc.object.def; + + if ( nspc.def == NULL || nspc.def->dump_variable == NULL ) + return FALSE; + + return nspc.def->dump_variable(denv, &nspc, oprnd, address); +} + +static int opr_namespace_variable_read +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r) +{ + struct sieve_variables_namespace nspc; + + if ( !sieve_opr_object_read + (renv, &sieve_variables_namespace_operand_class, address, &nspc.object) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "variable namespace operand corrupt: failed to read"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + nspc.def = (const struct sieve_variables_namespace_def *) nspc.object.def; + + if ( nspc.def == NULL || nspc.def->read_variable == NULL ) + return SIEVE_EXEC_FAILURE; + + return nspc.def->read_variable(renv, &nspc, oprnd, address, str_r); +} + + + diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-namespaces.h b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-namespaces.h new file mode 100644 index 0000000..a687582 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-namespaces.h @@ -0,0 +1,43 @@ +#ifndef EXT_VARIABLES_NAMESPACES_H +#define EXT_VARIABLES_NAMESPACES_H + +#include "sieve-common.h" + +#include "ext-variables-common.h" +#include "sieve-ext-variables.h" + +/* + * Namespace registry + */ + +bool ext_variables_namespace_exists + (const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + const char *identifier); +const struct sieve_variables_namespace *ext_variables_namespace_create_instance + (const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + struct sieve_command *cmd, const char *identifier); + +void ext_variables_register_core_namespaces + (const struct sieve_extension *var_ext, + struct ext_variables_validator_context *ctx); + +/* + * Namespace argument + */ + +struct sieve_ast_argument *ext_variables_namespace_argument_create + (const struct sieve_extension *this_ext, + struct sieve_validator *valdtr, struct sieve_ast_argument *parent_arg, + struct sieve_command *cmd, ARRAY_TYPE(sieve_variable_name) *var_name); +bool ext_variables_namespace_argument_activate + (const struct sieve_extension *this_ext, struct sieve_validator *valdtr, + struct sieve_ast_argument *arg, struct sieve_command *cmd, + ARRAY_TYPE(sieve_variable_name) *var_name, bool assignment); + +/* + * Namespace operand + */ + +extern const struct sieve_operand_def namespace_variable_operand; + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-operands.c b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-operands.c new file mode 100644 index 0000000..359f3bf --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-operands.c @@ -0,0 +1,279 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "hash.h" +#include "str.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-ast.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-match-types.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-dump.h" +#include "sieve-interpreter.h" + +#include "ext-variables-common.h" +#include "ext-variables-limits.h" +#include "ext-variables-name.h" +#include "ext-variables-dump.h" +#include "ext-variables-operands.h" + +/* + * Variable operand + */ + +static bool opr_variable_dump + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); +static int opr_variable_read_value + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r); + +const struct sieve_opr_string_interface variable_interface = { + opr_variable_dump, + opr_variable_read_value +}; + +const struct sieve_operand_def variable_operand = { + .name = "variable", + .ext_def = &variables_extension, + .code = EXT_VARIABLES_OPERAND_VARIABLE, + .class = &string_class, + .interface = &variable_interface +}; + +void sieve_variables_opr_variable_emit +(struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, + struct sieve_variable *var) +{ + i_assert( sieve_extension_is(var_ext, variables_extension) ); + + if ( var->ext == NULL ) { + /* Default variable storage */ + (void) sieve_operand_emit(sblock, var_ext, &variable_operand); + (void) sieve_binary_emit_byte(sblock, 0); /* Default */ + (void) sieve_binary_emit_unsigned(sblock, var->index); + return; + } + + (void) sieve_operand_emit(sblock, var_ext, &variable_operand); + (void) sieve_binary_emit_extension(sblock, var->ext, 1); /* Extension */ + (void) sieve_binary_emit_unsigned(sblock, var->index); +} + +static bool opr_variable_dump +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) +{ + const struct sieve_extension *this_ext = oprnd->ext; + unsigned int index = 0; + const struct sieve_extension *ext; + unsigned int code = 1; /* Initially set to offset value */ + const char *identifier; + + if ( !sieve_binary_read_extension(denv->sblock, address, &code, &ext) ) + return FALSE; + + if ( !sieve_binary_read_unsigned(denv->sblock, address, &index) ) + return FALSE; + + identifier = ext_variables_dump_get_identifier(this_ext, denv, ext, index); + identifier = identifier == NULL ? "??" : identifier; + + if ( oprnd->field_name != NULL ) + sieve_code_dumpf(denv, "%s: VAR[%s] ${%s}", + oprnd->field_name, sieve_ext_variables_get_varid(ext, index), identifier); + else + sieve_code_dumpf(denv, "VAR[%s] ${%s}", + sieve_ext_variables_get_varid(ext, index), identifier); + + return TRUE; +} + +static int opr_variable_read_value +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r) +{ + const struct sieve_extension *this_ext = oprnd->ext; + const struct sieve_extension *ext; + unsigned int code = 1; /* Initially set to offset value */ + struct sieve_variable_storage *storage; + unsigned int index = 0; + + if ( !sieve_binary_read_extension(renv->sblock, address, &code, &ext) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "variable operand corrupt: invalid extension byte"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + storage = sieve_ext_variables_runtime_get_storage + (this_ext, renv, ext); + if ( storage == NULL ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "variable operand corrupt: extension has no storage"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( sieve_binary_read_unsigned(renv->sblock, address, &index) ) { + /* Parameter str can be NULL if we are requested to only skip and not + * actually read the argument. + */ + if ( str_r != NULL ) { + if ( !sieve_variable_get(storage, index, str_r) ) + return SIEVE_EXEC_FAILURE; + + if ( *str_r == NULL ) *str_r = t_str_new(0); + } + + return SIEVE_EXEC_OK; + } + + sieve_runtime_trace_operand_error(renv, oprnd, + "variable operand corrupt: invalid variable index"); + return SIEVE_EXEC_BIN_CORRUPT; +} + +int sieve_variable_operand_read_data +(const struct sieve_runtime_env *renv, struct sieve_operand *oprnd, + sieve_size_t *address, const char *field_name, + struct sieve_variable_storage **storage_r, unsigned int *var_index_r) +{ + const struct sieve_extension *ext; + unsigned int code = 1; /* Initially set to offset value */ + unsigned int idx = 0; + + oprnd->field_name = field_name; + + if ( !sieve_operand_is_variable(oprnd) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "expected variable operand but found %s", sieve_operand_name(oprnd)); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( !sieve_binary_read_extension(renv->sblock, address, &code, &ext) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "variable operand corrupt: invalid extension byte"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + *storage_r = sieve_ext_variables_runtime_get_storage + (oprnd->ext, renv, ext); + if ( *storage_r == NULL ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "variable operand corrupt: extension has no storage"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( !sieve_binary_read_unsigned(renv->sblock, address, &idx) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "variable operand corrupt: invalid variable index"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + *var_index_r = idx; + return SIEVE_EXEC_OK; +} + +int sieve_variable_operand_read +(const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, struct sieve_variable_storage **storage_r, + unsigned int *var_index_r) +{ + struct sieve_operand operand; + int ret; + + if ( (ret=sieve_operand_runtime_read(renv, address, field_name, &operand)) + <= 0) + return ret; + + return sieve_variable_operand_read_data + (renv, &operand, address, field_name, storage_r, var_index_r); +} + +/* + * Match value operand + */ + +static bool opr_match_value_dump + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); +static int opr_match_value_read + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r); + +const struct sieve_opr_string_interface match_value_interface = { + opr_match_value_dump, + opr_match_value_read +}; + +const struct sieve_operand_def match_value_operand = { + .name = "match-value", + .ext_def = &variables_extension, + .code = EXT_VARIABLES_OPERAND_MATCH_VALUE, + .class = &string_class, + .interface = &match_value_interface +}; + +void sieve_variables_opr_match_value_emit +(struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, + unsigned int index) +{ + i_assert( sieve_extension_is(var_ext, variables_extension) ); + (void) sieve_operand_emit(sblock, var_ext, &match_value_operand); + (void) sieve_binary_emit_unsigned(sblock, index); +} + +static bool opr_match_value_dump +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) +{ + unsigned int index = 0; + + if (sieve_binary_read_unsigned(denv->sblock, address, &index) ) { + if ( oprnd->field_name != NULL ) + sieve_code_dumpf + (denv, "%s: MATCHVAL %lu", oprnd->field_name, (unsigned long) index); + else + sieve_code_dumpf(denv, "MATCHVAL %lu", (unsigned long) index); + + return TRUE; + } + + return FALSE; +} + +static int opr_match_value_read +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r) +{ + const struct sieve_extension *this_ext = oprnd->ext; + const struct ext_variables_config *config = + ext_variables_get_config(this_ext); + unsigned int index = 0; + + if ( sieve_binary_read_unsigned(renv->sblock, address, &index) ) { + /* Parameter str can be NULL if we are requested to only skip and not + * actually read the argument. + */ + if ( str_r != NULL ) { + sieve_match_values_get(renv, index, str_r); + + if ( *str_r == NULL ) + *str_r = t_str_new(0); + else if ( str_len(*str_r) > config->max_variable_size ) + str_truncate_utf8(*str_r, config->max_variable_size); + } + + return SIEVE_EXEC_OK; + } + + sieve_runtime_trace_operand_error(renv, oprnd, + "match value operand corrupt: invalid index data"); + return SIEVE_EXEC_BIN_CORRUPT; +} diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-operands.h b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-operands.h new file mode 100644 index 0000000..64a7781 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-operands.h @@ -0,0 +1,37 @@ +#ifndef EXT_VARIABLES_OPERANDS_H +#define EXT_VARIABLES_OPERANDS_H + +#include "lib.h" +#include "hash.h" +#include "str.h" +#include "array.h" + +#include "sieve-common.h" +#include "ext-variables-common.h" + +/* + * Variable operand + */ + +extern const struct sieve_operand_def variable_operand; + +bool ext_variables_opr_variable_read + (const struct sieve_runtime_env *renv, sieve_size_t *address, + struct sieve_variable_storage **storage, unsigned int *var_index); + +/* + * Match value operand + */ + +extern const struct sieve_operand_def match_value_operand; + +/* + * Variable string operand + */ + +void ext_variables_opr_variable_string_emit + (struct sieve_binary *sbin, unsigned int elements); + + +#endif + diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables.c b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables.c new file mode 100644 index 0000000..6bdef58 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables.c @@ -0,0 +1,84 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension variables + * ------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5229 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "str.h" +#include "unichar.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" + +#include "sieve-validator.h" + +#include "ext-variables-common.h" +#include "ext-variables-arguments.h" +#include "ext-variables-operands.h" +#include "ext-variables-namespaces.h" +#include "ext-variables-modifiers.h" +#include "ext-variables-dump.h" + +/* + * Operations + */ + +const struct sieve_operation_def *ext_variables_operations[] = { + &cmd_set_operation, + &tst_string_operation +}; + +/* + * Operands + */ + +const struct sieve_operand_def *ext_variables_operands[] = { + &variable_operand, + &match_value_operand, + &namespace_variable_operand, + &modifier_operand +}; + +/* + * Extension + */ + +static bool ext_variables_validator_load + (const struct sieve_extension *ext, struct sieve_validator *validator); + +const struct sieve_extension_def variables_extension = { + .name = "variables", + .load = ext_variables_load, + .unload = ext_variables_unload, + .validator_load = ext_variables_validator_load, + .generator_load = ext_variables_generator_load, + .interpreter_load = ext_variables_interpreter_load, + .code_dump = ext_variables_code_dump, + SIEVE_EXT_DEFINE_OPERATIONS(ext_variables_operations), + SIEVE_EXT_DEFINE_OPERANDS(ext_variables_operands) +}; + +static bool ext_variables_validator_load +(const struct sieve_extension *ext, struct sieve_validator *validator) +{ + sieve_validator_argument_override + (validator, SAT_VAR_STRING, ext, &variable_string_argument); + + sieve_validator_register_command(validator, ext, &cmd_set); + sieve_validator_register_command(validator, ext, &tst_string); + + ext_variables_validator_initialize(ext, validator); + + return TRUE; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/variables/sieve-ext-variables.h b/pigeonhole/src/lib-sieve/plugins/variables/sieve-ext-variables.h new file mode 100644 index 0000000..ce0d0bc --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/sieve-ext-variables.h @@ -0,0 +1,364 @@ +#ifndef SIEVE_EXT_VARIABLES_H +#define SIEVE_EXT_VARIABLES_H + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-objects.h" +#include "sieve-code.h" + +/* Public interface for other extensions to use + */ + +/* + * Limits + */ + +unsigned int +sieve_variables_get_max_scope_size(const struct sieve_extension *var_ext); +size_t +sieve_variables_get_max_variable_size(const struct sieve_extension *var_ext); + +/* + * Variable extension + */ + +/* FIXME: this is not suitable for future plugin support */ + +extern const struct sieve_extension_def variables_extension; + +static inline const struct sieve_extension *sieve_ext_variables_get_extension +(struct sieve_instance *svinst) +{ + return sieve_extension_register(svinst, &variables_extension, FALSE); +} + +/* + * Variable name + */ + +struct sieve_variable_name { + string_t *identifier; + int num_variable; +}; + +ARRAY_DEFINE_TYPE(sieve_variable_name, struct sieve_variable_name); + +bool sieve_variable_identifier_is_valid(const char *identifier); + +/* + * Variable scope + */ + +struct sieve_variable { + const char *identifier; + unsigned int index; + + const struct sieve_extension *ext; + void *context; +}; + +struct sieve_variable_scope; + +struct sieve_variable_scope *sieve_variable_scope_create + (struct sieve_instance *svinst, const struct sieve_extension *var_ext, + const struct sieve_extension *ext); +void sieve_variable_scope_ref + (struct sieve_variable_scope *scope); +void sieve_variable_scope_unref + (struct sieve_variable_scope **scope); +pool_t sieve_variable_scope_pool + (struct sieve_variable_scope *scope); + +struct sieve_variable *sieve_variable_scope_declare + (struct sieve_variable_scope *scope, const char *identifier); +struct sieve_variable *sieve_variable_scope_import + (struct sieve_variable_scope *scope, struct sieve_variable *var); +struct sieve_variable *sieve_variable_scope_get_variable + (struct sieve_variable_scope *scope, const char *identifier); +struct sieve_variable *sieve_variable_scope_get_indexed + (struct sieve_variable_scope *scope, unsigned int index); + +/* Binary */ + +struct sieve_variable_scope_binary *sieve_variable_scope_binary_create + (struct sieve_variable_scope *scope); + +void sieve_variable_scope_binary_ref + (struct sieve_variable_scope_binary *scpbin); +void sieve_variable_scope_binary_unref + (struct sieve_variable_scope_binary **scpbin); + +struct sieve_variable_scope *sieve_variable_scope_binary_dump + (struct sieve_instance *svinst, + const struct sieve_extension *var_ext, + const struct sieve_extension *ext, + const struct sieve_dumptime_env *denv, sieve_size_t *address); +struct sieve_variable_scope_binary *sieve_variable_scope_binary_read + (struct sieve_instance *svinst, + const struct sieve_extension *var_ext, + const struct sieve_extension *ext, + struct sieve_binary_block *sblock, sieve_size_t *address); + +struct sieve_variable_scope *sieve_variable_scope_binary_get + (struct sieve_variable_scope_binary *scpbin); +unsigned int sieve_variable_scope_binary_get_size + (struct sieve_variable_scope_binary *scpbin); + +/* + * Variable namespaces + */ + +struct sieve_variables_namespace; + +struct sieve_variables_namespace_def { + struct sieve_object_def obj_def; + + bool (*validate) + (struct sieve_validator *valdtr, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg, struct sieve_command *cmd, + ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, + bool assignment); + bool (*generate) + (const struct sieve_codegen_env *cgenv, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg, struct sieve_command *cmd, + void *var_data); + + bool (*dump_variable) + (const struct sieve_dumptime_env *denv, + const struct sieve_variables_namespace *nspc, + const struct sieve_operand *oprnd, sieve_size_t *address); + int (*read_variable) + (const struct sieve_runtime_env *renv, + const struct sieve_variables_namespace *nspc, + const struct sieve_operand *oprnd, sieve_size_t *address, string_t **str); +}; + +#define SIEVE_VARIABLES_DEFINE_NAMESPACE(OP) SIEVE_EXT_DEFINE_OBJECT(OP) +#define SIEVE_VARIABLES_DEFINE_NAMESPACES(OPS) SIEVE_EXT_DEFINE_OBJECTS(OPS) + +struct sieve_variables_namespace { + struct sieve_object object; + + const struct sieve_variables_namespace_def *def; +}; + +void sieve_variables_namespace_register +(const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + const struct sieve_extension *ext, + const struct sieve_variables_namespace_def *nspc_def); + +extern const struct sieve_operand_class sieve_variables_namespace_operand_class; + +void sieve_variables_opr_namespace_variable_emit + (struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, + const struct sieve_extension *ext, + const struct sieve_variables_namespace_def *nspc_def); + +/* Iteration over all declared variables */ + +struct sieve_variable_scope_iter; + +struct sieve_variable_scope_iter *sieve_variable_scope_iterate_init + (struct sieve_variable_scope *scope); +bool sieve_variable_scope_iterate + (struct sieve_variable_scope_iter *iter, struct sieve_variable **var_r); +void sieve_variable_scope_iterate_deinit + (struct sieve_variable_scope_iter **iter); + +/* Statistics */ + +unsigned int sieve_variable_scope_declarations + (struct sieve_variable_scope *scope); +unsigned int sieve_variable_scope_size + (struct sieve_variable_scope *scope); + +/* Get all native variables */ + +struct sieve_variable * const *sieve_variable_scope_get_variables + (struct sieve_variable_scope *scope, unsigned int *size_r); + +/* + * Variable storage + */ + +struct sieve_variable_storage; + +struct sieve_variable_storage *sieve_variable_storage_create + (const struct sieve_extension *var_ext, pool_t pool, + struct sieve_variable_scope_binary *scpbin); +bool sieve_variable_get + (struct sieve_variable_storage *storage, unsigned int index, + string_t **value); +bool sieve_variable_get_modifiable + (struct sieve_variable_storage *storage, unsigned int index, + string_t **value); +bool sieve_variable_assign + (struct sieve_variable_storage *storage, unsigned int index, + const string_t *value); +bool sieve_variable_assign_cstr + (struct sieve_variable_storage *storage, unsigned int index, + const char *value); +bool sieve_variable_get_identifier + (struct sieve_variable_storage *storage, unsigned int index, + const char **identifier); +const char *sieve_variable_get_varid + (struct sieve_variable_storage *storage, unsigned int index); + +/* + * Variables access + */ + +bool sieve_ext_variables_is_active + (const struct sieve_extension *var_ext, struct sieve_validator *valdtr); + +struct sieve_variable_scope *sieve_ext_variables_get_local_scope + (const struct sieve_extension *var_ext, struct sieve_validator *valdtr); + +/* Runtime */ + +static inline const char *sieve_ext_variables_get_varid +(const struct sieve_extension *ext, unsigned int index) +{ + if ( ext == NULL ) + return t_strdup_printf("%ld", (long) index); + + return t_strdup_printf("%s:%ld", sieve_extension_name(ext), (long) index); +} + +struct sieve_variable_storage *sieve_ext_variables_runtime_get_storage + (const struct sieve_extension *var_ext, const struct sieve_runtime_env *renv, + const struct sieve_extension *ext); +void sieve_ext_variables_runtime_set_storage + (const struct sieve_extension *var_ext, const struct sieve_runtime_env *renv, + const struct sieve_extension *ext, struct sieve_variable_storage *storage); + +const char *sieve_ext_variables_runtime_get_identifier +(const struct sieve_extension *var_ext, const struct sieve_runtime_env *renv, + const struct sieve_extension *ext, unsigned int index); + +/* + * Variable arguments + */ + +bool sieve_variable_argument_activate + (const struct sieve_extension *var_ext, + const struct sieve_extension *this_ext, + struct sieve_validator *valdtr, struct sieve_command *cmd, + struct sieve_ast_argument *arg, bool assignment); + +/* + * Variable operands + */ + +extern const struct sieve_operand_def variable_operand; + +void sieve_variables_opr_variable_emit + (struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, + struct sieve_variable *var); +void sieve_variables_opr_match_value_emit + (struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, + unsigned int index); + +int sieve_variable_operand_read_data + (const struct sieve_runtime_env *renv, struct sieve_operand *operand, + sieve_size_t *address, const char *field_name, + struct sieve_variable_storage **storage_r, unsigned int *var_index_r); +int sieve_variable_operand_read + (const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, struct sieve_variable_storage **storage_r, + unsigned int *var_index_r); + +static inline bool sieve_operand_is_variable +(const struct sieve_operand *operand) +{ + return ( operand != NULL && operand->def != NULL && + operand->def == &variable_operand ); +} + +/* + * Modifiers + */ + +/* Definition */ + +struct sieve_variables_modifier; + +struct sieve_variables_modifier_def { + struct sieve_object_def obj_def; + + unsigned int precedence; + + bool (*modify)(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result); +}; + +struct sieve_variables_modifier { + struct sieve_object object; + const struct sieve_extension *var_ext; + + const struct sieve_variables_modifier_def *def; +}; + +#define SIEVE_VARIABLES_DEFINE_MODIFIER(OP) SIEVE_EXT_DEFINE_OBJECT(OP) +#define SIEVE_VARIABLES_DEFINE_MODIFIERS(OPS) SIEVE_EXT_DEFINE_OBJECTS(OPS) + +#define sieve_variables_modifier_name(smodf) \ + ( (smodf)->object.def->identifier ) + +ARRAY_DEFINE_TYPE(sieve_variables_modifier, + struct sieve_variables_modifier); + +/* Registry */ + +void sieve_variables_modifier_register + (const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + const struct sieve_extension *ext, + const struct sieve_variables_modifier_def *smodf); + +/* Tagged argument */ + +void sieve_variables_modifiers_link_tag + (struct sieve_validator *valdtr, const struct sieve_extension *var_ext, + struct sieve_command_registration *cmd_reg); + +bool sieve_variables_modifiers_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd, + ARRAY_TYPE(sieve_variables_modifier) *modifiers); + +bool sieve_variables_modifiers_generate + (const struct sieve_codegen_env *cgenv, + ARRAY_TYPE(sieve_variables_modifier) *modifiers); + +/* Coding */ + +extern const struct sieve_operand_class + sieve_variables_modifier_operand_class; + +bool sieve_variables_modifiers_code_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +int sieve_variables_modifiers_code_read( + const struct sieve_runtime_env *renv, + const struct sieve_extension *var_ext, sieve_size_t *address, + ARRAY_TYPE(sieve_variables_modifier) *modifiers); + +/* Application */ + +int sieve_variables_modifiers_apply +(const struct sieve_runtime_env *renv, + const struct sieve_extension *var_ext, + ARRAY_TYPE(sieve_variables_modifier) *modifiers, + string_t **value); + +/* + * Code dumping + */ + +void sieve_ext_variables_dump_set_scope +(const struct sieve_extension *var_ext, const struct sieve_dumptime_env *denv, + const struct sieve_extension *ext, struct sieve_variable_scope *scope); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/variables/tst-string.c b/pigeonhole/src/lib-sieve/plugins/variables/tst-string.c new file mode 100644 index 0000000..91b0b82 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/tst-string.c @@ -0,0 +1,271 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-variables-common.h" + +/* + * String test + * + * Syntax: + * string [COMPARATOR] [MATCH-TYPE] + * <source: string-list> <key-list: string-list> + */ + +static bool tst_string_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool tst_string_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_string_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def tst_string = { + .identifier = "string", + .type = SCT_TEST, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_string_registered, + .validate = tst_string_validate, + .generate = tst_string_generate +}; + +/* + * String operation + */ + +static bool tst_string_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_string_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def tst_string_operation = { + .mnemonic = "STRING", + .ext_def = &variables_extension, + .code = EXT_VARIABLES_OPERATION_STRING, + .dump = tst_string_operation_dump, + .execute = tst_string_operation_execute +}; + +/* + * Optional arguments + */ + +enum tst_string_optional { + OPT_END, + OPT_COMPARATOR, + OPT_MATCH_TYPE +}; + +/* + * Test registration + */ + +static bool tst_string_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag(valdtr, cmd_reg, OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, OPT_MATCH_TYPE); + + return TRUE; +} + +/* + * Test validation + */ + +static bool tst_string_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + const struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_octet_comparator); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "source", 1, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + arg = sieve_ast_argument_next(arg); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "key list", 2, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate + (valdtr, tst, arg, &mcht_default, &cmp_default); +} + +/* + * Test generation + */ + +static bool tst_string_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &tst_string_operation); + + /* Generate arguments */ + if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) + return FALSE; + + return TRUE; +} + +/* + * Code dump + */ + +static bool tst_string_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "STRING-TEST"); + sieve_code_descend(denv); + + /* Optional operands */ + if ( sieve_match_opr_optional_dump(denv, address, NULL) != 0 ) + return FALSE; + + return + sieve_opr_stringlist_dump(denv, address, "source") && + sieve_opr_stringlist_dump(denv, address, "key list"); +} + +/* + * Code execution + */ + +static int tst_string_stringlist_next_item + (struct sieve_stringlist *_strlist, string_t **str_r); +static void tst_string_stringlist_reset + (struct sieve_stringlist *_strlist); +static int tst_string_stringlist_get_length + (struct sieve_stringlist *_strlist); + +struct tst_string_stringlist { + struct sieve_stringlist strlist; + + struct sieve_stringlist *value_list; +}; + +static struct sieve_stringlist *tst_string_stringlist_create +(const struct sieve_runtime_env *renv, struct sieve_stringlist *value_list) +{ + struct tst_string_stringlist *strlist; + + strlist = t_new(struct tst_string_stringlist, 1); + strlist->strlist.runenv = renv; + strlist->strlist.exec_status = SIEVE_EXEC_OK; + strlist->strlist.next_item = tst_string_stringlist_next_item; + strlist->strlist.reset = tst_string_stringlist_reset; + strlist->strlist.get_length = tst_string_stringlist_get_length; + strlist->value_list = value_list; + + return &strlist->strlist; +} + +static int tst_string_stringlist_next_item +(struct sieve_stringlist *_strlist, string_t **str_r) +{ + struct tst_string_stringlist *strlist = + (struct tst_string_stringlist *)_strlist; + + return sieve_stringlist_next_item(strlist->value_list, str_r); +} + +static void tst_string_stringlist_reset +(struct sieve_stringlist *_strlist) +{ + struct tst_string_stringlist *strlist = + (struct tst_string_stringlist *)_strlist; + + sieve_stringlist_reset(strlist->value_list); +} + +static int tst_string_stringlist_get_length +(struct sieve_stringlist *_strlist) +{ + struct tst_string_stringlist *strlist = + (struct tst_string_stringlist *)_strlist; + string_t *item; + int length = 0; + int ret; + + while ( (ret=sieve_stringlist_next_item(strlist->value_list, &item)) > 0 ) { + if ( str_len(item) > 0 ) + length++; + } + + return ( ret < 0 ? -1 : length ); +} + +static int tst_string_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_octet_comparator); + struct sieve_stringlist *source, *value_list, *key_list; + int match, ret; + + /* + * Read operands + */ + + /* Handle match-type and comparator operands */ + if ( sieve_match_opr_optional_read + (renv, address, NULL, &ret, &cmp, &mcht) < 0 ) + return ret; + + /* Read source */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "source", &source)) <= 0 ) + return ret; + + /* Read key-list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "string test"); + + /* Create wrapper string list wich does not count empty string items */ + value_list = tst_string_stringlist_create(renv, source); + + /* Perform match */ + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/Makefile.am b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/Makefile.am new file mode 100644 index 0000000..f409e2b --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS = debug environment report + diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/Makefile.in b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/Makefile.in new file mode 100644 index 0000000..43680f1 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/Makefile.in @@ -0,0 +1,692 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/vnd.dovecot +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = debug environment report +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/vnd.dovecot/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/vnd.dovecot/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/Makefile.am b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/Makefile.am new file mode 100644 index 0000000..1e08946 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/Makefile.am @@ -0,0 +1,15 @@ +noinst_LTLIBRARIES = libsieve_ext_debug.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../../.. \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-debug-log.c + +libsieve_ext_debug_la_SOURCES = \ + $(commands) \ + ext-debug.c + +noinst_HEADERS = \ + ext-debug-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/Makefile.in b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/Makefile.in new file mode 100644 index 0000000..f9b5450 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/Makefile.in @@ -0,0 +1,687 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/vnd.dovecot/debug +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_debug_la_LIBADD = +am__objects_1 = cmd-debug-log.lo +am_libsieve_ext_debug_la_OBJECTS = $(am__objects_1) ext-debug.lo +libsieve_ext_debug_la_OBJECTS = $(am_libsieve_ext_debug_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/cmd-debug-log.Plo \ + ./$(DEPDIR)/ext-debug.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_debug_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_debug_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_debug.la +AM_CPPFLAGS = \ + -I$(srcdir)/../../.. \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-debug-log.c + +libsieve_ext_debug_la_SOURCES = \ + $(commands) \ + ext-debug.c + +noinst_HEADERS = \ + ext-debug-common.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/vnd.dovecot/debug/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/vnd.dovecot/debug/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_debug.la: $(libsieve_ext_debug_la_OBJECTS) $(libsieve_ext_debug_la_DEPENDENCIES) $(EXTRA_libsieve_ext_debug_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_debug_la_OBJECTS) $(libsieve_ext_debug_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-debug-log.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-debug.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-debug-log.Plo + -rm -f ./$(DEPDIR)/ext-debug.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/cmd-debug-log.Plo + -rm -f ./$(DEPDIR)/ext-debug.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c new file mode 100644 index 0000000..355daa5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c @@ -0,0 +1,130 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-code.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-debug-common.h" + +/* + * Debug_log command + * + * Syntax + * debug_log <message: string> + */ + +static bool cmd_debug_log_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool cmd_debug_log_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def debug_log_command = { + .identifier = "debug_log", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_debug_log_validate, + .generate = cmd_debug_log_generate +}; + +/* + * Body operation + */ + +static bool cmd_debug_log_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_debug_log_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def debug_log_operation = { + .mnemonic = "DEBUG_LOG", + .ext_def = &vnd_debug_extension, + .dump = cmd_debug_log_operation_dump, + .execute = cmd_debug_log_operation_execute +}; + +/* + * Validation + */ + +static bool cmd_debug_log_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "message", 1, SAAT_STRING) ) { + return FALSE; + } + + return sieve_validator_argument_activate(valdtr, tst, arg, FALSE); +} + +/* + * Code generation + */ + +static bool cmd_debug_log_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + (void)sieve_operation_emit(cgenv->sblock, cmd->ext, &debug_log_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool cmd_debug_log_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "DEBUG_LOG"); + sieve_code_descend(denv); + + return sieve_opr_string_dump(denv, address, "key list"); +} + +/* + * Interpretation + */ + +static int cmd_debug_log_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + string_t *message; + int ret; + + /* + * Read operands + */ + + /* Read message */ + + if ( (ret=sieve_opr_string_read(renv, address, "message", &message)) <= 0 ) + return ret; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "debug_log \"%s\"", + str_sanitize(str_c(message), 80)); + + sieve_runtime_log(renv, NULL, "DEBUG: %s", str_c(message)); + + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug-common.h b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug-common.h new file mode 100644 index 0000000..88ae3db --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug-common.h @@ -0,0 +1,22 @@ +#ifndef EXT_DEBUG_COMMON_H +#define EXT_DEBUG_COMMON_H + +/* + * Extensions + */ + +extern const struct sieve_extension_def vnd_debug_extension; + +/* + * Commands + */ + +extern const struct sieve_command_def debug_log_command; + +/* + * Operations + */ + +extern const struct sieve_operation_def debug_log_operation; + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c new file mode 100644 index 0000000..2781e83 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c @@ -0,0 +1,70 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension debug + * --------------- + * + * Authors: Stephan Bosch + * Specification: vendor-defined; spec-bosch-sieve-debug + * Implementation: full + * Status: experimental + * + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-debug-common.h" + +/* + * Extension + */ + +static bool ext_debug_validator_load + (const struct sieve_extension *ext, struct sieve_validator *validator); +static bool ext_debug_interpreter_load + (const struct sieve_extension *ext ATTR_UNUSED, + const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED); + + +const struct sieve_extension_def vnd_debug_extension = { + .name = "vnd.dovecot.debug", + .validator_load = ext_debug_validator_load, + .interpreter_load = ext_debug_interpreter_load, + SIEVE_EXT_DEFINE_OPERATION(debug_log_operation), +}; + +static bool ext_debug_validator_load +(const struct sieve_extension *ext, struct sieve_validator *validator) +{ + /* Register new test */ + sieve_validator_register_command(validator, ext, &debug_log_command); + + return TRUE; +} + +static bool ext_debug_interpreter_load +(const struct sieve_extension *ext ATTR_UNUSED, + const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED) +{ + if ( renv->ehandler != NULL ) { + sieve_error_handler_accept_infolog(renv->ehandler, TRUE); + } + + return TRUE; +} + + + diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/Makefile.am b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/Makefile.am new file mode 100644 index 0000000..96618ff --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/Makefile.am @@ -0,0 +1,16 @@ +noinst_LTLIBRARIES = libsieve_ext_vnd_environment.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../../.. \ + -I$(srcdir)/../../environment \ + -I$(srcdir)/../../variables \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_vnd_environment_la_SOURCES = \ + ext-vnd-environment.c \ + ext-vnd-environment-items.c \ + ext-vnd-environment-variables.c + +noinst_HEADERS = \ + ext-vnd-environment-common.h + diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/Makefile.in b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/Makefile.in new file mode 100644 index 0000000..b5d8b20 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/Makefile.in @@ -0,0 +1,692 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/vnd.dovecot/environment +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_vnd_environment_la_LIBADD = +am_libsieve_ext_vnd_environment_la_OBJECTS = ext-vnd-environment.lo \ + ext-vnd-environment-items.lo ext-vnd-environment-variables.lo +libsieve_ext_vnd_environment_la_OBJECTS = \ + $(am_libsieve_ext_vnd_environment_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ext-vnd-environment-items.Plo \ + ./$(DEPDIR)/ext-vnd-environment-variables.Plo \ + ./$(DEPDIR)/ext-vnd-environment.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_vnd_environment_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_vnd_environment_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_vnd_environment.la +AM_CPPFLAGS = \ + -I$(srcdir)/../../.. \ + -I$(srcdir)/../../environment \ + -I$(srcdir)/../../variables \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_vnd_environment_la_SOURCES = \ + ext-vnd-environment.c \ + ext-vnd-environment-items.c \ + ext-vnd-environment-variables.c + +noinst_HEADERS = \ + ext-vnd-environment-common.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/vnd.dovecot/environment/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/vnd.dovecot/environment/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_vnd_environment.la: $(libsieve_ext_vnd_environment_la_OBJECTS) $(libsieve_ext_vnd_environment_la_DEPENDENCIES) $(EXTRA_libsieve_ext_vnd_environment_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_vnd_environment_la_OBJECTS) $(libsieve_ext_vnd_environment_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-vnd-environment-items.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-vnd-environment-variables.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-vnd-environment.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-vnd-environment-items.Plo + -rm -f ./$(DEPDIR)/ext-vnd-environment-variables.Plo + -rm -f ./$(DEPDIR)/ext-vnd-environment.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ext-vnd-environment-items.Plo + -rm -f ./$(DEPDIR)/ext-vnd-environment-variables.Plo + -rm -f ./$(DEPDIR)/ext-vnd-environment.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-common.h b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-common.h new file mode 100644 index 0000000..980c830 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-common.h @@ -0,0 +1,37 @@ +#ifndef EXT_VND_ENVIRONMENT_COMMON_H +#define EXT_VND_ENVIRONMENT_COMMON_H + +#include "sieve-ext-environment.h" + +/* + * Extension + */ + +struct ext_vnd_environment_context { + const struct sieve_extension *env_ext; + const struct sieve_extension *var_ext; +}; + +extern const struct sieve_extension_def vnd_environment_extension; + +/* + * Operands + */ + +extern const struct sieve_operand_def environment_namespace_operand; + +/* + * Environment items + */ + +void ext_vnd_environment_items_register +(const struct sieve_extension *ext, const struct sieve_runtime_env *renv); + +/* + * Variables + */ + +void ext_environment_variables_init +(const struct sieve_extension *this_ext, struct sieve_validator *valdtr); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-items.c b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-items.c new file mode 100644 index 0000000..af03255 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-items.c @@ -0,0 +1,95 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-settings.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-vnd-environment-common.h" + +/* + * Environment items + */ + +/* default_mailbox */ + +static const char * +envit_default_mailbox_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + i_assert(eenv->scriptenv->default_mailbox != NULL); + return eenv->scriptenv->default_mailbox; +} + +const struct sieve_environment_item default_mailbox_env_item = { + .name = "vnd.dovecot.default-mailbox", + .get_value = envit_default_mailbox_get_value +}; + +/* username */ + +static const char * +envit_username_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + return eenv->svinst->username; +} + +const struct sieve_environment_item username_env_item = { + .name = "vnd.dovecot.username", + .get_value = envit_username_get_value +}; + +/* config.* */ + +static const char * +envit_config_get_value(const struct sieve_runtime_env *renv, const char *name) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + if (*name == '\0') + return NULL; + + return sieve_setting_get(eenv->svinst, + t_strconcat("sieve_env_", name, NULL)); +} + +const struct sieve_environment_item config_env_item = { + .name = "vnd.dovecot.config", + .prefix = TRUE, + .get_value = envit_config_get_value +}; + +/* + * Register + */ + +void ext_vnd_environment_items_register(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv) +{ + struct ext_vnd_environment_context *ectx = + (struct ext_vnd_environment_context *)ext->context; + + sieve_environment_item_register(ectx->env_ext, renv->interp, + &default_mailbox_env_item); + sieve_environment_item_register(ectx->env_ext, renv->interp, + &username_env_item); + sieve_environment_item_register(ectx->env_ext, renv->interp, + &config_env_item); +} diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-variables.c b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-variables.c new file mode 100644 index 0000000..1466ee7 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-variables.c @@ -0,0 +1,206 @@ +/* Copyright (c) 2015-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" +#include "sieve-ast.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "ext-vnd-environment-common.h" + +static bool vnspc_vnd_environment_validate + (struct sieve_validator *valdtr, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg, struct sieve_command *cmd, + ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, + bool assignment); +static bool vnspc_vnd_environment_generate + (const struct sieve_codegen_env *cgenv, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg, + struct sieve_command *cmd, void *var_data); +static bool vnspc_vnd_environment_dump_variable + (const struct sieve_dumptime_env *denv, + const struct sieve_variables_namespace *nspc, + const struct sieve_operand *oprnd, sieve_size_t *address); +static int vnspc_vnd_environment_read_variable + (const struct sieve_runtime_env *renv, + const struct sieve_variables_namespace *nspc, + const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r); + +static const struct sieve_variables_namespace_def +environment_namespace = { + SIEVE_OBJECT("env", &environment_namespace_operand, 0), + .validate = vnspc_vnd_environment_validate, + .generate = vnspc_vnd_environment_generate, + .dump_variable = vnspc_vnd_environment_dump_variable, + .read_variable = vnspc_vnd_environment_read_variable +}; + +static bool vnspc_vnd_environment_validate +(struct sieve_validator *valdtr, + const struct sieve_variables_namespace *nspc ATTR_UNUSED, + struct sieve_ast_argument *arg, struct sieve_command *cmd ATTR_UNUSED, + ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, + bool assignment) +{ + struct sieve_ast *ast = arg->ast; + const struct sieve_variable_name *name_elements; + unsigned int i, count; + const char *variable; + string_t *name; + + /* Compose environment name from parsed variable name */ + name = t_str_new(64); + name_elements = array_get(var_name, &count); + i_assert(count > 1); + for (i = 1; i < count; i++) { + if ( name_elements[i].num_variable >= 0 ) { + sieve_argument_validate_error(valdtr, arg, + "vnd.dovecot.environment: invalid variable name within " + "env namespace `env.%d': " + "encountered numeric variable name", + name_elements[i].num_variable); + return FALSE; + } + if (str_len(name) > 0) + str_append_c(name, '.'); + str_append_str(name, name_elements[i].identifier); + } + + variable = str_c(name); + + if ( assignment ) { + sieve_argument_validate_error(valdtr, arg, + "vnd.dovecot.environment: cannot assign to environment " + "variable `env.%s'", variable); + return FALSE; + } + + *var_data = (void *) p_strdup(sieve_ast_pool(ast), variable); + return TRUE; +} + +static bool vnspc_vnd_environment_generate +(const struct sieve_codegen_env *cgenv, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg ATTR_UNUSED, + struct sieve_command *cmd ATTR_UNUSED, void *var_data) +{ + const struct sieve_extension *this_ext = SIEVE_OBJECT_EXTENSION(nspc); + const char *variable = (const char *) var_data; + struct ext_vnd_environment_context *ext_data; + + if ( this_ext == NULL ) + return FALSE; + + ext_data = (struct ext_vnd_environment_context *) this_ext->context; + + sieve_variables_opr_namespace_variable_emit + (cgenv->sblock, ext_data->var_ext, this_ext, &environment_namespace); + sieve_binary_emit_cstring(cgenv->sblock, variable); + + return TRUE; +} + +static bool vnspc_vnd_environment_dump_variable +(const struct sieve_dumptime_env *denv, + const struct sieve_variables_namespace *nspc ATTR_UNUSED, + const struct sieve_operand *oprnd, sieve_size_t *address) +{ + string_t *var_name; + + if ( !sieve_binary_read_string(denv->sblock, address, &var_name) ) + return FALSE; + + if ( oprnd->field_name != NULL ) + sieve_code_dumpf(denv, "%s: VAR ${env.%s}", + oprnd->field_name, str_c(var_name)); + else + sieve_code_dumpf(denv, "VAR ${env.%s}", + str_c(var_name)); + + return TRUE; +} + +static int vnspc_vnd_environment_read_variable +(const struct sieve_runtime_env *renv, + const struct sieve_variables_namespace *nspc, + const struct sieve_operand *oprnd, sieve_size_t *address, + string_t **str_r) +{ + const struct sieve_extension *this_ext = SIEVE_OBJECT_EXTENSION(nspc); + struct ext_vnd_environment_context *ectx = + (struct ext_vnd_environment_context *) this_ext->context; + string_t *var_name; + const char *ext_value; + + if ( !sieve_binary_read_string(renv->sblock, address, &var_name) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "environment variable operand corrupt: invalid name"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( str_r != NULL ) { + const char *vname = str_c(var_name); + + ext_value = ext_environment_item_get_value + (ectx->env_ext, renv, vname); + + if ( ext_value == NULL && strchr(vname, '_') != NULL) { + char *p, *aname; + + /* Try again with '_' replaced with '-' */ + aname = t_strdup_noconst(vname); + for (p = aname; *p != '\0'; p++) { + if (*p == '_') + *p = '-'; + } + ext_value = ext_environment_item_get_value + (ectx->env_ext, renv, aname); + } + + if ( ext_value == NULL ) { + *str_r = t_str_new_const("", 0); + return SIEVE_EXEC_OK; + } + + *str_r = t_str_new_const(ext_value, strlen(ext_value)); + } + return SIEVE_EXEC_OK; +} + +/* + * Namespace registration + */ + +static const struct sieve_extension_objects environment_namespaces = + SIEVE_VARIABLES_DEFINE_NAMESPACE(environment_namespace); + +const struct sieve_operand_def environment_namespace_operand = { + .name = "env-namespace", + .ext_def = &vnd_environment_extension, + .class = &sieve_variables_namespace_operand_class, + .interface = &environment_namespaces +}; + +void ext_environment_variables_init +(const struct sieve_extension *this_ext, struct sieve_validator *valdtr) +{ + struct ext_vnd_environment_context *ext_data = + (struct ext_vnd_environment_context *) this_ext->context; + + sieve_variables_namespace_register + (ext_data->var_ext, valdtr, this_ext, &environment_namespace); +} diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment.c b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment.c new file mode 100644 index 0000000..f8c7028 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment.c @@ -0,0 +1,112 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension vnd.dovecot.environment + * --------------------------------- + * + * Authors: Stephan Bosch + * Specification: vendor-defined; + * spec-bosch-sieve-dovecot-environment + * Implementation: preliminary + * Status: experimental + * + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "ext-vnd-environment-common.h" + +/* + * Extension + */ + +static bool ext_vnd_environment_load + (const struct sieve_extension *ext, void **context); +static void ext_vnd_environment_unload + (const struct sieve_extension *ext); +static bool ext_vnd_environment_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); +static bool ext_vnd_environment_interpreter_load + (const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_extension_def vnd_environment_extension = { + .name = "vnd.dovecot.environment", + .load = ext_vnd_environment_load, + .unload = ext_vnd_environment_unload, + .validator_load = ext_vnd_environment_validator_load, + .interpreter_load = ext_vnd_environment_interpreter_load, + SIEVE_EXT_DEFINE_OPERAND(environment_namespace_operand) +}; + +static bool ext_vnd_environment_load +(const struct sieve_extension *ext, void **context) +{ + struct ext_vnd_environment_context *ectx; + + if ( *context != NULL ) + ext_vnd_environment_unload(ext); + + ectx = i_new(struct ext_vnd_environment_context, 1); + ectx->env_ext = sieve_ext_environment_require_extension(ext->svinst); + ectx->var_ext = sieve_ext_variables_get_extension(ext->svinst); + *context = (void *) ectx; + + return TRUE; +} + +static void ext_vnd_environment_unload +(const struct sieve_extension *ext) +{ + struct ext_vnd_environment_context *ectx = + (struct ext_vnd_environment_context *) ext->context; + + i_free(ectx); +} + +/* + * Validator + */ + +static bool ext_vnd_environment_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + const struct sieve_extension *env_ext; + + /* Load environment extension implicitly */ + + env_ext = sieve_validator_extension_load_implicit + (valdtr, environment_extension.name); + if ( env_ext == NULL ) + return FALSE; + + ext_environment_variables_init(ext, valdtr); + return TRUE; +} + +/* + * Interpreter + */ + +static bool ext_vnd_environment_interpreter_load +(const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + ext_vnd_environment_items_register(ext, renv); + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/Makefile.am b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/Makefile.am new file mode 100644 index 0000000..599765f --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/Makefile.am @@ -0,0 +1,17 @@ +noinst_LTLIBRARIES = libsieve_ext_vnd_report.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../../.. \ + -I$(srcdir)/../../../util \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-report.c + +libsieve_ext_vnd_report_la_SOURCES = \ + ext-vnd-report.c \ + ext-vnd-report-common.c \ + $(commands) + +noinst_HEADERS = \ + ext-vnd-report-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/Makefile.in b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/Makefile.in new file mode 100644 index 0000000..1c2ec8c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/Makefile.in @@ -0,0 +1,695 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/plugins/vnd.dovecot/report +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_vnd_report_la_LIBADD = +am__objects_1 = cmd-report.lo +am_libsieve_ext_vnd_report_la_OBJECTS = ext-vnd-report.lo \ + ext-vnd-report-common.lo $(am__objects_1) +libsieve_ext_vnd_report_la_OBJECTS = \ + $(am_libsieve_ext_vnd_report_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/cmd-report.Plo \ + ./$(DEPDIR)/ext-vnd-report-common.Plo \ + ./$(DEPDIR)/ext-vnd-report.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_ext_vnd_report_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_vnd_report_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_ext_vnd_report.la +AM_CPPFLAGS = \ + -I$(srcdir)/../../.. \ + -I$(srcdir)/../../../util \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-report.c + +libsieve_ext_vnd_report_la_SOURCES = \ + ext-vnd-report.c \ + ext-vnd-report-common.c \ + $(commands) + +noinst_HEADERS = \ + ext-vnd-report-common.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/plugins/vnd.dovecot/report/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/vnd.dovecot/report/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_ext_vnd_report.la: $(libsieve_ext_vnd_report_la_OBJECTS) $(libsieve_ext_vnd_report_la_DEPENDENCIES) $(EXTRA_libsieve_ext_vnd_report_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_vnd_report_la_OBJECTS) $(libsieve_ext_vnd_report_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-report.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-vnd-report-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-vnd-report.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-report.Plo + -rm -f ./$(DEPDIR)/ext-vnd-report-common.Plo + -rm -f ./$(DEPDIR)/ext-vnd-report.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/cmd-report.Plo + -rm -f ./$(DEPDIR)/ext-vnd-report-common.Plo + -rm -f ./$(DEPDIR)/ext-vnd-report.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c new file mode 100644 index 0000000..af53e42 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c @@ -0,0 +1,692 @@ +/* Copyright (c) 2016-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "str.h" +#include "ioloop.h" +#include "hostpid.h" +#include "str-sanitize.h" +#include "istream.h" +#include "ostream.h" +#include "message-date.h" +#include "message-size.h" +#include "mail-storage.h" + +#include "rfc2822.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-address.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-message.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-result.h" +#include "sieve-address.h" +#include "sieve-message.h" +#include "sieve-smtp.h" + +#include "ext-vnd-report-common.h" + +#include <ctype.h> + +/* Report command + * + * Syntax: + * report [:headers_only] <feedback-type: string> + * <message: string> <address: string> + * + */ + +static bool +cmd_report_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool +cmd_report_validate(struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool +cmd_report_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def cmd_report = { + .identifier = "report", + .type = SCT_COMMAND, + .positional_args = 3, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_report_registered, + .validate = cmd_report_validate, + .generate = cmd_report_generate +}; + +/* + * Tagged arguments + */ + +static const struct sieve_argument_def report_headers_only_tag = { + .identifier = "headers_only" +}; + +/* + * Report operation + */ + +static bool +cmd_report_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_report_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def report_operation = { + .mnemonic = "REPORT", + .ext_def = &vnd_report_extension, + .code = 0, + .dump = cmd_report_operation_dump, + .execute = cmd_report_operation_execute +}; + +/* Codes for optional operands */ + +enum cmd_report_optional { + OPT_END, + OPT_HEADERS_ONLY +}; + +/* + * Report action + */ + +/* Forward declarations */ + +static int +act_report_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other); +static void +act_report_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep); +static int +act_report_commit(const struct sieve_action_exec_env *aenv, void *tr_context); + +/* Action object */ + +const struct sieve_action_def act_report = { + .name = "report", + .check_duplicate = act_report_check_duplicate, + .print = act_report_print, + .commit = act_report_commit +}; + +/* Action data */ + +struct act_report_data { + const char *feedback_type; + const char *message; + struct smtp_address *to_address; + bool headers_only:1; +}; + +/* + * Command registration + */ + +static bool +cmd_report_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &report_headers_only_tag, + OPT_HEADERS_ONLY); + return TRUE; +} + +/* + * Command validation + */ + +static bool +cmd_report_validate(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + /* type */ + if (!sieve_validate_positional_argument(valdtr, cmd, arg, + "feedback-type", 1, + SAAT_STRING)) + return FALSE; + if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE)) + return FALSE; + + if (sieve_argument_is_string_literal(arg)) { + string_t *fbtype = sieve_ast_argument_str(arg); + const char *feedback_type; + + T_BEGIN { + /* Check feedback type */ + feedback_type = + ext_vnd_report_parse_feedback_type(str_c(fbtype)); + + if (feedback_type == NULL) { + sieve_argument_validate_error( + valdtr, arg, + "specified feedback type `%s' is invalid", + str_sanitize(str_c(fbtype),128)); + } + } T_END; + + if (feedback_type == NULL) + return FALSE; + } + arg = sieve_ast_argument_next(arg); + + /* message */ + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "message", + 2, SAAT_STRING)) + return FALSE; + if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE)) + return FALSE; + arg = sieve_ast_argument_next(arg); + + /* address */ + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "address", + 3, SAAT_STRING)) + return FALSE; + if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE)) + return FALSE; + + /* We can only assess the validity of the outgoing address when it is a + string literal. For runtime-generated strings this needs to be done + at runtime. + */ + if (sieve_argument_is_string_literal(arg)) { + string_t *raw_address = sieve_ast_argument_str(arg); + const char *error; + bool result; + + T_BEGIN { + /* Parse the address */ + result = sieve_address_validate_str(raw_address, &error); + if (!result) { + sieve_argument_validate_error( + valdtr, arg, + "specified report address '%s' is invalid: %s", + str_sanitize(str_c(raw_address),128), + error); + } + } T_END; + + return result; + } + + return TRUE; +} + +/* + * Code generation + */ + +static bool +cmd_report_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &report_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool +cmd_report_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "REPORT"); + sieve_code_descend(denv); + + /* Dump optional operands */ + for (;;) { + int opt; + + if ((opt = sieve_opr_optional_dump(denv, address, + &opt_code)) < 0) + return FALSE; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_HEADERS_ONLY: + sieve_code_dumpf(denv, "headers_only"); + break; + default: + return FALSE; + } + } + + return (sieve_opr_string_dump(denv, address, "feedback-type") && + sieve_opr_string_dump(denv, address, "message") && + sieve_opr_string_dump(denv, address, "address")); +} + +/* + * Code execution + */ + + +static int +cmd_report_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct act_report_data *act; + string_t *fbtype, *message, *to_address; + const char *feedback_type, *error; + const struct smtp_address *parsed_address; + int opt_code = 0, ret = 0; + bool headers_only = FALSE; + pool_t pool; + + /* + * Read operands + */ + + /* Optional operands */ + + for (;;) { + int opt; + + if ((opt = sieve_opr_optional_read(renv, address, + &opt_code)) < 0) + return SIEVE_EXEC_BIN_CORRUPT; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_HEADERS_ONLY: + headers_only = TRUE; + break; + default: + sieve_runtime_trace_error( + renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + } + + /* Fixed operands */ + + if ((ret = sieve_opr_string_read(renv, address, "feedback-type", + &fbtype)) <= 0) + return ret; + if ((ret = sieve_opr_string_read(renv, address, "message", + &message)) <= 0) + return ret; + if ((ret = sieve_opr_string_read(renv, address, "address", + &to_address)) <= 0) + return ret; + + /* + * Perform operation + */ + + /* Verify and trim feedback type */ + feedback_type = ext_vnd_report_parse_feedback_type(str_c(fbtype)); + if (feedback_type == NULL) { + sieve_runtime_error( + renv, NULL, + "specified report feedback type `%s' is invalid", + str_sanitize(str_c(fbtype), 256)); + return SIEVE_EXEC_FAILURE; + } + + /* Verify and normalize the address to 'local_part@domain' */ + parsed_address = sieve_address_parse_str(to_address, &error); + if (parsed_address == NULL) { + sieve_runtime_error( + renv, NULL, + "specified report address '%s' is invalid: %s", + str_sanitize(str_c(to_address),128), error); + return SIEVE_EXEC_FAILURE; + } + + /* Trace */ + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_ACTIONS)) { + sieve_runtime_trace(renv, 0, "report action"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace( + renv, 0, "report incoming message as `%s' to address %s", + str_sanitize(str_c(fbtype), 32), + smtp_address_encode_path(parsed_address)); + } + + /* Add report action to the result */ + + pool = sieve_result_pool(renv->result); + act = p_new(pool, struct act_report_data, 1); + act->headers_only = headers_only; + act->feedback_type = p_strdup(pool, feedback_type); + act->message = p_strdup(pool, str_c(message)); + act->to_address = smtp_address_clone(pool, parsed_address); + + if (sieve_result_add_action(renv, this_ext, "report", &act_report, NULL, + (void *)act, 0, TRUE) < 0) + return SIEVE_EXEC_FAILURE; + return SIEVE_EXEC_OK; +} + +/* + * Action + */ + +/* Runtime verification */ + +static bool +act_report_equals(const struct sieve_script_env *senv ATTR_UNUSED, + const struct sieve_action *act1, + const struct sieve_action *act2) +{ + struct act_report_data *rdd1 = (struct act_report_data *)act1->context; + struct act_report_data *rdd2 = (struct act_report_data *)act2->context; + + /* Address is already normalized */ + return (smtp_address_equals(rdd1->to_address, rdd2->to_address)); +} + +static int +act_report_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + return (act_report_equals(eenv->scriptenv, act, act_other) ? 1 : 0); +} + +/* Result printing */ + +static void +act_report_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, + bool *keep ATTR_UNUSED) +{ + const struct act_report_data *rdd = + (struct act_report_data *)action->context; + + sieve_result_action_printf(rpenv, + "report incoming message as `%s' to: %s", + str_sanitize(rdd->feedback_type, 32), + smtp_address_encode_path(rdd->to_address)); +} + +/* Result execution */ + +static bool _contains_8bit(const char *msg) +{ + const unsigned char *s = (const unsigned char *)msg; + + for (; *s != '\0'; s++) { + if ((*s & 0x80) != 0) + return TRUE; + } + return FALSE; +} + +static int +act_report_send(const struct sieve_action_exec_env *aenv, + const struct ext_report_config *config, + const struct act_report_data *act) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_instance *svinst = eenv->svinst; + struct sieve_message_context *msgctx = aenv->msgctx; + const struct sieve_script_env *senv = eenv->scriptenv; + const struct sieve_message_data *msgdata = eenv->msgdata; + struct sieve_address_source report_from = config->report_from; + const struct smtp_address *sender, *user; + struct sieve_smtp_context *sctx; + struct istream *input; + struct ostream *output; + string_t *msg; + const char *const *headers; + const char *outmsgid, *boundary, *error, *subject, *from; + int ret; + + /* Just to be sure */ + if (!sieve_smtp_available(senv)) { + sieve_result_global_warning( + aenv, "report action has no means to send mail"); + return SIEVE_EXEC_OK; + } + + /* Make sure we have a subject for our report */ + if ((ret = mail_get_headers_utf8(msgdata->mail, "subject", + &headers)) < 0) { + return sieve_result_mail_error( + aenv, msgdata->mail, + "failed to read header field `subject'"); + } + if (ret > 0 && headers[0] != NULL) + subject = t_strconcat("Report: ", headers[0], NULL); + else + subject = "Report: (message without subject)"; + + /* Determine from address */ + if (report_from.type == SIEVE_ADDRESS_SOURCE_POSTMASTER) { + report_from.type = SIEVE_ADDRESS_SOURCE_DEFAULT; + report_from.address = NULL; + } + if (sieve_address_source_get_address( + &report_from, svinst, senv, msgctx, eenv->flags, + &sender) > 0 && sender != NULL) + from = smtp_address_encode_path(sender); + else + from = sieve_get_postmaster_address(senv); + + /* Start message */ + sctx = sieve_smtp_start_single(senv, act->to_address, NULL, &output); + + outmsgid = sieve_message_get_new_id(svinst); + boundary = t_strdup_printf("%s/%s", my_pid, svinst->hostname); + + /* Compose main report headers */ + msg = t_str_new(512); + rfc2822_header_write(msg, "X-Sieve", SIEVE_IMPLEMENTATION); + rfc2822_header_write(msg, "Message-ID", outmsgid); + rfc2822_header_write(msg, "Date", message_date_create(ioloop_time)); + + rfc2822_header_write(msg, "From", from); + rfc2822_header_write(msg, "To", + smtp_address_encode_path(act->to_address)); + + if (_contains_8bit(subject)) + rfc2822_header_utf8_printf(msg, "Subject", "%s", subject); + else + rfc2822_header_printf(msg, "Subject", "%s", subject); + + rfc2822_header_write(msg, "Auto-Submitted", "auto-generated (report)"); + + rfc2822_header_write(msg, "MIME-Version", "1.0"); + rfc2822_header_printf(msg, "Content-Type", + "multipart/report; report-type=feedback-report;\n" + "boundary=\"%s\"", boundary); + + str_append(msg, "\r\nThis is a MIME-encapsulated message\r\n\r\n"); + + /* Human-readable report */ + str_printfa(msg, "--%s\r\n", boundary); + if (_contains_8bit(act->message)) { + rfc2822_header_write(msg, "Content-Type", + "text/plain; charset=utf-8"); + rfc2822_header_write(msg, "Content-Transfer-Encoding", "8bit"); + } else { + rfc2822_header_write(msg, "Content-Type", + "text/plain; charset=us-ascii"); + rfc2822_header_write(msg, "Content-Transfer-Encoding", "7bit"); + } + rfc2822_header_write(msg, "Content-Disposition", "inline"); + + str_printfa(msg, "\r\n%s\r\n\r\n", act->message); + o_stream_nsend(output, str_data(msg), str_len(msg)); + + /* Machine-readable report */ + str_truncate(msg, 0); + str_printfa(msg, "--%s\r\n", boundary); + rfc2822_header_write(msg, "Content-Type", "message/feedback-report"); + str_append(msg, "\r\n"); + + rfc2822_header_write(msg, "Version", "1"); + rfc2822_header_write(msg, "Feedback-Type", act->feedback_type); + rfc2822_header_write(msg, "User-Agent", + PACKAGE_NAME "/" PACKAGE_VERSION " " + PIGEONHOLE_NAME "/" PIGEONHOLE_VERSION); + + if ((eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0) { + const struct smtp_address *sender, *orig_recipient; + + sender = sieve_message_get_sender(msgctx); + orig_recipient = sieve_message_get_orig_recipient(msgctx); + + rfc2822_header_write(msg, "Original-Mail-From", + smtp_address_encode_path(sender)); + if (orig_recipient != NULL) { + rfc2822_header_write( + msg, "Original-Rcpt-To", + smtp_address_encode_path(orig_recipient)); + } + } + if (svinst->user_email != NULL) + user = svinst->user_email; + else if ((eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) != 0 || + (user = sieve_message_get_orig_recipient(msgctx)) == NULL) + user = sieve_get_user_email(svinst); + if (user != NULL) { + rfc2822_header_write(msg, "Dovecot-Reporting-User", + smtp_address_encode_path(user)); + } + str_append(msg, "\r\n"); + + o_stream_nsend(output, str_data(msg), str_len(msg)); + + /* Original message */ + str_truncate(msg, 0); + str_printfa(msg, "--%s\r\n", boundary); + if (act->headers_only) { + rfc2822_header_write(msg, "Content-Type", + "text/rfc822-headers"); + } else { + rfc2822_header_write(msg, "Content-Type", "message/rfc822"); + } + rfc2822_header_write(msg, "Content-Disposition", "attachment"); + str_append(msg, "\r\n"); + o_stream_nsend(output, str_data(msg), str_len(msg)); + + if (act->headers_only) { + struct message_size hdr_size; + ret = mail_get_hdr_stream(msgdata->mail, &hdr_size, &input); + if (ret >= 0) { + input = i_stream_create_limit( + input, hdr_size.physical_size); + } + } else { + ret = mail_get_stream(msgdata->mail, NULL, NULL, &input); + if (ret >= 0) + i_stream_ref(input); + } + if (ret < 0) { + sieve_smtp_abort(sctx); + return sieve_result_mail_error(aenv, msgdata->mail, + "failed to read input message"); + } + + o_stream_nsend_istream(output, input); + + if (input->stream_errno != 0) { + /* Error; clean up */ + sieve_result_critical(aenv, "failed to read input message", + "read(%s) failed: %s", + i_stream_get_name(input), + i_stream_get_error(input)); + i_stream_unref(&input); + sieve_smtp_abort(sctx); + return SIEVE_EXEC_OK; + } + i_stream_unref(&input); + + str_truncate(msg, 0); + if (!act->headers_only) + str_printfa(msg, "\r\n"); + str_printfa(msg, "\r\n--%s--\r\n", boundary); + o_stream_nsend(output, str_data(msg), str_len(msg)); + + /* Finish sending message */ + if ((ret = sieve_smtp_finish(sctx, &error)) <= 0) { + if (ret < 0) { + sieve_result_global_error( + aenv, "failed to send `%s' report to <%s>: %s " + "(temporary failure)", + str_sanitize(act->feedback_type, 32), + smtp_address_encode(act->to_address), + str_sanitize(error, 512)); + } else { + sieve_result_global_log_error( + aenv, "failed to send `%s' report to <%s>: %s " + "(permanent failure)", + str_sanitize(act->feedback_type, 32), + smtp_address_encode(act->to_address), + str_sanitize(error, 512)); + } + } else { + eenv->exec_status->significant_action_executed = TRUE; + + struct event_passthrough *e = + sieve_action_create_finish_event(aenv)-> + add_str("report_target", + smtp_address_encode(act->to_address))-> + add_str("report_type", + str_sanitize(act->feedback_type, 32)); + + sieve_result_event_log(aenv, e->event(), + "sent `%s' report to <%s>", + str_sanitize(act->feedback_type, 32), + smtp_address_encode(act->to_address)); + } + + return SIEVE_EXEC_OK; +} + +static int +act_report_commit(const struct sieve_action_exec_env *aenv, + void *tr_context ATTR_UNUSED) +{ + const struct sieve_action *action = aenv->action; + const struct sieve_extension *ext = action->ext; + const struct ext_report_config *config = + (const struct ext_report_config *)ext->context; + const struct act_report_data *act = + (const struct act_report_data *)action->context; + int ret; + + T_BEGIN { + ret = act_report_send(aenv, config, act); + } T_END; + + if (ret == SIEVE_EXEC_TEMP_FAILURE) + return SIEVE_EXEC_TEMP_FAILURE; + + /* Ignore all other errors */ + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.c b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.c new file mode 100644 index 0000000..d22ad16 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.c @@ -0,0 +1,51 @@ +/* Copyright (c) 2016-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "rfc822-parser.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" + +#include "ext-vnd-report-common.h" + +bool ext_report_load +(const struct sieve_extension *ext, void **context) +{ + struct sieve_instance *svinst = ext->svinst; + struct ext_report_config *config; + + config = p_new(svinst->pool, struct ext_report_config, 1); + + (void)sieve_address_source_parse_from_setting(svinst, + svinst->pool, "sieve_report_from", &config->report_from); + + *context = (void *) config; + return TRUE; +} + +const char * +ext_vnd_report_parse_feedback_type(const char *feedback_type) +{ + struct rfc822_parser_context parser; + string_t *token; + + /* Initialize parsing */ + rfc822_parser_init(&parser, + (const unsigned char *)feedback_type, strlen(feedback_type), NULL); + (void)rfc822_skip_lwsp(&parser); + + /* Parse MIME token */ + token = t_str_new(64); + if (rfc822_parse_mime_token(&parser, token) < 0) + return NULL; + + /* Content-type value must end here, otherwise it is invalid after all */ + (void)rfc822_skip_lwsp(&parser); + if ( parser.data != parser.end ) + return NULL; + + /* Success */ + return str_c(token); +} diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.h b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.h new file mode 100644 index 0000000..11a3757 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.h @@ -0,0 +1,40 @@ +#ifndef EXT_REPORT_COMMON_H +#define EXT_REPORT_COMMON_H + +/* + * Extension configuration + */ + +struct ext_report_config { + struct sieve_address_source report_from; +}; + +/* + * Extension + */ + +extern const struct sieve_extension_def vnd_report_extension; + +bool ext_report_load + (const struct sieve_extension *ext, void **context); + +/* + * Commands + */ + +extern const struct sieve_command_def cmd_report; + +/* + * Operations + */ + +extern const struct sieve_operation_def report_operation; + +/* + * RFC 5965 feedback-type + */ + +const char * +ext_vnd_report_parse_feedback_type(const char *feedback_type); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report.c b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report.c new file mode 100644 index 0000000..a5fb64c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report.c @@ -0,0 +1,52 @@ +/* Copyright (c) 2016-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension report + * ---------------- + * + * Authors: Stephan Bosch + * Specification: draft-ietf-sieve-report-00.txt + * Implementation: full, but deprecated; provided for backwards compatibility + * Status: testing + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "ext-vnd-report-common.h" + +/* + * Extension + */ + +static bool ext_report_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def vnd_report_extension = { + .name = "vnd.dovecot.report", + .load = ext_report_load, + .validator_load = ext_report_validator_load, + SIEVE_EXT_DEFINE_OPERATION(report_operation) +}; + +/* + * Extension validation + */ + +static bool ext_report_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register new commands */ + sieve_validator_register_command(valdtr, ext, &cmd_report); + + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/sieve-actions.c b/pigeonhole/src/lib-sieve/sieve-actions.c new file mode 100644 index 0000000..86c9954 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-actions.c @@ -0,0 +1,1096 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "strfuncs.h" +#include "ioloop.h" +#include "hostpid.h" +#include "str-sanitize.h" +#include "unichar.h" +#include "istream.h" +#include "istream-header-filter.h" +#include "ostream.h" +#include "smtp-params.h" +#include "mail-storage.h" +#include "message-date.h" +#include "message-size.h" + +#include "rfc2822.h" + +#include "sieve-code.h" +#include "sieve-settings.h" +#include "sieve-extensions.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-result.h" +#include "sieve-actions.h" +#include "sieve-message.h" +#include "sieve-smtp.h" + +/* + * Action execution environment + */ + +struct event_passthrough * +sieve_action_create_finish_event(const struct sieve_action_exec_env *aenv) +{ + struct event_passthrough *e = + event_create_passthrough(aenv->event)-> + set_name("sieve_action_finished"); + + return e; +} + +/* + * Action instance + */ + +bool sieve_action_is_executed(const struct sieve_action *act, + struct sieve_result *result) +{ + unsigned int cur_exec_seq = sieve_result_get_exec_seq(result); + + i_assert(act->exec_seq <= cur_exec_seq); + return (act->exec_seq < cur_exec_seq); +} + +/* + * Side-effect operand + */ + +const struct sieve_operand_class +sieve_side_effect_operand_class = { "SIDE-EFFECT" }; + +bool sieve_opr_side_effect_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + struct sieve_side_effect seffect; + const struct sieve_side_effect_def *sdef; + + if (!sieve_opr_object_dump(denv, &sieve_side_effect_operand_class, + address, &seffect.object)) + return FALSE; + + sdef = seffect.def = + (const struct sieve_side_effect_def *)seffect.object.def; + + if (sdef->dump_context != NULL) { + sieve_code_descend(denv); + if (!sdef->dump_context(&seffect, denv, address)) + return FALSE; + sieve_code_ascend(denv); + } + return TRUE; +} + +int sieve_opr_side_effect_read(const struct sieve_runtime_env *renv, + sieve_size_t *address, + struct sieve_side_effect *seffect) +{ + const struct sieve_side_effect_def *sdef; + int ret; + + seffect->context = NULL; + + if (!sieve_opr_object_read(renv, &sieve_side_effect_operand_class, + address, &seffect->object)) + return SIEVE_EXEC_BIN_CORRUPT; + + sdef = seffect->def = + (const struct sieve_side_effect_def *)seffect->object.def; + + if (sdef->read_context != NULL && + (ret = sdef->read_context(seffect, renv, address, + &seffect->context)) <= 0) + return ret; + return SIEVE_EXEC_OK; +} + +/* + * Optional operands + */ + +int sieve_action_opr_optional_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address, signed int *opt_code) +{ + signed int _opt_code = 0; + bool final = FALSE, opok = TRUE; + + if (opt_code == NULL) { + opt_code = &_opt_code; + final = TRUE; + } + + while (opok) { + int opt; + + opt = sieve_opr_optional_dump(denv, address, opt_code); + if (opt <= 0) + return opt; + + if (*opt_code == SIEVE_OPT_SIDE_EFFECT) + opok = sieve_opr_side_effect_dump(denv, address); + else + return (final ? -1 : 1); + } + + return -1; +} + +int sieve_action_opr_optional_read(const struct sieve_runtime_env *renv, + sieve_size_t *address, + signed int *opt_code, int *exec_status, + struct sieve_side_effects_list **list) +{ + signed int _opt_code = 0; + bool final = FALSE; + int ret; + + if (opt_code == NULL) { + opt_code = &_opt_code; + final = TRUE; + } + + if (exec_status != NULL) + *exec_status = SIEVE_EXEC_OK; + + for (;;) { + int opt; + + opt = sieve_opr_optional_read(renv, address, opt_code); + if (opt <= 0) { + if (opt < 0 && exec_status != NULL) + *exec_status = SIEVE_EXEC_BIN_CORRUPT; + return opt; + } + + if (*opt_code == SIEVE_OPT_SIDE_EFFECT) { + struct sieve_side_effect seffect; + + i_assert(list != NULL); + + ret = sieve_opr_side_effect_read(renv, address, + &seffect); + if (ret <= 0) { + if (exec_status != NULL) + *exec_status = ret; + return -1; + } + + if (*list == NULL) { + *list = sieve_side_effects_list_create( + renv->result); + } + + sieve_side_effects_list_add(*list, &seffect); + } else { + if (final) { + sieve_runtime_trace_error( + renv, "invalid optional operand"); + if (exec_status != NULL) + *exec_status = SIEVE_EXEC_BIN_CORRUPT; + return -1; + } + return 1; + } + } + + i_unreached(); + return -1; +} + +/* + * Store action + */ + +/* Forward declarations */ + +static bool +act_store_equals(const struct sieve_script_env *senv, + const struct sieve_action *act1, + const struct sieve_action *act2); + +static int +act_store_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other); +static void +act_store_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep); + +static int +act_store_start(const struct sieve_action_exec_env *aenv, void **tr_context); +static int +act_store_execute(const struct sieve_action_exec_env *aenv, void *tr_context, + bool *keep); +static int +act_store_commit(const struct sieve_action_exec_env *aenv, void *tr_context); +static void +act_store_rollback(const struct sieve_action_exec_env *aenv, void *tr_context, + bool success); + +/* Action object */ + +const struct sieve_action_def act_store = { + .name = "store", + .flags = + SIEVE_ACTFLAG_TRIES_DELIVER | + SIEVE_ACTFLAG_MAIL_STORAGE, + .equals = act_store_equals, + .check_duplicate = act_store_check_duplicate, + .print = act_store_print, + .start = act_store_start, + .execute = act_store_execute, + .commit = act_store_commit, + .rollback = act_store_rollback, +}; + +/* API */ + +int sieve_act_store_add_to_result(const struct sieve_runtime_env *renv, + const char *name, + struct sieve_side_effects_list *seffects, + const char *mailbox) +{ + pool_t pool; + struct act_store_context *act; + + /* Add redirect action to the result */ + pool = sieve_result_pool(renv->result); + act = p_new(pool, struct act_store_context, 1); + act->mailbox = p_strdup(pool, mailbox); + + return sieve_result_add_action(renv, NULL, name, &act_store, seffects, + (void *)act, 0, TRUE); +} + +void sieve_act_store_add_flags(const struct sieve_action_exec_env *aenv, + void *tr_context, const char *const *keywords, + enum mail_flags flags) +{ + struct act_store_transaction *trans = + (struct act_store_transaction *)tr_context; + + i_assert(trans != NULL); + + /* Assign mail keywords for subsequent mailbox_copy() */ + if (*keywords != NULL) { + const char *const *kw; + + if (!array_is_created(&trans->keywords)) { + pool_t pool = sieve_result_pool(aenv->result); + p_array_init(&trans->keywords, pool, 2); + } + + kw = keywords; + while (*kw != NULL) { + array_append(&trans->keywords, kw, 1); + kw++; + } + } + + /* Assign mail flags for subsequent mailbox_copy() */ + trans->flags |= flags; + + trans->flags_altered = TRUE; +} + +/* Equality */ + +static bool +act_store_equals(const struct sieve_script_env *senv, + const struct sieve_action *act1, + const struct sieve_action *act2) +{ + struct act_store_context *st_ctx1 = + (act1 == NULL ? + NULL : (struct act_store_context *)act1->context); + struct act_store_context *st_ctx2 = + (act2 == NULL ? + NULL : (struct act_store_context *)act2->context); + const char *mailbox1, *mailbox2; + + /* FIXME: consider namespace aliases */ + + if (st_ctx1 == NULL && st_ctx2 == NULL) + return TRUE; + + mailbox1 = (st_ctx1 == NULL ? + SIEVE_SCRIPT_DEFAULT_MAILBOX(senv) : st_ctx1->mailbox); + mailbox2 = (st_ctx2 == NULL ? + SIEVE_SCRIPT_DEFAULT_MAILBOX(senv) : st_ctx2->mailbox); + + if (strcmp(mailbox1, mailbox2) == 0) + return TRUE; + + return (strcasecmp(mailbox1, "INBOX") == 0 && + strcasecmp(mailbox2, "INBOX") == 0); +} + +/* Result verification */ + +static int +act_store_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + return (act_store_equals(eenv->scriptenv, act, act_other) ? 1 : 0); +} + +/* Result printing */ + +static void +act_store_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep) +{ + struct act_store_context *ctx = + (struct act_store_context *)action->context; + const char *mailbox; + + mailbox = (ctx == NULL ? + SIEVE_SCRIPT_DEFAULT_MAILBOX(rpenv->scriptenv) : + ctx->mailbox); + + sieve_result_action_printf(rpenv, "store message in folder: %s", + str_sanitize(mailbox, 128)); + + *keep = FALSE; +} + +/* Action implementation */ + +void sieve_act_store_get_storage_error(const struct sieve_action_exec_env *aenv, + struct act_store_transaction *trans) +{ + pool_t pool = sieve_result_pool(aenv->result); + + trans->error = p_strdup(pool, + mailbox_get_last_internal_error(trans->box, + &trans->error_code)); +} + +static bool +act_store_mailbox_alloc(const struct sieve_action_exec_env *aenv, + const char *mailbox, struct mailbox **box_r, + enum mail_error *error_code_r, const char **error_r) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct mailbox *box; + struct mail_storage **storage = &(eenv->exec_status->last_storage); + enum mailbox_flags flags = MAILBOX_FLAG_POST_SESSION; + + *box_r = NULL; + *error_code_r = MAIL_ERROR_NONE; + *error_r = NULL; + + if (!uni_utf8_str_is_valid(mailbox)) { + /* Just a precaution; already (supposed to be) checked at + compiletime/runtime. + */ + *error_r = t_strdup_printf("mailbox name not utf-8: %s", + mailbox); + *error_code_r = MAIL_ERROR_PARAMS; + return FALSE; + } + + if (eenv->scriptenv->mailbox_autocreate) + flags |= MAILBOX_FLAG_AUTO_CREATE; + if (eenv->scriptenv->mailbox_autosubscribe) + flags |= MAILBOX_FLAG_AUTO_SUBSCRIBE; + *box_r = box = mailbox_alloc_for_user(eenv->scriptenv->user, mailbox, + flags); + *storage = mailbox_get_storage(box); + + return TRUE; +} + +static int +act_store_start(const struct sieve_action_exec_env *aenv, void **tr_context) +{ + const struct sieve_action *action = aenv->action; + struct act_store_context *ctx = + (struct act_store_context *)action->context; + const struct sieve_execute_env *eenv = aenv->exec_env; + const struct sieve_script_env *senv = eenv->scriptenv; + struct act_store_transaction *trans; + struct mailbox *box = NULL; + pool_t pool = sieve_result_pool(aenv->result); + const char *error = NULL; + enum mail_error error_code = MAIL_ERROR_NONE; + bool disabled = FALSE, alloc_failed = FALSE; + + /* If context is NULL, the store action is the result of (implicit) + keep. + */ + if (ctx == NULL) { + ctx = p_new(pool, struct act_store_context, 1); + ctx->mailbox = + p_strdup(pool, SIEVE_SCRIPT_DEFAULT_MAILBOX(senv)); + } + + e_debug(aenv->event, "Start storing into mailbox %s", ctx->mailbox); + + /* Open the requested mailbox */ + + /* NOTE: The caller of the sieve library is allowed to leave user set + to NULL. This implementation will then skip actually storing the + message. + */ + if (senv->user != NULL) { + if (!act_store_mailbox_alloc(aenv, ctx->mailbox, &box, + &error_code, &error)) + alloc_failed = TRUE; + } else { + disabled = TRUE; + } + + /* Create transaction context */ + trans = p_new(pool, struct act_store_transaction, 1); + + trans->context = ctx; + trans->box = box; + trans->flags = 0; + + trans->mailbox_name = ctx->mailbox; + trans->mailbox_identifier = + p_strdup_printf(pool, "'%s'", str_sanitize(ctx->mailbox, 256)); + + trans->disabled = disabled; + + if (alloc_failed) { + trans->error = p_strdup(pool, error); + trans->error_code = error_code; + e_debug(aenv->event, "Failed to open mailbox %s: %s", + trans->mailbox_identifier, trans->error); + } else { + trans->error_code = MAIL_ERROR_NONE; + } + + *tr_context = (void *)trans; + + switch (trans->error_code) { + case MAIL_ERROR_NONE: + case MAIL_ERROR_NOTFOUND: + return SIEVE_EXEC_OK; + case MAIL_ERROR_TEMP: + return SIEVE_EXEC_TEMP_FAILURE; + default: + break; + } + return SIEVE_EXEC_FAILURE; +} + +static struct mail_keywords * +act_store_keywords_create(const struct sieve_action_exec_env *aenv, + ARRAY_TYPE(const_string) *keywords, + struct mailbox *box, bool create_empty) +{ + struct mail_keywords *box_keywords = NULL; + const char *const *kwds = NULL; + + if (!array_is_created(keywords) || array_count(keywords) == 0) { + if (!create_empty) + return NULL; + } else { + ARRAY_TYPE(const_string) valid_keywords; + const char *error; + unsigned int count, i; + + kwds = array_get(keywords, &count); + t_array_init(&valid_keywords, count); + + for (i = 0; i < count; i++) { + if (mailbox_keyword_is_valid(box, kwds[i], &error)) { + array_append(&valid_keywords, &kwds[i], 1); + continue; + } + + sieve_result_warning(aenv, + "specified IMAP keyword '%s' is invalid " + "(ignored): %s", str_sanitize(kwds[i], 64), + sieve_error_from_external(error)); + } + + array_append_zero(keywords); + kwds = array_idx(keywords, 0); + } + + if (mailbox_keywords_create(box, kwds, &box_keywords) < 0) { + sieve_result_error( + aenv, "invalid keywords set for stored message"); + return NULL; + } + + return box_keywords; +} + +static bool have_equal_keywords(struct mail *mail, struct mail_keywords *new_kw) +{ + const ARRAY_TYPE(keyword_indexes) *old_kw_arr = + mail_get_keyword_indexes(mail); + const unsigned int *old_kw; + unsigned int i, j; + + if (array_count(old_kw_arr) != new_kw->count) + return FALSE; + if (new_kw->count == 0) + return TRUE; + + old_kw = array_front(old_kw_arr); + for (i = 0; i < new_kw->count; i++) { + /* new_kw->count equals old_kw's count and it's easier to use */ + for (j = 0; j < new_kw->count; j++) { + if (old_kw[j] == new_kw->idx[i]) + break; + } + if (j == new_kw->count) + return FALSE; + } + return TRUE; +} + +static int +act_store_execute(const struct sieve_action_exec_env *aenv, void *tr_context, + bool *keep) +{ + const struct sieve_action *action = aenv->action; + const struct sieve_execute_env *eenv = aenv->exec_env; + struct act_store_transaction *trans = + (struct act_store_transaction *)tr_context; + struct mail *mail = (action->mail != NULL ? + action->mail : eenv->msgdata->mail); + struct mail_save_context *save_ctx; + struct mail_keywords *keywords = NULL; + struct mailbox *box; + bool backends_equal = FALSE; + int status = SIEVE_EXEC_OK; + + /* Verify transaction */ + if (trans == NULL) + return SIEVE_EXEC_FAILURE; + box = trans->box; + + /* Check whether we need to do anything */ + if (trans->disabled) { + e_debug(aenv->event, "Skip storing into mailbox %s", + trans->mailbox_identifier); + *keep = FALSE; + return SIEVE_EXEC_OK; + } + + /* Exit early if mailbox is not available */ + if (box == NULL) + return SIEVE_EXEC_FAILURE; + + e_debug(aenv->event, "Execute storing into mailbox %s", + trans->mailbox_identifier); + + /* Mark attempt to use storage. Can only get here when all previous + actions succeeded. + */ + eenv->exec_status->last_storage = mailbox_get_storage(box); + + /* Open the mailbox (may already be open) */ + if (trans->error_code == MAIL_ERROR_NONE) { + if (mailbox_open(box) < 0) { + sieve_act_store_get_storage_error(aenv, trans); + e_debug(aenv->event, "Failed to open mailbox %s: %s", + trans->mailbox_identifier, trans->error); + } + } + + /* Exit early if transaction already failed */ + switch (trans->error_code) { + case MAIL_ERROR_NONE: + break; + case MAIL_ERROR_TEMP: + return SIEVE_EXEC_TEMP_FAILURE; + default: + return SIEVE_EXEC_FAILURE; + } + + /* If the message originates from the target mailbox, only update the + flags and keywords (if not read-only) + */ + if (mailbox_backends_equal(box, mail->box)) { + backends_equal = TRUE; + } else { + struct mail *real_mail; + + if (mail_get_backend_mail(mail, &real_mail) < 0) + return SIEVE_EXEC_FAILURE; + if (real_mail != mail && + mailbox_backends_equal(box, real_mail->box)) + backends_equal = TRUE; + } + if (backends_equal) { + trans->redundant = TRUE; + + if (trans->flags_altered && !mailbox_is_readonly(mail->box)) { + keywords = act_store_keywords_create( + aenv, &trans->keywords, mail->box, TRUE); + + if (keywords != NULL) { + if (!have_equal_keywords(mail, keywords)) { + eenv->exec_status->significant_action_executed = TRUE; + mail_update_keywords(mail, MODIFY_REPLACE, keywords); + } + mailbox_keywords_unref(&keywords); + } + + if ((mail_get_flags(mail) & MAIL_FLAGS_NONRECENT) != trans->flags) { + eenv->exec_status->significant_action_executed = TRUE; + mail_update_flags(mail, MODIFY_REPLACE, trans->flags); + } + } + e_debug(aenv->event, "Updated existing mail in mailbox %s", + trans->mailbox_identifier); + return SIEVE_EXEC_OK; + + /* If the message is modified, only store it in the source mailbox when + it is not opened read-only. Mail structs of modified messages have + their own mailbox, unrelated to the orignal mail, so this case needs + to be handled separately. + */ + } else if (mail != eenv->msgdata->mail && + mailbox_is_readonly(eenv->msgdata->mail->box) && + (mailbox_backends_equal(box, eenv->msgdata->mail->box))) { + e_debug(aenv->event, + "Not modifying exsiting mail in read-only mailbox %s", + trans->mailbox_identifier); + trans->redundant = TRUE; + return SIEVE_EXEC_OK; + } + + /* Mark attempt to store in default mailbox */ + if (strcmp(trans->context->mailbox, + SIEVE_SCRIPT_DEFAULT_MAILBOX(eenv->scriptenv)) == 0) + eenv->exec_status->tried_default_save = TRUE; + + /* Start mail transaction */ + trans->mail_trans = mailbox_transaction_begin( + box, MAILBOX_TRANSACTION_FLAG_EXTERNAL, __func__); + + /* Store the message */ + save_ctx = mailbox_save_alloc(trans->mail_trans); + + /* Apply keywords and flags that side-effects may have added */ + if (trans->flags_altered) { + keywords = act_store_keywords_create(aenv, &trans->keywords, + box, FALSE); + + if (trans->flags != 0 || keywords != NULL) { + eenv->exec_status->significant_action_executed = TRUE; + mailbox_save_set_flags(save_ctx, trans->flags, keywords); + } + } else { + mailbox_save_copy_flags(save_ctx, mail); + } + + if (mailbox_save_using_mail(&save_ctx, mail) < 0) { + sieve_act_store_get_storage_error(aenv, trans); + e_debug(aenv->event, "Failed to save to mailbox %s: %s", + trans->mailbox_identifier, trans->error); + + status = (trans->error_code == MAIL_ERROR_TEMP ? + SIEVE_EXEC_TEMP_FAILURE : SIEVE_EXEC_FAILURE); + } else { + e_debug(aenv->event, "Saving to mailbox %s successful so far", + trans->mailbox_identifier); + eenv->exec_status->significant_action_executed = TRUE; + } + + /* Deallocate keywords */ + if (keywords != NULL) + mailbox_keywords_unref(&keywords); + + /* Cancel implicit keep if all went well so far */ + *keep = (status < SIEVE_EXEC_OK); + + return status; +} + +static void +act_store_log_status(struct act_store_transaction *trans, + const struct sieve_action_exec_env *aenv, + bool rolled_back, bool status) +{ + const char *mailbox_name = trans->mailbox_name; + const char *mailbox_identifier = trans->mailbox_identifier; + + if (trans->box != NULL) { + const char *mailbox_vname = str_sanitize(mailbox_get_vname(trans->box), 128); + + if (strcmp(trans->mailbox_name, mailbox_vname) != 0) { + mailbox_identifier = t_strdup_printf( + "%s (%s)", mailbox_identifier, + str_sanitize(mailbox_vname, 256)); + } + } + + /* Store disabled? */ + if (trans->disabled) { + sieve_result_global_log(aenv, "store into mailbox %s skipped", + mailbox_identifier); + /* Store redundant? */ + } else if (trans->redundant) { + sieve_result_global_log(aenv, "left message in mailbox %s", + mailbox_identifier); + /* Store failed? */ + } else if (!status) { + const char *errstr; + enum mail_error error_code; + + if (trans->error == NULL) + sieve_act_store_get_storage_error(aenv, trans); + + errstr = trans->error; + error_code = trans->error_code; + + if (error_code == MAIL_ERROR_NOQUOTA) { + /* Never log quota problems as error in global log */ + sieve_result_global_log_error( + aenv, "failed to store into mailbox %s: %s", + mailbox_identifier, errstr); + } else if (error_code == MAIL_ERROR_NOTFOUND || + error_code == MAIL_ERROR_PARAMS || + error_code == MAIL_ERROR_PERM) { + sieve_result_error( + aenv, "failed to store into mailbox %s: %s", + mailbox_identifier, errstr); + } else { + sieve_result_global_error( + aenv, "failed to store into mailbox %s: %s", + mailbox_identifier, errstr); + } + /* Store aborted? */ + } else if (rolled_back) { + if (!aenv->action->keep) { + sieve_result_global_log( + aenv, "store into mailbox %s aborted", + mailbox_identifier); + } else { + e_debug(aenv->event, "Store into mailbox %s aborted", + mailbox_identifier); + } + /* Succeeded */ + } else { + struct event_passthrough *e = + sieve_action_create_finish_event(aenv)-> + add_str("fileinto_mailbox_name", mailbox_name)-> + add_str("fileinto_mailbox", mailbox_identifier); + sieve_result_event_log(aenv, e->event(), + "stored mail into mailbox %s", + mailbox_identifier); + } +} + +static void act_store_cleanup(struct act_store_transaction *trans) +{ + if (trans->mail_trans != NULL) + mailbox_transaction_rollback(&trans->mail_trans); + if (trans->box != NULL) + mailbox_free(&trans->box); +} + +static int +act_store_commit(const struct sieve_action_exec_env *aenv, void *tr_context) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct act_store_transaction *trans = + (struct act_store_transaction *)tr_context; + bool bail_out = FALSE, status = TRUE; + int ret = SIEVE_EXEC_OK; + + /* Verify transaction */ + if (trans == NULL) + return SIEVE_EXEC_FAILURE; + + e_debug(aenv->event, "Commit storing into mailbox %s", + trans->mailbox_identifier); + + /* Check whether we can commit this transaction */ + if (trans->error_code != MAIL_ERROR_NONE) { + /* Transaction already failed */ + bail_out = TRUE; + status = FALSE; + if (trans->error_code == MAIL_ERROR_TEMP) + ret = SIEVE_EXEC_TEMP_FAILURE; + else + ret = SIEVE_EXEC_FAILURE; + /* Check whether we need to do anything */ + } else if (trans->disabled) { + /* Nothing to do */ + bail_out = TRUE; + } else if (trans->redundant) { + /* This transaction is redundant */ + bail_out = TRUE; + eenv->exec_status->keep_original = TRUE; + eenv->exec_status->message_saved = TRUE; + } + if (bail_out) { + act_store_log_status(trans, aenv, FALSE, status); + act_store_cleanup(trans); + return ret; + } + + i_assert(trans->box != NULL); + i_assert(trans->mail_trans != NULL); + + /* Mark attempt to use storage. Can only get here when all previous + actions succeeded. + */ + eenv->exec_status->last_storage = mailbox_get_storage(trans->box); + + /* Commit mailbox transaction */ + status = (mailbox_transaction_commit(&trans->mail_trans) == 0); + + /* Note the fact that the message was stored at least once */ + if (status) + eenv->exec_status->message_saved = TRUE; + else + eenv->exec_status->store_failed = TRUE; + + /* Log our status */ + act_store_log_status(trans, aenv, FALSE, status); + + /* Clean up */ + act_store_cleanup(trans); + + if (status) + return SIEVE_EXEC_OK; + + return (trans->error_code == MAIL_ERROR_TEMP ? + SIEVE_EXEC_TEMP_FAILURE : SIEVE_EXEC_FAILURE); +} + +static void +act_store_rollback(const struct sieve_action_exec_env *aenv, void *tr_context, + bool success) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct act_store_transaction *trans = + (struct act_store_transaction *)tr_context; + + if (trans == NULL) + return; + + e_debug(aenv->event, "Roll back storing into mailbox %s", + trans->mailbox_identifier); + + i_assert(trans->box != NULL); + + if (!success) { + eenv->exec_status->last_storage = + mailbox_get_storage(trans->box); + eenv->exec_status->store_failed = TRUE; + } + + /* Log status */ + act_store_log_status(trans, aenv, TRUE, success); + + /* Rollback mailbox transaction and clean up */ + act_store_cleanup(trans); +} + +/* + * Redirect action + */ + +int sieve_act_redirect_add_to_result(const struct sieve_runtime_env *renv, + const char *name, + struct sieve_side_effects_list *seffects, + const struct smtp_address *to_address) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct sieve_instance *svinst = eenv->svinst; + struct act_redirect_context *act; + pool_t pool; + + pool = sieve_result_pool(renv->result); + act = p_new(pool, struct act_redirect_context, 1); + act->to_address = smtp_address_clone(pool, to_address); + + if (sieve_result_add_action(renv, NULL, name, &act_redirect, seffects, + (void *)act, svinst->max_redirects, + TRUE) < 0) + return SIEVE_EXEC_FAILURE; + + return SIEVE_EXEC_OK; +} + +/* + * Action utility functions + */ + +/* Rejecting the mail */ + +static int +sieve_action_do_reject_mail(const struct sieve_action_exec_env *aenv, + const struct smtp_address *recipient, + const char *reason) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_instance *svinst = eenv->svinst; + const struct sieve_script_env *senv = eenv->scriptenv; + const struct sieve_message_data *msgdata = eenv->msgdata; + const struct smtp_address *sender, *orig_recipient; + struct istream *input; + struct ostream *output; + struct sieve_smtp_context *sctx; + const char *new_msgid, *boundary, *error; + string_t *hdr; + int ret; + + sender = sieve_message_get_sender(aenv->msgctx); + orig_recipient = msgdata->envelope.rcpt_params->orcpt.addr; + + sctx = sieve_smtp_start_single(senv, sender, NULL, &output); + + /* Just to be sure */ + if (sctx == NULL) { + sieve_result_global_warning( + aenv, "reject action has no means to send mail"); + return SIEVE_EXEC_OK; + } + + new_msgid = sieve_message_get_new_id(svinst); + boundary = t_strdup_printf("%s/%s", my_pid, svinst->hostname); + + hdr = t_str_new(512); + rfc2822_header_write(hdr, "X-Sieve", SIEVE_IMPLEMENTATION); + rfc2822_header_write(hdr, "Message-ID", new_msgid); + rfc2822_header_write(hdr, "Date", message_date_create(ioloop_time)); + rfc2822_header_write(hdr, "From", sieve_get_postmaster_address(senv)); + rfc2822_header_printf(hdr, "To", "<%s>", smtp_address_encode(sender)); + rfc2822_header_write(hdr, "Subject", "Automatically rejected mail"); + rfc2822_header_write(hdr, "Auto-Submitted", "auto-replied (rejected)"); + rfc2822_header_write(hdr, "Precedence", "bulk"); + + rfc2822_header_write(hdr, "MIME-Version", "1.0"); + rfc2822_header_printf(hdr, "Content-Type", + "multipart/report; " + "report-type=disposition-notification;\r\n" + "boundary=\"%s\"", boundary); + + str_append(hdr, "\r\nThis is a MIME-encapsulated message\r\n\r\n"); + + /* Human readable status report */ + str_printfa(hdr, "--%s\r\n", boundary); + rfc2822_header_write(hdr, "Content-Type", "text/plain; charset=utf-8"); + rfc2822_header_write(hdr, "Content-Disposition", "inline"); + rfc2822_header_write(hdr, "Content-Transfer-Encoding", "8bit"); + + str_printfa(hdr, "\r\nYour message to <%s> was automatically rejected:\r\n" + "%s\r\n", smtp_address_encode(recipient), reason); + + /* MDN status report */ + str_printfa(hdr, "--%s\r\n", boundary); + rfc2822_header_write(hdr, "Content-Type", + "message/disposition-notification"); + str_append(hdr, "\r\n"); + rfc2822_header_write(hdr, + "Reporting-UA: %s; Dovecot Mail Delivery Agent", + svinst->hostname); + if (orig_recipient != NULL) { + rfc2822_header_printf(hdr, "Original-Recipient", "rfc822; %s", + smtp_address_encode(orig_recipient)); + } + rfc2822_header_printf(hdr, "Final-Recipient", "rfc822; %s", + smtp_address_encode(recipient)); + + if (msgdata->id != NULL) + rfc2822_header_write(hdr, "Original-Message-ID", msgdata->id); + rfc2822_header_write(hdr, "Disposition", + "automatic-action/MDN-sent-automatically; deleted"); + str_append(hdr, "\r\n"); + + /* original message's headers */ + str_printfa(hdr, "--%s\r\n", boundary); + rfc2822_header_write(hdr, "Content-Type", "message/rfc822"); + str_append(hdr, "\r\n"); + o_stream_nsend(output, str_data(hdr), str_len(hdr)); + + if (mail_get_hdr_stream(msgdata->mail, NULL, &input) == 0) { + /* NOTE: If you add more headers, they need to be sorted. We'll + drop Content-Type because we're not including the message + body, and having a multipart Content-Type may confuse some + MIME parsers when they don't see the message boundaries. + */ + static const char *const exclude_headers[] = { + "Content-Type" + }; + + input = i_stream_create_header_filter( + input, HEADER_FILTER_EXCLUDE | HEADER_FILTER_NO_CR | + HEADER_FILTER_HIDE_BODY, + exclude_headers, N_ELEMENTS(exclude_headers), + *null_header_filter_callback, (void *)NULL); + o_stream_nsend_istream(output, input); + i_stream_unref(&input); + } + + str_truncate(hdr, 0); + str_printfa(hdr, "\r\n\r\n--%s--\r\n", boundary); + o_stream_nsend(output, str_data(hdr), str_len(hdr)); + + if ((ret = sieve_smtp_finish(sctx, &error)) <= 0) { + if (ret < 0) { + sieve_result_global_error(aenv, + "failed to send rejection message to <%s>: %s " + "(temporary failure)", + smtp_address_encode(sender), + str_sanitize(error, 512)); + } else { + sieve_result_global_log_error(aenv, + "failed to send rejection message to <%s>: %s " + "(permanent failure)", + smtp_address_encode(sender), + str_sanitize(error, 512)); + } + return SIEVE_EXEC_FAILURE; + } + + return SIEVE_EXEC_OK; +} + +int sieve_action_reject_mail(const struct sieve_action_exec_env *aenv, + const struct smtp_address *recipient, + const char *reason) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + const struct sieve_script_env *senv = eenv->scriptenv; + int result; + + T_BEGIN { + if (senv->reject_mail != NULL) { + result = (senv->reject_mail(senv, recipient, + reason) >= 0 ? + SIEVE_EXEC_OK : SIEVE_EXEC_FAILURE); + } else { + result = sieve_action_do_reject_mail(aenv, recipient, + reason); + } + } T_END; + + return result; +} + +/* + * Mailbox + */ + +bool sieve_mailbox_check_name(const char *mailbox, const char **error_r) +{ + if (!uni_utf8_str_is_valid(mailbox)) { + *error_r = "invalid utf-8"; + return FALSE; + } + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/sieve-actions.h b/pigeonhole/src/lib-sieve/sieve-actions.h new file mode 100644 index 0000000..f1a447f --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-actions.h @@ -0,0 +1,311 @@ +#ifndef SIEVE_ACTIONS_H +#define SIEVE_ACTIONS_H + +#include "lib.h" +#include "mail-types.h" +#include "mail-error.h" + +#include "sieve-common.h" +#include "sieve-objects.h" +#include "sieve-extensions.h" +#include "sieve-execute.h" + +/* + * Action execution environment + */ + +struct sieve_action_exec_env { + const struct sieve_execute_env *exec_env; + struct sieve_result_execution *rexec; + const struct sieve_action *action; + struct event *event; + + struct sieve_result *result; + struct sieve_error_handler *ehandler; + + struct sieve_message_context *msgctx; +}; + +struct event_passthrough * +sieve_action_create_finish_event(const struct sieve_action_exec_env *aenv); + +/* + * Action flags + */ + +enum sieve_action_flags { + SIEVE_ACTFLAG_TRIES_DELIVER = (1 << 0), + SIEVE_ACTFLAG_SENDS_RESPONSE = (1 << 1), + SIEVE_ACTFLAG_MAIL_STORAGE = (1 << 2) +}; + +/* + * Action definition + */ + +struct sieve_action_def { + const char *name; + unsigned int flags; + + bool (*equals)(const struct sieve_script_env *senv, + const struct sieve_action *act1, + const struct sieve_action *act2); + + /* Result verification */ + int (*check_duplicate)(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other); + int (*check_conflict)(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other); + + /* Result printing */ + void (*print)(const struct sieve_action *action, + const struct sieve_result_print_env *penv, bool *keep); + + /* Result execution */ + int (*start)(const struct sieve_action_exec_env *aenv, + void **tr_context); + int (*execute)(const struct sieve_action_exec_env *aenv, + void *tr_context, bool *keep); + int (*commit)(const struct sieve_action_exec_env *aenv, + void *tr_context); + void (*rollback)(const struct sieve_action_exec_env *aenv, + void *tr_context, bool success); + void (*finish)(const struct sieve_action_exec_env *aenv, + void *tr_context, int status); +}; + +/* + * Action instance + */ + +struct sieve_action { + const struct sieve_action_def *def; + const struct sieve_extension *ext; + struct event *event; + + const char *name; + const char *location; + unsigned int exec_seq; + void *context; + struct mail *mail; + + bool keep:1; +}; + +#define sieve_action_is(act, definition) ((act)->def == &(definition)) +#define sieve_action_name(act) ((act)->name) + +bool sieve_action_is_executed(const struct sieve_action *act, + struct sieve_result *result); + +/* + * Action side effects + */ + +/* Side effect object */ + +struct sieve_side_effect_def { + struct sieve_object_def obj_def; + + /* Precedence (side effects with higher value are executed first) */ + + unsigned int precedence; + + /* The action it is supposed to link to */ + const struct sieve_action_def *to_action; + + /* Context coding */ + bool (*dump_context)(const struct sieve_side_effect *seffect, + const struct sieve_dumptime_env *renv, + sieve_size_t *address); + int (*read_context)(const struct sieve_side_effect *seffect, + const struct sieve_runtime_env *renv, + sieve_size_t *address, void **se_context); + + /* Result verification */ + int (*merge)(const struct sieve_runtime_env *renv, + const struct sieve_action *action, + const struct sieve_side_effect *old_seffect, + const struct sieve_side_effect *new_seffect, + void **old_context); + + /* Result printing */ + void (*print)(const struct sieve_side_effect *seffect, + const struct sieve_action *action, + const struct sieve_result_print_env *penv, bool *keep); + + /* Result execution */ + + int (*pre_execute)(const struct sieve_side_effect *seffect, + const struct sieve_action_exec_env *aenv, + void *tr_context, void **se_tr_context); + int (*post_execute)(const struct sieve_side_effect *seffect, + const struct sieve_action_exec_env *aenv, + void *tr_context, void *se_tr_context, bool *keep); + void (*post_commit)(const struct sieve_side_effect *seffect, + const struct sieve_action_exec_env *aenv, + void *tr_context, void *se_tr_context, + int commit_status); + void (*rollback)(const struct sieve_side_effect *seffect, + const struct sieve_action_exec_env *aenv, + void *tr_context, void *se_tr_context, bool success); +}; + +struct sieve_side_effect { + struct sieve_object object; + + const struct sieve_side_effect_def *def; + + void *context; +}; + +/* + * Side effect operand + */ + +#define SIEVE_EXT_DEFINE_SIDE_EFFECT(SEF) SIEVE_EXT_DEFINE_OBJECT(SEF) +#define SIEVE_EXT_DEFINE_SIDE_EFFECTS(SEFS) SIEVE_EXT_DEFINE_OBJECTS(SEFS) + +#define SIEVE_OPT_SIDE_EFFECT (-1) + +extern const struct sieve_operand_class sieve_side_effect_operand_class; + +static inline void +sieve_opr_side_effect_emit(struct sieve_binary_block *sblock, + const struct sieve_extension *ext, + const struct sieve_side_effect_def *seff) +{ + sieve_opr_object_emit(sblock, ext, &seff->obj_def); +} + +bool sieve_opr_side_effect_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +int sieve_opr_side_effect_read(const struct sieve_runtime_env *renv, + sieve_size_t *address, + struct sieve_side_effect *seffect); + +/* + * Optional operands + */ + +int sieve_action_opr_optional_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address, signed int *opt_code); + +int sieve_action_opr_optional_read(const struct sieve_runtime_env *renv, + sieve_size_t *address, signed int *opt_code, + int *exec_status, + struct sieve_side_effects_list **list); + +/* + * Core actions + */ + +extern const struct sieve_action_def act_redirect; +extern const struct sieve_action_def act_store; +extern const struct sieve_action_def act_discard; + +/* + * Store action + */ + +struct act_store_context { + /* Folder name represented in utf-8 */ + const char *mailbox; +}; + +struct act_store_transaction { + struct act_store_context *context; + struct mailbox *box; + struct mailbox_transaction_context *mail_trans; + + const char *mailbox_name; + const char *mailbox_identifier; + + const char *error; + enum mail_error error_code; + + enum mail_flags flags; + ARRAY_TYPE(const_string) keywords; + + bool flags_altered:1; + bool disabled:1; + bool redundant:1; +}; + +int sieve_act_store_add_to_result(const struct sieve_runtime_env *renv, + const char *name, + struct sieve_side_effects_list *seffects, + const char *folder); + +void sieve_act_store_add_flags(const struct sieve_action_exec_env *aenv, + void *tr_context, const char *const *keywords, + enum mail_flags flags); + +void sieve_act_store_get_storage_error(const struct sieve_action_exec_env *aenv, + struct act_store_transaction *trans); + +/* + * Redirect action + */ + +struct act_redirect_context { + const struct smtp_address *to_address; +}; + +int sieve_act_redirect_add_to_result(const struct sieve_runtime_env *renv, + const char *name, + struct sieve_side_effects_list *seffects, + const struct smtp_address *to_address); + +/* + * Checking for duplicates + */ + +static inline bool +sieve_action_duplicate_check_available(const struct sieve_action_exec_env *aenv) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + + return sieve_execute_duplicate_check_available(eenv); +} + +static inline int +sieve_action_duplicate_check(const struct sieve_action_exec_env *aenv, + const void *id, size_t id_size, + bool *duplicate_r) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + + return sieve_execute_duplicate_check(eenv, id, id_size, + duplicate_r); +} + +static inline void +sieve_action_duplicate_mark(const struct sieve_action_exec_env *aenv, + const void *id, size_t id_size, time_t time) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + + return sieve_execute_duplicate_mark(eenv, id, id_size, time); +} + +/* + * Action utility functions + */ + +/* Rejecting mail */ + +int sieve_action_reject_mail(const struct sieve_action_exec_env *aenv, + const struct smtp_address *recipient, + const char *reason); + +/* + * Mailbox + */ + +// FIXME: move this to a more appropriate location +bool sieve_mailbox_check_name(const char *mailbox, const char **error_r); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-address-parts.c b/pigeonhole/src/lib-sieve/sieve-address-parts.c new file mode 100644 index 0000000..a856e20 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-address-parts.c @@ -0,0 +1,495 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "compat.h" +#include "mempool.h" +#include "hash.h" +#include "array.h" +#include "str-sanitize.h" + +#include "sieve-extensions.h" +#include "sieve-code.h" +#include "sieve-address.h" +#include "sieve-commands.h" +#include "sieve-binary.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "sieve-address-parts.h" + +#include <string.h> + +/* + * Default address parts + */ + +const struct sieve_address_part_def *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); + +/* + * Address-part 'extension' + */ + +static bool addrp_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def address_part_extension = { + .name = "@address-parts", + .validator_load = addrp_validator_load +}; + +/* + * Validator context: + * name-based address-part registry. + */ + +static struct sieve_validator_object_registry *_get_object_registry +(struct sieve_validator *valdtr) +{ + struct sieve_instance *svinst; + const struct sieve_extension *adrp_ext; + + svinst = sieve_validator_svinst(valdtr); + adrp_ext = sieve_get_address_part_extension(svinst); + return sieve_validator_object_registry_get(valdtr, adrp_ext); +} + +void sieve_address_part_register +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + const struct sieve_address_part_def *addrp_def) +{ + struct sieve_validator_object_registry *regs = _get_object_registry(valdtr); + + sieve_validator_object_registry_add(regs, ext, &addrp_def->obj_def); +} + +static bool sieve_address_part_exists +(struct sieve_validator *valdtr, const char *identifier) +{ + struct sieve_validator_object_registry *regs = _get_object_registry(valdtr); + + return sieve_validator_object_registry_find(regs, identifier, NULL); +} + +static const struct sieve_address_part *sieve_address_part_create_instance +(struct sieve_validator *valdtr, struct sieve_command *cmd, + const char *identifier) +{ + struct sieve_validator_object_registry *regs = _get_object_registry(valdtr); + struct sieve_object object; + struct sieve_address_part *addrp; + + if ( !sieve_validator_object_registry_find(regs, identifier, &object) ) + return NULL; + + addrp = p_new(sieve_command_pool(cmd), struct sieve_address_part, 1); + addrp->object = object; + addrp->def = (const struct sieve_address_part_def *) object.def; + + return addrp; +} + +static bool addrp_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + struct sieve_validator_object_registry *regs = + sieve_validator_object_registry_init(valdtr, ext); + unsigned int i; + + /* Register core address-parts */ + for ( i = 0; i < sieve_core_address_parts_count; i++ ) { + sieve_validator_object_registry_add + (regs, NULL, &(sieve_core_address_parts[i]->obj_def)); + } + + return TRUE; +} + +void sieve_address_parts_link_tags +(struct sieve_validator *valdtr, struct sieve_command_registration *cmd_reg, + int id_code) +{ + struct sieve_instance *svinst; + const struct sieve_extension *adrp_ext; + + svinst = sieve_validator_svinst(valdtr); + adrp_ext = sieve_get_address_part_extension(svinst); + + sieve_validator_register_tag + (valdtr, cmd_reg, adrp_ext, &address_part_tag, id_code); +} + +/* + * Address-part tagged argument + */ + +/* Forward declarations */ + +static bool tag_address_part_is_instance_of + (struct sieve_validator *valdtr, struct sieve_command *cmd, + const struct sieve_extension *ext, const char *identifier, void **data); +static bool tag_address_part_validate + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool tag_address_part_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd); + +/* Argument object */ + +const struct sieve_argument_def address_part_tag = { + .identifier = "ADDRESS-PART", + .is_instance_of = tag_address_part_is_instance_of, + .validate = tag_address_part_validate, + .generate = tag_address_part_generate +}; + +/* Argument implementation */ + +static bool tag_address_part_is_instance_of +(struct sieve_validator *valdtr, struct sieve_command *cmd, + const struct sieve_extension *ext ATTR_UNUSED, const char *identifier, + void **data) +{ + const struct sieve_address_part *addrp; + + if ( data == NULL ) + return sieve_address_part_exists(valdtr, identifier); + + if ( (addrp=sieve_address_part_create_instance + (valdtr, cmd, identifier)) == NULL ) + return FALSE; + + *data = (void *) addrp; + return TRUE; +} + +static bool tag_address_part_validate +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_ast_argument **arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + /* NOTE: Currenly trivial, but might need to allow for further validation for + * future extensions. + */ + + /* Syntax: + * ":localpart" / ":domain" / ":all" (subject to extension) + */ + + /* Skip tag */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +static bool tag_address_part_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + struct sieve_address_part *addrp = + (struct sieve_address_part *) arg->argument->data; + + sieve_opr_address_part_emit(cgenv->sblock, addrp); + + return TRUE; +} + +/* + * Address-part operand + */ + +const struct sieve_operand_class sieve_address_part_operand_class = + { "address part" }; + +static const struct sieve_extension_objects core_address_parts = + SIEVE_EXT_DEFINE_MATCH_TYPES(sieve_core_address_parts); + +const struct sieve_operand_def address_part_operand = { + .name = "address-part", + .code = SIEVE_OPERAND_ADDRESS_PART, + .class = &sieve_address_part_operand_class, + .interface = &core_address_parts +}; + +/* + * Address-part string list + */ + +static int sieve_address_part_stringlist_next_item + (struct sieve_stringlist *_strlist, string_t **str_r); +static void sieve_address_part_stringlist_reset + (struct sieve_stringlist *_strlist); +static int sieve_address_part_stringlist_get_length + (struct sieve_stringlist *_strlist); +static void sieve_address_part_stringlist_set_trace +(struct sieve_stringlist *_strlist, bool trace); + +struct sieve_address_part_stringlist { + struct sieve_stringlist strlist; + + const struct sieve_address_part *addrp; + struct sieve_address_list *addresses; +}; + +struct sieve_stringlist *sieve_address_part_stringlist_create +(const struct sieve_runtime_env *renv, const struct sieve_address_part *addrp, + struct sieve_address_list *addresses) +{ + struct sieve_address_part_stringlist *strlist; + + strlist = t_new(struct sieve_address_part_stringlist, 1); + strlist->strlist.runenv = renv; + strlist->strlist.next_item = sieve_address_part_stringlist_next_item; + strlist->strlist.reset = sieve_address_part_stringlist_reset; + strlist->strlist.get_length = sieve_address_part_stringlist_get_length; + strlist->strlist.set_trace = sieve_address_part_stringlist_set_trace; + + strlist->addrp = addrp; + strlist->addresses = addresses; + + return &strlist->strlist; +} + +static int sieve_address_part_stringlist_next_item + (struct sieve_stringlist *_strlist, string_t **str_r) +{ + struct sieve_address_part_stringlist *strlist = + (struct sieve_address_part_stringlist *)_strlist; + struct smtp_address item; + string_t *item_unparsed; + int ret; + + *str_r = NULL; + + while ( *str_r == NULL ) { + if ( (ret=sieve_address_list_next_item + (strlist->addresses, &item, &item_unparsed)) <= 0 ) + return ret; + + if ( item.localpart == NULL ) { + if ( item_unparsed != NULL ) { + if ( _strlist->trace ) { + sieve_runtime_trace(_strlist->runenv, 0, + "extracting `%s' part from non-address value `%s'", + sieve_address_part_name(strlist->addrp), + str_sanitize(str_c(item_unparsed), 80)); + } + + if ( str_len(item_unparsed) == 0 || + sieve_address_part_is(strlist->addrp, all_address_part) ) + *str_r = item_unparsed; + } + } else { + const struct sieve_address_part *addrp = strlist->addrp; + const char *part = NULL; + + if ( _strlist->trace ) { + sieve_runtime_trace(_strlist->runenv, 0, + "extracting `%s' part from address %s", + sieve_address_part_name(strlist->addrp), + smtp_address_encode_path(&item)); + } + + if ( addrp->def != NULL && addrp->def->extract_from != NULL ) + part = addrp->def->extract_from(addrp, &item); + + if ( part != NULL ) + *str_r = t_str_new_const(part, strlen(part)); + } + } + + return 1; +} + +static void sieve_address_part_stringlist_reset + (struct sieve_stringlist *_strlist) +{ + struct sieve_address_part_stringlist *strlist = + (struct sieve_address_part_stringlist *)_strlist; + + sieve_address_list_reset(strlist->addresses); +} + +static int sieve_address_part_stringlist_get_length + (struct sieve_stringlist *_strlist) +{ + struct sieve_address_part_stringlist *strlist = + (struct sieve_address_part_stringlist *)_strlist; + + return sieve_address_list_get_length(strlist->addresses); +} + +static void sieve_address_part_stringlist_set_trace +(struct sieve_stringlist *_strlist, bool trace) +{ + struct sieve_address_part_stringlist *strlist = + (struct sieve_address_part_stringlist *)_strlist; + + sieve_address_list_set_trace(strlist->addresses, trace); +} + +/* + * Default ADDRESS-PART, MATCH-TYPE, COMPARATOR access + */ + +int sieve_addrmatch_opr_optional_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address, + signed int *opt_code) +{ + signed int _opt_code = 0; + bool final = FALSE, opok = TRUE; + + if ( opt_code == NULL ) { + opt_code = &_opt_code; + final = TRUE; + } + + while ( opok ) { + int opt; + + if ( (opt=sieve_opr_optional_dump(denv, address, opt_code)) <= 0 ) + return opt; + + switch ( *opt_code ) { + case SIEVE_MATCH_OPT_COMPARATOR: + opok = sieve_opr_comparator_dump(denv, address); + break; + case SIEVE_MATCH_OPT_MATCH_TYPE: + opok = sieve_opr_match_type_dump(denv, address); + break; + case SIEVE_AM_OPT_ADDRESS_PART: + opok = sieve_opr_address_part_dump(denv, address); + break; + default: + return ( final ? -1 : 1 ); + } + } + + return -1; +} + +int sieve_addrmatch_opr_optional_read +(const struct sieve_runtime_env *renv, sieve_size_t *address, + signed int *opt_code, int *exec_status, struct sieve_address_part *addrp, + struct sieve_match_type *mtch, struct sieve_comparator *cmp) +{ + signed int _opt_code = 0; + bool final = FALSE; + int status = SIEVE_EXEC_OK; + + if ( opt_code == NULL ) { + opt_code = &_opt_code; + final = TRUE; + } + + if ( exec_status != NULL ) + *exec_status = SIEVE_EXEC_OK; + + while ( status == SIEVE_EXEC_OK ) { + int opt; + + if ( (opt=sieve_opr_optional_read(renv, address, opt_code)) <= 0 ){ + if ( opt < 0 && exec_status != NULL ) + *exec_status = SIEVE_EXEC_BIN_CORRUPT; + return opt; + } + + switch ( *opt_code ) { + case SIEVE_MATCH_OPT_COMPARATOR: + if (cmp == NULL) { + sieve_runtime_trace_error(renv, "unexpected comparator operand"); + if ( exec_status != NULL ) + *exec_status = SIEVE_EXEC_BIN_CORRUPT; + return -1; + } + status = sieve_opr_comparator_read(renv, address, cmp); + break; + case SIEVE_MATCH_OPT_MATCH_TYPE: + if (mtch == NULL) { + sieve_runtime_trace_error(renv, "unexpected match-type operand"); + if ( exec_status != NULL ) + *exec_status = SIEVE_EXEC_BIN_CORRUPT; + return -1; + } + status = sieve_opr_match_type_read(renv, address, mtch); + break; + case SIEVE_AM_OPT_ADDRESS_PART: + if (addrp == NULL) { + sieve_runtime_trace_error(renv, "unexpected address-part operand"); + if ( exec_status != NULL ) + *exec_status = SIEVE_EXEC_BIN_CORRUPT; + return -1; + } + status = sieve_opr_address_part_read(renv, address, addrp); + break; + default: + if ( final ) { + sieve_runtime_trace_error(renv, "invalid optional operand"); + if ( exec_status != NULL ) + *exec_status = SIEVE_EXEC_BIN_CORRUPT; + return -1; + } + return 1; + } + } + + if ( exec_status != NULL ) + *exec_status = status; + return -1; +} + +/* + * Core address-part modifiers + */ + +static const char *addrp_all_extract_from +(const struct sieve_address_part *addrp ATTR_UNUSED, + const struct smtp_address *address) +{ + if ( address->localpart == NULL ) + return NULL; + return smtp_address_encode(address); +} + +static const char *addrp_domain_extract_from +(const struct sieve_address_part *addrp ATTR_UNUSED, + const struct smtp_address *address) +{ + return address->domain; +} + +static const char *addrp_localpart_extract_from +(const struct sieve_address_part *addrp ATTR_UNUSED, + const struct smtp_address *address) +{ + return address->localpart; +} + +const struct sieve_address_part_def all_address_part = { + SIEVE_OBJECT("all", + &address_part_operand, SIEVE_ADDRESS_PART_ALL), + .extract_from = addrp_all_extract_from +}; + +const struct sieve_address_part_def local_address_part = { + SIEVE_OBJECT("localpart", + &address_part_operand, SIEVE_ADDRESS_PART_LOCAL), + .extract_from = addrp_localpart_extract_from +}; + +const struct sieve_address_part_def domain_address_part = { + SIEVE_OBJECT("domain", + &address_part_operand, SIEVE_ADDRESS_PART_DOMAIN), + .extract_from = addrp_domain_extract_from +}; + diff --git a/pigeonhole/src/lib-sieve/sieve-address-parts.h b/pigeonhole/src/lib-sieve/sieve-address-parts.h new file mode 100644 index 0000000..c774dc3 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-address-parts.h @@ -0,0 +1,135 @@ +#ifndef SIEVE_ADDRESS_PARTS_H +#define SIEVE_ADDRESS_PARTS_H + +#include "message-address.h" + +#include "sieve-common.h" +#include "sieve-match.h" +#include "sieve-extensions.h" +#include "sieve-objects.h" + +/* + * Address part definition + */ + +struct sieve_address_part_def { + struct sieve_object_def obj_def; + + const char *(*extract_from) + (const struct sieve_address_part *addrp, + const struct smtp_address *address); +}; + +/* + * Address part instance + */ + +struct sieve_address_part { + struct sieve_object object; + + const struct sieve_address_part_def *def; +}; + +#define SIEVE_ADDRESS_PART_DEFAULT(definition) \ + { SIEVE_OBJECT_DEFAULT(definition), &(definition) }; + +#define sieve_address_part_name(addrp) \ + ( (addrp)->object.def->identifier ) +#define sieve_address_part_is(addrp, definition) \ + ( (addrp)->def == &(definition) ) + +/* + * Core address parts + */ + +enum sieve_address_part_code { + SIEVE_ADDRESS_PART_ALL, + SIEVE_ADDRESS_PART_LOCAL, + SIEVE_ADDRESS_PART_DOMAIN, + SIEVE_ADDRESS_PART_CUSTOM +}; + +extern const struct sieve_address_part_def all_address_part; +extern const struct sieve_address_part_def local_address_part; +extern const struct sieve_address_part_def domain_address_part; + +/* + * Address part tagged argument + */ + +extern const struct sieve_argument_def address_part_tag; + +void sieve_address_parts_link_tags + (struct sieve_validator *valdtr, struct sieve_command_registration *cmd_reg, + int id_code); + +/* + * Address part registry + */ + +void sieve_address_part_register + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + const struct sieve_address_part_def *addrp); + +/* + * Address part operand + */ + +extern const struct sieve_operand_def address_part_operand; +extern const struct sieve_operand_class sieve_address_part_operand_class; + +#define SIEVE_EXT_DEFINE_ADDRESS_PART(OP) SIEVE_EXT_DEFINE_OBJECT(OP) +#define SIEVE_EXT_DEFINE_ADDRESS_PARTS(OPS) SIEVE_EXT_DEFINE_OBJECTS(OPS) + +static inline void sieve_opr_address_part_emit +(struct sieve_binary_block *sblock, const struct sieve_address_part *addrp) +{ + sieve_opr_object_emit(sblock, addrp->object.ext, addrp->object.def); +} + +static inline bool sieve_opr_address_part_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + return sieve_opr_object_dump + (denv, &sieve_address_part_operand_class, address, NULL); +} + +static inline int sieve_opr_address_part_read +(const struct sieve_runtime_env *renv, sieve_size_t *address, + struct sieve_address_part *addrp) +{ + if ( !sieve_opr_object_read + (renv, &sieve_address_part_operand_class, address, &addrp->object) ) + return SIEVE_EXEC_BIN_CORRUPT; + + addrp->def = (const struct sieve_address_part_def *) addrp->object.def; + return SIEVE_EXEC_OK; +} + +/* + * Address-part string list + */ + +struct sieve_stringlist *sieve_address_part_stringlist_create + (const struct sieve_runtime_env *renv, const struct sieve_address_part *addrp, + struct sieve_address_list *addresses); + +/* + * Match utility + */ + +enum sieve_addrmatch_opt_operand { + SIEVE_AM_OPT_ADDRESS_PART = SIEVE_MATCH_OPT_LAST, + SIEVE_AM_OPT_LAST +}; + +int sieve_addrmatch_opr_optional_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address, + signed int *opt_code); + +int sieve_addrmatch_opr_optional_read + (const struct sieve_runtime_env *renv, sieve_size_t *address, + signed int *opt_code, int *exec_status, struct sieve_address_part *addrp, + struct sieve_match_type *mtch, struct sieve_comparator *cmp); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-address-source.c b/pigeonhole/src/lib-sieve/sieve-address-source.c new file mode 100644 index 0000000..a5ec6f6 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-address-source.c @@ -0,0 +1,119 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-settings.h" +#include "sieve-address.h" +#include "sieve-message.h" + +#include "sieve-address-source.h" + +bool sieve_address_source_parse +(pool_t pool, const char *value, + struct sieve_address_source *asrc) +{ + struct smtp_address *address; + const char *error; + size_t val_len; + + i_zero(asrc); + + value = t_str_trim(value, "\t "); + value = t_str_lcase(value); + val_len = strlen(value); + if ( val_len > 0 ) { + if ( strcmp(value, "default") == 0 ) { + asrc->type = SIEVE_ADDRESS_SOURCE_DEFAULT; + } else if ( strcmp(value, "sender") == 0 ) { + asrc->type = SIEVE_ADDRESS_SOURCE_SENDER; + } else if ( strcmp(value, "recipient") == 0 ) { + asrc->type = SIEVE_ADDRESS_SOURCE_RECIPIENT; + } else if ( strcmp(value, "orig_recipient") == 0 ) { + asrc->type = SIEVE_ADDRESS_SOURCE_ORIG_RECIPIENT; + } else if ( strcmp(value, "user_email") == 0 ) { + asrc->type = SIEVE_ADDRESS_SOURCE_USER_EMAIL; + } else if ( strcmp(value, "postmaster") == 0 ) { + asrc->type = SIEVE_ADDRESS_SOURCE_POSTMASTER; + } else if ( smtp_address_parse_path(pool_datastack_create(), value, + SMTP_ADDRESS_PARSE_FLAG_ALLOW_EMPTY, &address, &error) >= 0 ) { + asrc->type = SIEVE_ADDRESS_SOURCE_EXPLICIT; + asrc->address = smtp_address_clone(pool, address); + } else { + return FALSE; + } + } + return TRUE; +} + +bool sieve_address_source_parse_from_setting +(struct sieve_instance *svinst, pool_t pool, + const char *setting, struct sieve_address_source *asrc) +{ + const char *value; + + value = sieve_setting_get(svinst, setting); + if ( value == NULL ) + return FALSE; + + if ( !sieve_address_source_parse(pool, value, asrc) ) { + e_warning(svinst->event, "Invalid value for setting '%s': '%s'", + setting, value); + return FALSE; + } + return TRUE; +} + +int sieve_address_source_get_address +(struct sieve_address_source *asrc, + struct sieve_instance *svinst, + const struct sieve_script_env *senv, + struct sieve_message_context *msgctx, + enum sieve_execute_flags flags, + const struct smtp_address **addr_r) +{ + enum sieve_address_source_type type = asrc->type; + + if ( type == SIEVE_ADDRESS_SOURCE_USER_EMAIL && + svinst->user_email == NULL ) + type = SIEVE_ADDRESS_SOURCE_RECIPIENT; + + if ( (flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) != 0 ) { + switch ( type ) { + case SIEVE_ADDRESS_SOURCE_SENDER: + case SIEVE_ADDRESS_SOURCE_RECIPIENT: + case SIEVE_ADDRESS_SOURCE_ORIG_RECIPIENT: + /* We have no envelope */ + type = SIEVE_ADDRESS_SOURCE_DEFAULT; + break; + default: + break; + } + } + + switch ( type ) { + case SIEVE_ADDRESS_SOURCE_SENDER: + *addr_r = sieve_message_get_sender(msgctx); + return 1; + case SIEVE_ADDRESS_SOURCE_RECIPIENT: + *addr_r = sieve_message_get_final_recipient(msgctx); + return 1; + case SIEVE_ADDRESS_SOURCE_ORIG_RECIPIENT: + *addr_r = sieve_message_get_orig_recipient(msgctx); + return 1; + case SIEVE_ADDRESS_SOURCE_USER_EMAIL: + *addr_r = svinst->user_email; + return 1; + case SIEVE_ADDRESS_SOURCE_POSTMASTER: + *addr_r = sieve_get_postmaster_smtp(senv); + return 1; + case SIEVE_ADDRESS_SOURCE_EXPLICIT: + *addr_r = asrc->address; + return 1; + case SIEVE_ADDRESS_SOURCE_DEFAULT: + break; + } + return 0; +} diff --git a/pigeonhole/src/lib-sieve/sieve-address-source.h b/pigeonhole/src/lib-sieve/sieve-address-source.h new file mode 100644 index 0000000..fac4b49 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-address-source.h @@ -0,0 +1,36 @@ +#ifndef SIEVE_ADDRESS_SOURCE_H +#define SIEVE_ADDRESS_SOURCE_H + +#include "sieve-common.h" + +enum sieve_address_source_type { + SIEVE_ADDRESS_SOURCE_DEFAULT = 0, + SIEVE_ADDRESS_SOURCE_SENDER, + SIEVE_ADDRESS_SOURCE_RECIPIENT, + SIEVE_ADDRESS_SOURCE_ORIG_RECIPIENT, + SIEVE_ADDRESS_SOURCE_USER_EMAIL, + SIEVE_ADDRESS_SOURCE_POSTMASTER, + SIEVE_ADDRESS_SOURCE_EXPLICIT +}; + +struct sieve_address_source { + enum sieve_address_source_type type; + const struct smtp_address *address; +}; + +bool sieve_address_source_parse + (pool_t pool, const char *value, + struct sieve_address_source *asrc); +bool sieve_address_source_parse_from_setting + (struct sieve_instance *svinst, pool_t pool, + const char *setting, struct sieve_address_source *asrc); + +int sieve_address_source_get_address + (struct sieve_address_source *asrc, + struct sieve_instance *svinst, + const struct sieve_script_env *senv, + struct sieve_message_context *msgctx, + enum sieve_execute_flags flags, + const struct smtp_address **addr_r); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-address.c b/pigeonhole/src/lib-sieve/sieve-address.c new file mode 100644 index 0000000..f9456f8 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-address.c @@ -0,0 +1,558 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" +#include "rfc822-parser.h" +#include "message-address.h" + +#include "sieve-common.h" +#include "sieve-runtime-trace.h" + +#include "sieve-address.h" + +#include <ctype.h> + +/* + * Header address list + */ + +/* Forward declarations */ + +static int +sieve_header_address_list_next_string_item(struct sieve_stringlist *_strlist, + string_t **str_r); +static int +sieve_header_address_list_next_item(struct sieve_address_list *_addrlist, + struct smtp_address *addr_r, + string_t **unparsed_r); +static void +sieve_header_address_list_reset(struct sieve_stringlist *_strlist); +static void +sieve_header_address_list_set_trace(struct sieve_stringlist *_strlist, + bool trace); + +/* Stringlist object */ + +struct sieve_header_address_list { + struct sieve_address_list addrlist; + + struct sieve_stringlist *field_values; + const struct message_address *cur_address; +}; + +struct sieve_address_list * +sieve_header_address_list_create(const struct sieve_runtime_env *renv, + struct sieve_stringlist *field_values) +{ + struct sieve_header_address_list *addrlist; + + addrlist = t_new(struct sieve_header_address_list, 1); + addrlist->addrlist.strlist.runenv = renv; + addrlist->addrlist.strlist.exec_status = SIEVE_EXEC_OK; + addrlist->addrlist.strlist.next_item = + sieve_header_address_list_next_string_item; + addrlist->addrlist.strlist.reset = sieve_header_address_list_reset; + addrlist->addrlist.strlist.set_trace = + sieve_header_address_list_set_trace; + addrlist->addrlist.next_item = sieve_header_address_list_next_item; + addrlist->field_values = field_values; + + return &addrlist->addrlist; +} + +static int +sieve_header_address_list_next_address( + struct sieve_header_address_list *addrlist, struct smtp_address *addr_r) +{ + struct smtp_address adummy; + int ret = 0; + + if (addr_r == NULL) + addr_r = &adummy; + + while (addrlist->cur_address != NULL) { + const struct message_address *aitem = addrlist->cur_address; + + addrlist->cur_address = addrlist->cur_address->next; + + if (!aitem->invalid_syntax && aitem->domain != NULL && + smtp_address_init_from_msg(addr_r, aitem) >= 0) + return 1; + ret = -1; + } + return ret; +} + +static int +sieve_header_address_list_next_item(struct sieve_address_list *_addrlist, + struct smtp_address *addr_r, + string_t **unparsed_r) +{ + struct sieve_header_address_list *addrlist = + (struct sieve_header_address_list *)_addrlist; + const struct sieve_runtime_env *runenv = _addrlist->strlist.runenv; + string_t *value_item = NULL; + bool trace = _addrlist->strlist.trace; + + if (addr_r != NULL) + smtp_address_init(addr_r, NULL, NULL); + if (unparsed_r != NULL) + *unparsed_r = NULL; + + for (;;) { + int ret; + + if ((ret = sieve_header_address_list_next_address( + addrlist, addr_r)) < 0 && + value_item != NULL) { + /* completely invalid address list is returned as-is */ + if (trace) { + sieve_runtime_trace( + runenv, 0, + "invalid address value `%s'", + str_sanitize(str_c(value_item), 80)); + } + if (unparsed_r != NULL) + *unparsed_r = value_item; + return 1; + } + if (ret > 0) { + if (trace) { + sieve_runtime_trace( + runenv, 0, + "address value `%s'", + str_sanitize(smtp_address_encode(addr_r), + 80)); + } + return 1; + } + + /* Read next header value from source list */ + if ((ret = sieve_stringlist_next_item(addrlist->field_values, + &value_item)) <= 0) + return ret; + if (str_len(value_item) == 0) { + /* empty header value is returned as-is */ + if (trace) { + sieve_runtime_trace(runenv, 0, + "empty address value"); + } + addrlist->cur_address = NULL; + if (unparsed_r != NULL) + *unparsed_r = value_item; + return 1; + } + + if (trace) { + sieve_runtime_trace( + runenv, 0, + "parsing address header value `%s'", + str_sanitize(str_c(value_item), 80)); + } + + addrlist->cur_address = message_address_parse( + pool_datastack_create(), + (const unsigned char *)str_data(value_item), + str_len(value_item), 256, 0); + } + i_unreached(); +} + +static int +sieve_header_address_list_next_string_item(struct sieve_stringlist *_strlist, + string_t **str_r) +{ + struct sieve_address_list *addrlist = + (struct sieve_address_list *)_strlist; + struct smtp_address addr; + int ret; + + if ((ret = sieve_header_address_list_next_item( + addrlist, &addr, str_r)) <= 0) + return ret; + + if (addr.localpart != NULL) { + const char *addr_str = smtp_address_encode(&addr); + + if (str_r != NULL) + *str_r = t_str_new_const(addr_str, strlen(addr_str)); + } + return 1; +} + +static void sieve_header_address_list_reset(struct sieve_stringlist *_strlist) +{ + struct sieve_header_address_list *addrlist = + (struct sieve_header_address_list *)_strlist; + + sieve_stringlist_reset(addrlist->field_values); + addrlist->cur_address = NULL; +} + +static void +sieve_header_address_list_set_trace(struct sieve_stringlist *_strlist, + bool trace) +{ + struct sieve_header_address_list *addrlist = + (struct sieve_header_address_list *)_strlist; + + sieve_stringlist_set_trace(addrlist->field_values, trace); +} + +/* + * RFC 2822 addresses + */ + +/* Mail message address according to RFC 2822 and implemented in the Dovecot + message address parser: + + address = mailbox / group + mailbox = name-addr / addr-spec + name-addr = [display-name] angle-addr + angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr + group = display-name ":" [mailbox-list / CFWS] ";" [CFWS] + display-name = phrase + + addr-spec = local-part "@" domain + local-part = dot-atom / quoted-string / obs-local-part + domain = dot-atom / domain-literal / obs-domain + domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS] + dcontent = dtext / quoted-pair + dtext = NO-WS-CTL / ; Non white space controls + %d33-90 / ; The rest of the US-ASCII + %d94-126 ; characters not including "[", + ; "]", or "\" + + atext = ALPHA / DIGIT / ; Any character except controls, + "!" / "#" / ; SP, and specials. + "$" / "%" / ; Used for atoms + "&" / "'" / + "*" / "+" / + "-" / "/" / + "=" / "?" / + "^" / "_" / + "`" / "{" / + "|" / "}" / + "~" + atom = [CFWS] 1*atext [CFWS] + dot-atom = [CFWS] dot-atom-text [CFWS] + dot-atom-text = 1*atext *("." 1*atext) + word = atom / quoted-string + phrase = 1*word / obs-phrase + + Message address specification as allowed bij the RFC 5228 SIEVE + specification: + sieve-address = addr-spec ; simple address + / phrase "<" addr-spec ">" ; name & addr-spec\ + + Which concisely is about equal to: + sieve-address = mailbox + */ + +/* + * Address parse context + */ + +struct sieve_message_address_parser { + struct rfc822_parser_context parser; + + string_t *str; + string_t *local_part; + string_t *domain; + + string_t *error; +}; + +/* + * Error handling + */ + +static inline void ATTR_FORMAT(2, 3) +sieve_address_error(struct sieve_message_address_parser *ctx, + const char *fmt, ...) +{ + va_list args; + + if (str_len(ctx->error) == 0) { + va_start(args, fmt); + str_vprintfa(ctx->error, fmt, args); + va_end(args); + } +} + +/* + Partial RFC 2822 address parser + + FIXME: lots of overlap with dovecot/src/lib-mail/message-parser.c + --> this implementation adds textual error reporting + MERGE! + */ + +static int check_local_part(struct sieve_message_address_parser *ctx) +{ + const unsigned char *p, *pend; + + p = str_data(ctx->local_part); + pend = p + str_len(ctx->local_part); + while (p < pend) { + if (*p < 0x20 || *p > 0x7e) + return -1; + p++; + } + return 0; +} + +static int parse_local_part(struct sieve_message_address_parser *ctx) +{ + int ret; + + /* + local-part = dot-atom / quoted-string / obs-local-part + obs-local-part = word *("." word) + */ + if (ctx->parser.data == ctx->parser.end) { + sieve_address_error(ctx, "empty local part"); + return -1; + } + + str_truncate(ctx->local_part, 0); + if (*ctx->parser.data == '"') { + ret = rfc822_parse_quoted_string(&ctx->parser, ctx->local_part); + } else { + ret = -1; + /* NOTE: this deviates from dot-atom syntax to allow some + Japanese mail addresses with dots at non-standard places to + be accepted. */ + do { + while (*ctx->parser.data == '.') { + str_append_c(ctx->local_part, '.'); + ctx->parser.data++; + if (ctx->parser.data == ctx->parser.end) { + /* @domain is missing, but local-part + parsing was successful */ + return 0; + } + ret = 1; + } + if (*ctx->parser.data == '@') + break; + ret = rfc822_parse_atom(&ctx->parser, ctx->local_part); + } while (ret > 0 && *ctx->parser.data == '.'); + } + + if (ret < 0 || check_local_part(ctx) < 0) { + sieve_address_error(ctx, "invalid local part"); + return -1; + } + return ret; +} + +static int parse_domain(struct sieve_message_address_parser *ctx) +{ + int ret; + + str_truncate(ctx->domain, 0); + if ((ret = rfc822_parse_domain(&ctx->parser, ctx->domain)) < 0) { + sieve_address_error(ctx, "invalid or missing domain"); + return -1; + } + + return ret; +} + +static int parse_addr_spec(struct sieve_message_address_parser *ctx) +{ + /* addr-spec = local-part "@" domain */ + int ret; + + if ((ret = parse_local_part(ctx)) < 0) + return ret; + + if (ret > 0 && *ctx->parser.data == '@') { + return parse_domain(ctx); + } + + sieve_address_error( + ctx, "invalid or lonely local part '%s' (expecting '@')", + str_sanitize(str_c(ctx->local_part), 80)); + return -1; +} + +static int parse_mailbox(struct sieve_message_address_parser *ctx) +{ + int ret; + const unsigned char *start; + + /* sieve-address = addr-spec ; simple address + / phrase "<" addr-spec ">" ; name & addr-spec + */ + + /* Record parser state in case we fail at our first attempt */ + start = ctx->parser.data; + + /* First try: phrase "<" addr-spec ">" ; name & addr-spec */ + str_truncate(ctx->str, 0); + if (rfc822_parse_phrase(&ctx->parser, ctx->str) <= 0 || + *ctx->parser.data != '<') { + /* Failed; try just bare addr-spec */ + ctx->parser.data = start; + return parse_addr_spec(ctx); + } + + /* "<" addr-spec ">" */ + ctx->parser.data++; + + if ((ret = rfc822_skip_lwsp(&ctx->parser)) <= 0) { + if (ret < 0) + sieve_address_error(ctx, "invalid characters after <"); + return ret; + } + + if (parse_addr_spec(ctx) < 0) + return -1; + + if (*ctx->parser.data != '>') { + sieve_address_error(ctx, "missing '>'"); + return -1; + } + ctx->parser.data++; + + if ((ret = rfc822_skip_lwsp(&ctx->parser)) < 0) { + sieve_address_error( + ctx, "address ends with invalid characters"); + } + return ret; +} + +static bool +parse_mailbox_address(struct sieve_message_address_parser *ctx, + const unsigned char *address, unsigned int addr_size) +{ + /* Initialize parser */ + + rfc822_parser_init(&ctx->parser, address, addr_size, NULL); + + /* Parse */ + + rfc822_skip_lwsp(&ctx->parser); + + if (ctx->parser.data == ctx->parser.end) { + sieve_address_error(ctx, "empty address"); + return FALSE; + } + + if (parse_mailbox(ctx) < 0) + return FALSE; + + if (ctx->parser.data != ctx->parser.end) { + if (*ctx->parser.data == ',') { + sieve_address_error( + ctx, "not a single addres (found ',')"); + } else { + sieve_address_error( + ctx, "address ends in invalid characters"); + } + return FALSE; + } + + if (str_len(ctx->domain) == 0) { + /* Not gonna happen */ + sieve_address_error(ctx, "missing domain"); + return FALSE; + } + + if (str_len(ctx->local_part) == 0) { + sieve_address_error(ctx, "missing local part"); + return FALSE; + } + return TRUE; +} + +static bool +sieve_address_do_validate(const unsigned char *address, size_t size, + const char **error_r) +{ + struct sieve_message_address_parser ctx; + + *error_r = NULL; + + if (address == NULL) { + *error_r = "null address"; + return FALSE; + } + + i_zero(&ctx); + + ctx.local_part = t_str_new(128); + ctx.domain = t_str_new(128); + ctx.str = t_str_new(128); + ctx.error = t_str_new(128); + + if (!parse_mailbox_address(&ctx, address, size)) { + *error_r = str_c(ctx.error); + return FALSE; + } + + return TRUE; +} + +static const struct smtp_address * +sieve_address_do_parse(const unsigned char *address, size_t size, + const char **error_r) +{ + struct sieve_message_address_parser ctx; + + *error_r = NULL; + + if (address == NULL) + return NULL; + + i_zero(&ctx); + + ctx.local_part = t_str_new(128); + ctx.domain = t_str_new(128); + ctx.str = t_str_new(128); + ctx.error = t_str_new(128); + + if (!parse_mailbox_address(&ctx, address, size)) { + *error_r = str_c(ctx.error); + return NULL; + } + + (void)str_lcase(str_c_modifiable(ctx.domain)); + + return smtp_address_create_temp(str_c(ctx.local_part), + str_c(ctx.domain)); +} + +/* + * Sieve address + */ + +const struct smtp_address * +sieve_address_parse(const char *address, const char **error_r) +{ + return sieve_address_do_parse((const unsigned char *)address, + strlen(address), error_r); +} + +const struct smtp_address * +sieve_address_parse_str(string_t *address, const char **error_r) +{ + return sieve_address_do_parse(str_data(address), str_len(address), + error_r); +} + +bool sieve_address_validate(const char *address, const char **error_r) +{ + return sieve_address_do_validate((const unsigned char *)address, + strlen(address), error_r); +} + +bool sieve_address_validate_str(string_t *address, const char **error_r) +{ + return sieve_address_do_validate(str_data(address), str_len(address), + error_r); +} diff --git a/pigeonhole/src/lib-sieve/sieve-address.h b/pigeonhole/src/lib-sieve/sieve-address.h new file mode 100644 index 0000000..3779a07 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-address.h @@ -0,0 +1,67 @@ +#ifndef SIEVE_ADDRESS_H +#define SIEVE_ADDRESS_H + +#include "lib.h" +#include "strfuncs.h" +#include "smtp-address.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" + +/* + * Address list API + */ + +struct sieve_address_list { + struct sieve_stringlist strlist; + + int (*next_item)(struct sieve_address_list *_addrlist, + struct smtp_address *addr_r, string_t **unparsed_r); +}; + +static inline int +sieve_address_list_next_item(struct sieve_address_list *addrlist, + struct smtp_address *addr_r, string_t **unparsed_r) +{ + return addrlist->next_item(addrlist, addr_r, unparsed_r); +} + +static inline void +sieve_address_list_reset(struct sieve_address_list *addrlist) +{ + sieve_stringlist_reset(&addrlist->strlist); +} + +static inline int +sieve_address_list_get_length(struct sieve_address_list *addrlist) +{ + return sieve_stringlist_get_length(&addrlist->strlist); +} + +static inline void +sieve_address_list_set_trace(struct sieve_address_list *addrlist, bool trace) +{ + sieve_stringlist_set_trace(&addrlist->strlist, trace); +} + +/* + * Header address list + */ + +struct sieve_address_list * +sieve_header_address_list_create(const struct sieve_runtime_env *renv, + struct sieve_stringlist *field_values); + +/* + * Sieve address parsing/validatin + */ + +const struct smtp_address * +sieve_address_parse(const char *address, const char **error_r); +const struct smtp_address * +sieve_address_parse_str(string_t *address, const char **error_r); + +bool sieve_address_validate(const char *address, const char **error_r); +bool sieve_address_validate_str(string_t *address, const char **error_r); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-ast.c b/pigeonhole/src/lib-sieve/sieve-ast.c new file mode 100644 index 0000000..197dbad --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-ast.c @@ -0,0 +1,1111 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "mempool.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-script.h" +#include "sieve-extensions.h" + +#include "sieve-ast.h" + +#include <stdio.h> + +/* + * Forward declarations + */ + +static struct sieve_ast_node * +sieve_ast_node_create(struct sieve_ast *ast, struct sieve_ast_node *parent, + enum sieve_ast_type type, unsigned int source_line); + +/* + * Types + */ + +/* Extensions to the AST */ + +struct sieve_ast_extension_reg { + const struct sieve_extension *ext; + const struct sieve_ast_extension *ast_ext; + void *context; + + bool required:1; +}; + +/* + * AST object + */ + +struct sieve_ast { + pool_t pool; + int refcount; + + struct sieve_instance *svinst; + + struct sieve_script *script; + + struct sieve_ast_node *root; + + ARRAY(const struct sieve_extension *) linked_extensions; + ARRAY(struct sieve_ast_extension_reg) extensions; +}; + +struct sieve_ast *sieve_ast_create(struct sieve_script *script) +{ + pool_t pool; + struct sieve_ast *ast; + unsigned int ext_count; + + pool = pool_alloconly_create("sieve_ast", 32768); + ast = p_new(pool, struct sieve_ast, 1); + ast->pool = pool; + ast->refcount = 1; + + ast->script = script; + sieve_script_ref(script); + ast->svinst = sieve_script_svinst(script); + + ast->root = sieve_ast_node_create(ast, NULL, SAT_ROOT, 0); + ast->root->identifier = "ROOT"; + + ext_count = sieve_extensions_get_count(ast->svinst); + p_array_init(&ast->linked_extensions, pool, ext_count); + p_array_init(&ast->extensions, pool, ext_count); + + return ast; +} + +void sieve_ast_ref(struct sieve_ast *ast) +{ + ast->refcount++; +} + +void sieve_ast_unref(struct sieve_ast **ast) +{ + unsigned int i, ext_count; + const struct sieve_ast_extension_reg *extrs; + + i_assert((*ast)->refcount > 0); + + if (--(*ast)->refcount != 0) + return; + + /* Release script reference */ + sieve_script_unref(&(*ast)->script); + + /* Signal registered extensions that the AST is being destroyed */ + extrs = array_get(&(*ast)->extensions, &ext_count); + for (i = 0; i < ext_count; i++) { + if (extrs[i].ast_ext != NULL && extrs[i].ast_ext->free != NULL) + extrs[i].ast_ext->free(extrs[i].ext, *ast, + extrs[i].context); + } + + /* Destroy AST */ + pool_unref(&(*ast)->pool); + + *ast = NULL; +} + +struct sieve_ast_node *sieve_ast_root(struct sieve_ast *ast) +{ + return ast->root; +} + +pool_t sieve_ast_pool(struct sieve_ast *ast) +{ + return ast->pool; +} + +struct sieve_script *sieve_ast_script(struct sieve_ast *ast) +{ + return ast->script; +} + +/* + * Extension support + */ + +void sieve_ast_extension_link(struct sieve_ast *ast, + const struct sieve_extension *ext, bool required) +{ + unsigned int i, ext_count; + const struct sieve_extension *const *extensions; + struct sieve_ast_extension_reg *reg; + + if (ext->id < 0) + return; + + /* Initialize registration */ + reg = array_idx_get_space(&ast->extensions, (unsigned int)ext->id); + i_assert(reg->ext == NULL || reg->ext == ext); + reg->ext = ext; + reg->required = reg->required || required; + + /* Prevent duplicates */ + extensions = array_get(&ast->linked_extensions, &ext_count); + for (i = 0; i < ext_count; i++) { + if (extensions[i] == ext) + return; + } + + /* Add extension */ + array_append(&ast->linked_extensions, &ext, 1); +} + +const struct sieve_extension * const * +sieve_ast_extensions_get(struct sieve_ast *ast, unsigned int *count_r) +{ + return array_get(&ast->linked_extensions, count_r); +} + +void sieve_ast_extension_register(struct sieve_ast *ast, + const struct sieve_extension *ext, + const struct sieve_ast_extension *ast_ext, + void *context) +{ + struct sieve_ast_extension_reg *reg; + + if (ext->id < 0) + return; + + /* Initialize registration */ + reg = array_idx_get_space(&ast->extensions, (unsigned int)ext->id); + i_assert(reg->ext == NULL || reg->ext == ext); + reg->ext = ext; + reg->ast_ext = ast_ext; + reg->context = context; +} + +void sieve_ast_extension_set_context(struct sieve_ast *ast, + const struct sieve_extension *ext, + void *context) +{ + struct sieve_ast_extension_reg *reg; + + if (ext->id < 0) + return; + + reg = array_idx_get_space(&ast->extensions, (unsigned int)ext->id); + reg->context = context; +} + +void *sieve_ast_extension_get_context(struct sieve_ast *ast, + const struct sieve_extension *ext) +{ + const struct sieve_ast_extension_reg *reg; + + if (ext->id < 0 || ext->id >= (int)array_count(&ast->extensions)) + return NULL; + + reg = array_idx(&ast->extensions, (unsigned int)ext->id); + + return reg->context; +} + +bool sieve_ast_extension_is_required +(struct sieve_ast *ast, const struct sieve_extension *ext) +{ + const struct sieve_ast_extension_reg *reg; + + i_assert(ext->id >= 0 && + ext->id < (int)array_count(&ast->extensions)); + + reg = array_idx(&ast->extensions, (unsigned int)ext->id); + return reg->required; +} + +/* + * AST list implementations + */ + +/* Very simplistic linked list implementation + FIXME: Merge with core + */ +#define __LIST_CREATE(pool, type) { \ + type *list = p_new(pool, type, 1); \ + list->head = NULL; \ + list->tail = NULL; \ + list->len = 0; \ + return list; \ + } + +#define __LIST_ADD(list, node) { \ + if (list->len + 1 < list->len) \ + return FALSE; \ + \ + node->next = NULL; \ + if (list->head == NULL) { \ + node->prev = NULL; \ + list->head = node; \ + list->tail = node; \ + } else { \ + list->tail->next = node; \ + node->prev = list->tail; \ + list->tail = node; \ + } \ + list->len++; \ + node->list = list; \ + return TRUE; \ + } + +#define __LIST_INSERT(list, before, node) { \ + if (list->len + 1 < list->len) \ + return FALSE; \ + \ + node->next = before; \ + if (list->head == before) { \ + node->prev = NULL; \ + list->head = node; \ + } else { \ + before->prev->next = node; \ + } \ + node->prev = before->prev; \ + before->prev = node; \ + list->len++; \ + node->list = list; \ + \ + return TRUE; \ + } + +#define __LIST_JOIN(list, node_type, items) { \ + node_type *node; \ + \ + if (list->len + items->len < list->len) \ + return FALSE; \ + \ + if (items->len == 0) \ + return TRUE; \ + \ + if (list->head == NULL) { \ + list->head = items->head; \ + list->tail = items->tail; \ + } else { \ + list->tail->next = items->head; \ + items->head->prev = list->tail; \ + list->tail = items->tail; \ + } \ + list->len += items->len; \ + \ + node = items->head; \ + while (node != NULL) { \ + node->list = list; \ + node = node->next; \ + } \ + return TRUE; \ + } + +#define __LIST_DETACH(first, node_type, count) { \ + node_type *last, *result; \ + unsigned int left; \ + \ + i_assert(first->list != NULL); \ + \ + left = count - 1; \ + last = first; \ + while (left > 0 && last->next != NULL) { \ + left--; \ + last = last->next; \ + } \ + \ + if (first->list->head == first) \ + first->list->head = last->next; \ + if (first->list->tail == last) \ + first->list->tail = first->prev; \ + \ + if (first->prev != NULL) \ + first->prev->next = last->next; \ + if (last->next != NULL) \ + last->next->prev = first->prev; \ + \ + first->list->len -= count - left; \ + \ + result = last->next; \ + first->prev = NULL; \ + last->next = NULL; \ + \ + return result; \ + } + +/* List of AST nodes */ + +static struct sieve_ast_list * +sieve_ast_list_create(pool_t pool) + __LIST_CREATE(pool, struct sieve_ast_list) + +static bool +sieve_ast_list_add(struct sieve_ast_list *list, struct sieve_ast_node *node) + __LIST_ADD(list, node) + +static struct sieve_ast_node * +sieve_ast_list_detach(struct sieve_ast_node *first, unsigned int count) + __LIST_DETACH(first, struct sieve_ast_node, count) + +/* List of argument AST nodes */ + +struct sieve_ast_arg_list *sieve_ast_arg_list_create(pool_t pool) + __LIST_CREATE(pool, struct sieve_ast_arg_list) + +bool sieve_ast_arg_list_add(struct sieve_ast_arg_list *list, + struct sieve_ast_argument *argument) + __LIST_ADD(list, argument) + +bool sieve_ast_arg_list_insert(struct sieve_ast_arg_list *list, + struct sieve_ast_argument *before, + struct sieve_ast_argument *argument) + __LIST_INSERT(list, before, argument) + +static bool +sieve_ast_arg_list_join(struct sieve_ast_arg_list *list, + struct sieve_ast_arg_list *items) + __LIST_JOIN(list, struct sieve_ast_argument, items) + +static struct sieve_ast_argument * +sieve_ast_arg_list_detach(struct sieve_ast_argument *first, + const unsigned int count) + __LIST_DETACH(first, struct sieve_ast_argument, count) + +void sieve_ast_arg_list_substitute(struct sieve_ast_arg_list *list, + struct sieve_ast_argument *argument, + struct sieve_ast_argument *replacement) +{ + if (list->head == argument) + list->head = replacement; + if (list->tail == argument) + list->tail = replacement; + + if (argument->prev != NULL) + argument->prev->next = replacement; + if (argument->next != NULL) + argument->next->prev = replacement; + + replacement->prev = argument->prev; + replacement->next = argument->next; + replacement->list = argument->list; + + argument->next = NULL; + argument->prev = NULL; +} + +/* + * AST node + */ + +static struct sieve_ast_node * +sieve_ast_node_create(struct sieve_ast *ast, struct sieve_ast_node *parent, + enum sieve_ast_type type, unsigned int source_line) +{ + struct sieve_ast_node *node = + p_new(ast->pool, struct sieve_ast_node, 1); + + node->ast = ast; + node->parent = parent; + node->type = type; + + node->prev = NULL; + node->next = NULL; + + node->arguments = NULL; + node->tests = NULL; + node->commands = NULL; + + node->test_list = FALSE; + node->block = FALSE; + + node->source_line = source_line; + + return node; +} + +static bool +sieve_ast_node_add_command(struct sieve_ast_node *node, + struct sieve_ast_node *command) +{ + i_assert(command->type == SAT_COMMAND && + (node->type == SAT_ROOT || node->type == SAT_COMMAND)); + + if (node->commands == NULL) + node->commands = sieve_ast_list_create(node->ast->pool); + + return sieve_ast_list_add(node->commands, command); +} + +static bool +sieve_ast_node_add_test(struct sieve_ast_node *node, + struct sieve_ast_node *test) +{ + i_assert(test->type == SAT_TEST && + (node->type == SAT_TEST || node->type == SAT_COMMAND)); + + if (node->tests == NULL) + node->tests = sieve_ast_list_create(node->ast->pool); + + return sieve_ast_list_add(node->tests, test); +} + +static bool +sieve_ast_node_add_argument(struct sieve_ast_node *node, + struct sieve_ast_argument *argument) +{ + i_assert(node->type == SAT_TEST || node->type == SAT_COMMAND); + + if (node->arguments == NULL) + node->arguments = sieve_ast_arg_list_create(node->ast->pool); + + return sieve_ast_arg_list_add(node->arguments, argument); +} + +struct sieve_ast_node *sieve_ast_node_detach(struct sieve_ast_node *first) +{ + return sieve_ast_list_detach(first, 1); +} + +const char *sieve_ast_type_name(enum sieve_ast_type ast_type) +{ + switch (ast_type) { + case SAT_NONE: + return "none"; + case SAT_ROOT: + return "ast root node"; + case SAT_COMMAND: + return "command"; + case SAT_TEST: + return "test"; + default: + return "??AST NODE??"; + } +} + +/* + * Argument AST node + */ + +struct sieve_ast_argument * +sieve_ast_argument_create(struct sieve_ast *ast, unsigned int source_line) +{ + struct sieve_ast_argument *arg = + p_new(ast->pool, struct sieve_ast_argument, 1); + + arg->ast = ast; + + arg->prev = NULL; + arg->next = NULL; + + arg->source_line = source_line; + + arg->argument = NULL; + + return arg; +} + +static void +sieve_ast_argument_substitute(struct sieve_ast_argument *argument, + struct sieve_ast_argument *replacement) +{ + sieve_ast_arg_list_substitute(argument->list, argument, replacement); +} + +struct sieve_ast_argument * +sieve_ast_argument_string_create_raw(struct sieve_ast *ast, string_t *str, + unsigned int source_line) +{ + struct sieve_ast_argument *argument = + sieve_ast_argument_create(ast, source_line); + + argument->type = SAAT_STRING; + argument->_value.str = str; + + return argument; +} + +struct sieve_ast_argument * +sieve_ast_argument_string_create(struct sieve_ast_node *node, + const string_t *str, unsigned int source_line) +{ + struct sieve_ast_argument *argument; + string_t *newstr; + + /* Allocate new internal string buffer */ + newstr = str_new(node->ast->pool, str_len(str)); + + /* Clone string */ + str_append_str(newstr, str); + + /* Create string argument */ + argument = sieve_ast_argument_string_create_raw( + node->ast, newstr, source_line); + + /* Add argument to command/test node */ + sieve_ast_node_add_argument(node, argument); + + return argument; +} + +struct sieve_ast_argument * +sieve_ast_argument_cstring_create(struct sieve_ast_node *node, const char *str, + unsigned int source_line) +{ + struct sieve_ast_argument *argument; + string_t *newstr; + + /* Allocate new internal string buffer */ + newstr = str_new(node->ast->pool, strlen(str)); + + /* Clone string */ + str_append(newstr, str); + + /* Create string argument */ + argument = sieve_ast_argument_string_create_raw( + node->ast, newstr, source_line); + + /* Add argument to command/test node */ + sieve_ast_node_add_argument(node, argument); + + return argument; +} + +void sieve_ast_argument_string_set(struct sieve_ast_argument *argument, + string_t *newstr) +{ + i_assert(argument->type == SAAT_STRING); + argument->_value.str = newstr; +} + +void sieve_ast_argument_string_setc(struct sieve_ast_argument *argument, + const char *newstr) +{ + i_assert(argument->type == SAAT_STRING); + + str_truncate(argument->_value.str, 0); + str_append(argument->_value.str, newstr); +} + +void sieve_ast_argument_number_substitute(struct sieve_ast_argument *argument, + sieve_number_t number) +{ + argument->type = SAAT_NUMBER; + argument->_value.number = number; +} + +struct sieve_ast_argument * +sieve_ast_argument_stringlist_create(struct sieve_ast_node *node, + unsigned int source_line) +{ + struct sieve_ast_argument *argument = + sieve_ast_argument_create(node->ast, source_line); + + argument->type = SAAT_STRING_LIST; + argument->_value.strlist = NULL; + + sieve_ast_node_add_argument(node, argument); + + return argument; +} + +struct sieve_ast_argument * +sieve_ast_argument_stringlist_substitute(struct sieve_ast_node *node, + struct sieve_ast_argument *arg) +{ + struct sieve_ast_argument *argument = + sieve_ast_argument_create(node->ast, arg->source_line); + + argument->type = SAAT_STRING_LIST; + argument->_value.strlist = NULL; + + sieve_ast_argument_substitute(arg, argument); + + return argument; +} + +static inline bool +_sieve_ast_stringlist_add_item(struct sieve_ast_argument *list, + struct sieve_ast_argument *item) +{ + i_assert(list->type == SAAT_STRING_LIST); + + if (list->_value.strlist == NULL) { + list->_value.strlist = + sieve_ast_arg_list_create(list->ast->pool); + } + + return sieve_ast_arg_list_add(list->_value.strlist, item); +} + +static bool +sieve_ast_stringlist_add_stringlist(struct sieve_ast_argument *list, + struct sieve_ast_argument *items) +{ + i_assert(list->type == SAAT_STRING_LIST); + i_assert(items->type == SAAT_STRING_LIST); + + if (list->_value.strlist == NULL) { + list->_value.strlist = + sieve_ast_arg_list_create(list->ast->pool); + } + + return sieve_ast_arg_list_join(list->_value.strlist, + items->_value.strlist); +} + +static bool +_sieve_ast_stringlist_add_str(struct sieve_ast_argument *list, string_t *str, + unsigned int source_line) +{ + struct sieve_ast_argument *stritem; + + stritem = sieve_ast_argument_create(list->ast, source_line); + stritem->type = SAAT_STRING; + stritem->_value.str = str; + + return _sieve_ast_stringlist_add_item(list, stritem); +} + +bool sieve_ast_stringlist_add(struct sieve_ast_argument *list, + const string_t *str, unsigned int source_line) +{ + string_t *copied_str = str_new(list->ast->pool, str_len(str)); + str_append_str(copied_str, str); + + return _sieve_ast_stringlist_add_str(list, copied_str, source_line); +} + +bool sieve_ast_stringlist_add_strc(struct sieve_ast_argument *list, + const char *str, unsigned int source_line) +{ + string_t *copied_str = str_new(list->ast->pool, strlen(str)); + str_append(copied_str, str); + + return _sieve_ast_stringlist_add_str(list, copied_str, source_line); +} + +struct sieve_ast_argument * +sieve_ast_argument_tag_create(struct sieve_ast_node *node, const char *tag, + unsigned int source_line) +{ + struct sieve_ast_argument *argument = + sieve_ast_argument_create(node->ast, source_line); + + argument->type = SAAT_TAG; + argument->_value.tag = p_strdup(node->ast->pool, tag); + + if (!sieve_ast_node_add_argument(node, argument)) + return NULL; + return argument; +} + +struct sieve_ast_argument * +sieve_ast_argument_tag_insert(struct sieve_ast_argument *before, + const char *tag, unsigned int source_line) +{ + struct sieve_ast_argument *argument = + sieve_ast_argument_create(before->ast, source_line); + + argument->type = SAAT_TAG; + argument->_value.tag = p_strdup(before->ast->pool, tag); + + if (!sieve_ast_arg_list_insert(before->list, before, argument)) + return NULL; + return argument; +} + +struct sieve_ast_argument * +sieve_ast_argument_number_create(struct sieve_ast_node *node, + sieve_number_t number, + unsigned int source_line) +{ + struct sieve_ast_argument *argument = + sieve_ast_argument_create(node->ast, source_line); + + argument->type = SAAT_NUMBER; + argument->_value.number = number; + + if (!sieve_ast_node_add_argument(node, argument)) + return NULL; + return argument; +} + +void sieve_ast_argument_number_set(struct sieve_ast_argument *argument, + sieve_number_t newnum) +{ + i_assert(argument->type == SAAT_NUMBER); + argument->_value.number = newnum; +} + +struct sieve_ast_argument * +sieve_ast_arguments_detach(struct sieve_ast_argument *first, + unsigned int count) +{ + return sieve_ast_arg_list_detach(first, count); +} + +bool sieve_ast_argument_attach(struct sieve_ast_node *node, + struct sieve_ast_argument *argument) +{ + return sieve_ast_node_add_argument(node, argument); +} + +const char *sieve_ast_argument_type_name(enum sieve_ast_argument_type arg_type) +{ + switch (arg_type) { + case SAAT_NONE: + return "none"; + case SAAT_STRING_LIST: + return "a string list"; + case SAAT_STRING: + return "a string"; + case SAAT_NUMBER: + return "a number"; + case SAAT_TAG: + return "a tag"; + default: + return "??ARGUMENT??"; + } +} + +/* Test AST node */ + +struct sieve_ast_node * +sieve_ast_test_create(struct sieve_ast_node *parent, const char *identifier, + unsigned int source_line) +{ + struct sieve_ast_node *test = sieve_ast_node_create( + parent->ast, parent, SAT_TEST, source_line); + + test->identifier = p_strdup(parent->ast->pool, identifier); + + if (!sieve_ast_node_add_test(parent, test)) + return NULL; + return test; +} + +/* Command AST node */ + +struct sieve_ast_node * +sieve_ast_command_create(struct sieve_ast_node *parent, const char *identifier, + unsigned int source_line) +{ + struct sieve_ast_node *command = sieve_ast_node_create( + parent->ast, parent, SAT_COMMAND, source_line); + + command->identifier = p_strdup(parent->ast->pool, identifier); + + if (!sieve_ast_node_add_command(parent, command)) + return NULL; + return command; +} + +/* + * Utility + */ + +int sieve_ast_stringlist_map( + struct sieve_ast_argument **listitem, void *context, + int (*map_function)(void *context, struct sieve_ast_argument *arg)) +{ + if (sieve_ast_argument_type(*listitem) == SAAT_STRING) { + /* Single string */ + return map_function(context, *listitem); + } else if (sieve_ast_argument_type(*listitem) == SAAT_STRING_LIST) { + int ret = 0; + + /* String list */ + *listitem = sieve_ast_strlist_first(*listitem); + + while (*listitem != NULL) { + if ((ret = map_function(context, *listitem)) <= 0) + return ret; + + *listitem = sieve_ast_strlist_next(*listitem); + } + + return ret; + } + + i_unreached(); + return -1; +} + +struct sieve_ast_argument * +sieve_ast_stringlist_join(struct sieve_ast_argument *list, + struct sieve_ast_argument *items) +{ + enum sieve_ast_argument_type list_type, items_type; + struct sieve_ast_argument *newlist; + + list_type = sieve_ast_argument_type(list); + items_type = sieve_ast_argument_type(items); + + switch (list_type) { + case SAAT_STRING: + switch (items_type) { + case SAAT_STRING: + newlist = sieve_ast_argument_create( + list->ast, list->source_line); + newlist->type = SAAT_STRING_LIST; + newlist->_value.strlist = NULL; + + sieve_ast_argument_substitute(list, newlist); + sieve_ast_arguments_detach(items, 1); + + if (!_sieve_ast_stringlist_add_item(newlist, list) || + !_sieve_ast_stringlist_add_item(newlist, items)) + return NULL; + return newlist; + case SAAT_STRING_LIST: + /* Adding stringlist to string; make them swith places + and add one to the other. + */ + sieve_ast_arguments_detach(items, 1); + sieve_ast_argument_substitute(list, items); + if (!_sieve_ast_stringlist_add_item(items, list)) + return NULL; + return list; + default: + i_unreached(); + } + break; + case SAAT_STRING_LIST: + switch (items_type) { + case SAAT_STRING: + /* Adding string to stringlist; straightforward add */ + sieve_ast_arguments_detach(items, 1); + if (!_sieve_ast_stringlist_add_item(list, items)) + return NULL; + return list; + case SAAT_STRING_LIST: + /* Adding stringlist to stringlist; perform actual join + */ + sieve_ast_arguments_detach(items, 1); + if (!sieve_ast_stringlist_add_stringlist(list, items)) + return NULL; + return list; + default: + i_unreached(); + } + break; + default: + i_unreached(); + } + return NULL; +} + +/* Debug */ + +/* Unparsing, currently implemented using plain printf()s */ + +static void sieve_ast_unparse_string(const string_t *strval) +{ + char *str = t_strdup_noconst(str_c((string_t *)strval)); + + if (strchr(str, '\n') != NULL && str[strlen(str)-1] == '\n') { + /* Print it as a multi-line string and do required dotstuffing + */ + char *spos = str; + char *epos = strchr(str, '\n'); + printf("text:\n"); + + while (epos != NULL) { + *epos = '\0'; + if (*spos == '.') + printf("."); + + printf("%s\n", spos); + + spos = epos+1; + epos = strchr(spos, '\n'); + } + if (*spos == '.') + printf("."); + + printf("%s\n.\n", spos); + } else { + /* Print it as a quoted string and escape " */ + char *spos = str; + char *epos = strchr(str, '"'); + printf("\""); + + while (epos != NULL) { + *epos = '\0'; + printf("%s\\\"", spos); + + spos = epos+1; + epos = strchr(spos, '"'); + } + + printf("%s\"", spos); + } +} + +static void +sieve_ast_unparse_argument(struct sieve_ast_argument *argument, int level); + +static void +sieve_ast_unparse_stringlist(struct sieve_ast_argument *strlist, int level) +{ + struct sieve_ast_argument *stritem; + + if (sieve_ast_strlist_count(strlist) > 1) { + int i; + + printf("[\n"); + + /* Create indent */ + for (i = 0; i < level+2; i++) + printf(" "); + + stritem = sieve_ast_strlist_first(strlist); + if (stritem != NULL) { + sieve_ast_unparse_string( + sieve_ast_strlist_str(stritem)); + + stritem = sieve_ast_strlist_next(stritem); + while (stritem != NULL) { + printf(",\n"); + for (i = 0; i < level+2; i++) + printf(" "); + sieve_ast_unparse_string( + sieve_ast_strlist_str(stritem)); + stritem = sieve_ast_strlist_next(stritem); + } + } + + printf(" ]"); + } else { + stritem = sieve_ast_strlist_first(strlist); + if (stritem != NULL) { + sieve_ast_unparse_string( + sieve_ast_strlist_str(stritem)); + } + } +} + +static void +sieve_ast_unparse_argument(struct sieve_ast_argument *argument, int level) +{ + switch (argument->type) { + case SAAT_STRING: + sieve_ast_unparse_string(sieve_ast_argument_str(argument)); + break; + case SAAT_STRING_LIST: + sieve_ast_unparse_stringlist(argument, level+1); + break; + case SAAT_NUMBER: + printf("%"SIEVE_PRI_NUMBER, + sieve_ast_argument_number(argument)); + break; + case SAAT_TAG: + printf(":%s", sieve_ast_argument_tag(argument)); + break; + default: + printf("??ARGUMENT??"); + break; + } +} + +static void sieve_ast_unparse_test(struct sieve_ast_node *node, int level); + +static void sieve_ast_unparse_tests(struct sieve_ast_node *node, int level) +{ + struct sieve_ast_node *test; + + if (sieve_ast_test_count(node) > 1) { + int i; + + printf(" (\n"); + + /* Create indent */ + for (i = 0; i < level+2; i++) + printf(" "); + + test = sieve_ast_test_first(node); + sieve_ast_unparse_test(test, level+1); + + test = sieve_ast_test_next(test); + while (test != NULL) { + printf(", \n"); + for (i = 0; i < level+2; i++) + printf(" "); + sieve_ast_unparse_test(test, level+1); + test = sieve_ast_test_next(test); + } + + printf(" )"); + } else { + test = sieve_ast_test_first(node); + if (test != NULL) + sieve_ast_unparse_test(test, level); + } +} + +static void sieve_ast_unparse_test(struct sieve_ast_node *node, int level) +{ + struct sieve_ast_argument *argument; + + printf(" %s", node->identifier); + + argument = sieve_ast_argument_first(node); + while (argument != NULL) { + printf(" "); + sieve_ast_unparse_argument(argument, level); + argument = sieve_ast_argument_next(argument); + } + + sieve_ast_unparse_tests(node, level); +} + +static void sieve_ast_unparse_command(struct sieve_ast_node *node, int level) +{ + struct sieve_ast_node *command; + struct sieve_ast_argument *argument; + + int i; + + /* Create indent */ + for (i = 0; i < level; i++) + printf(" "); + + printf("%s", node->identifier); + + argument = sieve_ast_argument_first(node); + while (argument != NULL) { + printf(" "); + sieve_ast_unparse_argument(argument, level); + argument = sieve_ast_argument_next(argument); + } + + sieve_ast_unparse_tests(node, level); + + command = sieve_ast_command_first(node); + if (command != NULL) { + printf(" {\n"); + + while (command != NULL) { + sieve_ast_unparse_command(command, level+1); + command = sieve_ast_command_next(command); + } + + for (i = 0; i < level; i++) + printf(" "); + printf("}\n"); + } else + printf(";\n"); +} + +void sieve_ast_unparse(struct sieve_ast *ast) +{ + struct sieve_ast_node *command; + + printf("Unparsing Abstract Syntax Tree:\n"); + + T_BEGIN { + command = sieve_ast_command_first(sieve_ast_root(ast)); + while (command != NULL) { + sieve_ast_unparse_command(command, 0); + command = sieve_ast_command_next(command); + } + } T_END; +} diff --git a/pigeonhole/src/lib-sieve/sieve-ast.h b/pigeonhole/src/lib-sieve/sieve-ast.h new file mode 100644 index 0000000..00f8a6b --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-ast.h @@ -0,0 +1,382 @@ +#ifndef SIEVE_AST_H +#define SIEVE_AST_H + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" +#include "sieve-error.h" + +/* + Abstract Syntax Tree (AST) structure: + + sieve_ast (root) + [*command] + | + +-- command: + | .... + +-- command: + | [identifier *argument *test *command] + | +-- argument: | \--> as from root + | | .... | + | +-- argument: V (continued below) + | | [number | tag | *string] + | . + . + + *test + +-- test: + | .... + +-- test: + | [identifier *argument *test] + | +-- argument: \--> as from the top + . | .... of this tree + +-- argument: + | [number | tag | *string] + . + + Tests and commands are defined using the same structure: sieve_ast_node. + However, arguments and string-lists are described using sieve_ast_argument. +*/ + +/* IMPORTANT NOTICE: Do not decorate the AST with objects other than those + allocated on the ast's pool or static const objects. Otherwise it is possible + that pointers in the tree become dangling which is highly undesirable. + */ + +/* + * Forward declarations + */ + +struct sieve_ast_list; +struct sieve_ast_arg_list; + +/* + * Types + */ + +enum sieve_ast_argument_type { + SAAT_NONE, + SAAT_NUMBER, + SAAT_STRING, + SAAT_STRING_LIST, + SAAT_TAG, +}; + +enum sieve_ast_type { + SAT_NONE, + SAT_ROOT, + SAT_COMMAND, + SAT_TEST, +}; + +/* + * AST Nodes + */ + +/* Argument node */ + +struct sieve_ast_argument { + enum sieve_ast_argument_type type; + + /* Back reference to the AST object */ + struct sieve_ast *ast; + + /* List related */ + struct sieve_ast_arg_list *list; + struct sieve_ast_argument *next; + struct sieve_ast_argument *prev; + + /* Parser-assigned data */ + + union { + string_t *str; + struct sieve_ast_arg_list *strlist; + const char *tag; + sieve_number_t number; + } _value; + + unsigned int source_line; + + /* Assigned during validation */ + + /* Argument associated with this ast element */ + struct sieve_argument *argument; + + /* Parameters to this (tag) argument */ + struct sieve_ast_argument *parameters; +}; + +struct sieve_ast_node { + enum sieve_ast_type type; + + /* Back reference to the AST object */ + struct sieve_ast *ast; + + /* Back reference to this node's parent */ + struct sieve_ast_node *parent; + + /* Linked list references */ + struct sieve_ast_list *list; + struct sieve_ast_node *next; + struct sieve_ast_node *prev; + + /* Commands (NULL if not allocated) */ + bool block; + struct sieve_ast_list *commands; + + /* Tests (NULL if not allocated)*/ + bool test_list; + struct sieve_ast_list *tests; + + /* Arguments (NULL if not allocated) */ + struct sieve_ast_arg_list *arguments; + + /* Identifier of command or test */ + const char *identifier; + + /* The location in the file where this command was started */ + unsigned int source_line; + + /* Assigned during validation */ + + /* Context */ + struct sieve_command *command; +}; + +/* + * AST node lists + */ + +struct sieve_ast_list { + struct sieve_ast_node *head; + struct sieve_ast_node *tail; + unsigned int len; +}; + +struct sieve_ast_arg_list { + struct sieve_ast_argument *head; + struct sieve_ast_argument *tail; + unsigned int len; +}; + +/* + * AST object + */ + +struct sieve_ast; + +struct sieve_ast *sieve_ast_create(struct sieve_script *script); +void sieve_ast_ref(struct sieve_ast *ast); +void sieve_ast_unref(struct sieve_ast **ast); + +struct sieve_ast_node *sieve_ast_root(struct sieve_ast *ast); +pool_t sieve_ast_pool(struct sieve_ast *ast); +struct sieve_script *sieve_ast_script(struct sieve_ast *ast); + +/* Extension support */ + +struct sieve_ast_extension { + const struct sieve_extension_def *ext; + + void (*free)(const struct sieve_extension *ext, struct sieve_ast *ast, + void *context); +}; + +void sieve_ast_extension_link(struct sieve_ast *ast, + const struct sieve_extension *ext, + bool required); +const struct sieve_extension * const * +sieve_ast_extensions_get(struct sieve_ast *ast, unsigned int *count_r); + +void sieve_ast_extension_register(struct sieve_ast *ast, + const struct sieve_extension *ext, + const struct sieve_ast_extension *ast_ext, + void *context); +void sieve_ast_extension_set_context(struct sieve_ast *ast, + const struct sieve_extension *ext, + void *context); +void *sieve_ast_extension_get_context(struct sieve_ast *ast, + const struct sieve_extension *ext); + +bool sieve_ast_extension_is_required(struct sieve_ast *ast, + const struct sieve_extension *ext); + +/* + * AST node manipulation + */ + +/* Command nodes */ + +struct sieve_ast_node * +sieve_ast_test_create(struct sieve_ast_node *parent, const char *identifier, + unsigned int source_line); +struct sieve_ast_node * +sieve_ast_command_create(struct sieve_ast_node *parent, const char *identifier, + unsigned int source_line); + +struct sieve_ast_node * +sieve_ast_node_detach(struct sieve_ast_node *first); + +const char *sieve_ast_type_name(enum sieve_ast_type ast_type); + +/* Argument nodes */ + +struct sieve_ast_argument * +sieve_ast_argument_create(struct sieve_ast *ast, unsigned int source_line); + +struct sieve_ast_arg_list *sieve_ast_arg_list_create(pool_t pool); +bool sieve_ast_arg_list_add(struct sieve_ast_arg_list *list, + struct sieve_ast_argument *argument); +bool sieve_ast_arg_list_insert(struct sieve_ast_arg_list *list, + struct sieve_ast_argument *before, + struct sieve_ast_argument *argument); +void sieve_ast_arg_list_substitute(struct sieve_ast_arg_list *list, + struct sieve_ast_argument *argument, + struct sieve_ast_argument *replacement); + +struct sieve_ast_argument * +sieve_ast_argument_string_create_raw(struct sieve_ast *ast, string_t *str, + unsigned int source_line); +struct sieve_ast_argument * +sieve_ast_argument_string_create(struct sieve_ast_node *node, + const string_t *str, unsigned int source_line); +struct sieve_ast_argument * +sieve_ast_argument_cstring_create(struct sieve_ast_node *node, const char *str, + unsigned int source_line); + +struct sieve_ast_argument * +sieve_ast_argument_tag_create(struct sieve_ast_node *node, const char *tag, + unsigned int source_line); + +struct sieve_ast_argument * +sieve_ast_argument_number_create(struct sieve_ast_node *node, + sieve_number_t number, + unsigned int source_line); + +void sieve_ast_argument_string_set(struct sieve_ast_argument *argument, + string_t *newstr); +void sieve_ast_argument_string_setc(struct sieve_ast_argument *argument, + const char *newstr); + +void sieve_ast_argument_number_set(struct sieve_ast_argument *argument, + sieve_number_t newnum); +void sieve_ast_argument_number_substitute(struct sieve_ast_argument *argument, + sieve_number_t number); + +struct sieve_ast_argument * +sieve_ast_argument_tag_insert(struct sieve_ast_argument *before, + const char *tag, unsigned int source_line); + +struct sieve_ast_argument * +sieve_ast_argument_stringlist_create(struct sieve_ast_node *node, + unsigned int source_line); +struct sieve_ast_argument * +sieve_ast_argument_stringlist_substitute(struct sieve_ast_node *node, + struct sieve_ast_argument *arg); + +struct sieve_ast_argument * +sieve_ast_arguments_detach(struct sieve_ast_argument *first, + unsigned int count); +bool sieve_ast_argument_attach(struct sieve_ast_node *node, + struct sieve_ast_argument *argument); + +const char *sieve_ast_argument_type_name(enum sieve_ast_argument_type arg_type); +#define sieve_ast_argument_name(argument) \ + sieve_ast_argument_type_name((argument)->type) + +bool sieve_ast_stringlist_add(struct sieve_ast_argument *list, + const string_t *str, unsigned int source_line); +bool sieve_ast_stringlist_add_strc(struct sieve_ast_argument *list, + const char *str, unsigned int source_line); + +/* + * Utility + */ + +int sieve_ast_stringlist_map( + struct sieve_ast_argument **listitem, void *context, + int (*map_function)(void *context, struct sieve_ast_argument *arg)); +struct sieve_ast_argument * +sieve_ast_stringlist_join(struct sieve_ast_argument *list, + struct sieve_ast_argument *items); + +/* + * AST access macros + */ + +/* Generic list access macros */ +#define __AST_LIST_FIRST(list) \ + ((list) == NULL ? NULL : (list)->head) +#define __AST_LIST_LAST(list) \ + ((list) == NULL ? NULL : (list)->tail) +#define __AST_LIST_COUNT(list) \ + ((list) == NULL || (list)->head == NULL ? 0 : (list)->len) +#define __AST_LIST_NEXT(item) ((item)->next) +#define __AST_LIST_PREV(item) ((item)->prev) + +#define __AST_NODE_LIST_FIRST(node, list) __AST_LIST_FIRST((node)->list) +#define __AST_NODE_LIST_LAST(node, list) __AST_LIST_LAST((node)->list) +#define __AST_NODE_LIST_COUNT(node, list) __AST_LIST_COUNT((node)->list) + +/* AST macros */ + +/* AST node macros */ +#define sieve_ast_node_pool(node) (sieve_ast_pool((node)->ast)) +#define sieve_ast_node_parent(node) ((node)->parent) +#define sieve_ast_node_prev(node) __AST_LIST_PREV(node) +#define sieve_ast_node_next(node) __AST_LIST_NEXT(node) +#define sieve_ast_node_type(node) ((node) == NULL ? SAT_NONE : (node)->type) +#define sieve_ast_node_line(node) ((node) == NULL ? 0 : (node)->source_line) + +/* AST command node macros */ +#define sieve_ast_command_first(node) __AST_NODE_LIST_FIRST(node, commands) +#define sieve_ast_command_count(node) __AST_NODE_LIST_COUNT(node, commands) +#define sieve_ast_command_prev(command) __AST_LIST_PREV(command) +#define sieve_ast_command_next(command) __AST_LIST_NEXT(command) + +/* Compare the identifier of the previous command */ +#define sieve_ast_prev_cmd_is(cmd, id) \ + ((cmd)->prev == NULL ? FALSE : \ + strncasecmp((cmd)->prev->identifier, id, sizeof(id)-1) == 0) + +/* AST test macros */ +#define sieve_ast_test_count(node) __AST_NODE_LIST_COUNT(node, tests) +#define sieve_ast_test_first(node) __AST_NODE_LIST_FIRST(node, tests) +#define sieve_ast_test_next(test) __AST_LIST_NEXT(test) + +/* AST argument macros */ +#define sieve_ast_argument_pool(node) (sieve_ast_pool((node)->ast)) +#define sieve_ast_argument_first(node) __AST_NODE_LIST_FIRST(node, arguments) +#define sieve_ast_argument_last(node) __AST_NODE_LIST_LAST(node, arguments) +#define sieve_ast_argument_count(node) __AST_NODE_LIST_COUNT(node, arguments) +#define sieve_ast_argument_prev(argument) __AST_LIST_PREV(argument) +#define sieve_ast_argument_next(argument) __AST_LIST_NEXT(argument) +#define sieve_ast_argument_type(argument) (argument)->type +#define sieve_ast_argument_line(argument) (argument)->source_line + +#define sieve_ast_argument_str(argument) ((argument)->_value.str) +#define sieve_ast_argument_strc(argument) (str_c((argument)->_value.str)) +#define sieve_ast_argument_tag(argument) ((argument)->_value.tag) +#define sieve_ast_argument_number(argument) ((argument)->_value.number) + +/* AST string list macros */ +// @UNSAFE: should check whether we are actually accessing a string list +#define sieve_ast_strlist_first(list) \ + __AST_NODE_LIST_FIRST(list, _value.strlist) +#define sieve_ast_strlist_last(list) \ + __AST_NODE_LIST_LAST(list, _value.strlist) +#define sieve_ast_strlist_count(list) \ + __AST_NODE_LIST_COUNT(list, _value.strlist) +#define sieve_ast_strlist_next(str) __AST_LIST_NEXT(str) +#define sieve_ast_strlist_prev(str) __AST_LIST_PREV(str) +#define sieve_ast_strlist_str(str) sieve_ast_argument_str(str) +#define sieve_ast_strlist_strc(str) sieve_ast_argument_strc(str) + +/* + * Debug + */ + +void sieve_ast_unparse(struct sieve_ast *ast); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-binary-code.c b/pigeonhole/src/lib-sieve/sieve-binary-code.c new file mode 100644 index 0000000..0d76ee0 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-binary-code.c @@ -0,0 +1,405 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" +#include "mempool.h" +#include "buffer.h" +#include "hash.h" +#include "array.h" +#include "ostream.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-extensions.h" +#include "sieve-code.h" +#include "sieve-script.h" + +#include "sieve-binary-private.h" + +/* + * Forward declarations + */ + +static inline sieve_size_t +sieve_binary_emit_dynamic_data(struct sieve_binary_block *sblock, + const void *data, size_t size); + +/* + * Emission functions + */ + +/* Low-level emission functions */ + +static inline void +_sieve_binary_emit_data(struct sieve_binary_block *sblock, + const void *data, sieve_size_t size) +{ + buffer_append(sblock->data, data, size); +} + +static inline void +_sieve_binary_emit_byte(struct sieve_binary_block *sblock, uint8_t byte) +{ + _sieve_binary_emit_data(sblock, &byte, 1); +} + +static inline void +_sieve_binary_update_data(struct sieve_binary_block *sblock, + sieve_size_t address, const void *data, + sieve_size_t size) +{ + buffer_write(sblock->data, address, data, size); +} + +sieve_size_t sieve_binary_emit_data(struct sieve_binary_block *sblock, + const void *data, sieve_size_t size) +{ + sieve_size_t address = _sieve_binary_block_get_size(sblock); + + _sieve_binary_emit_data(sblock, data, size); + + return address; +} + +sieve_size_t sieve_binary_emit_byte(struct sieve_binary_block *sblock, + uint8_t byte) +{ + sieve_size_t address = _sieve_binary_block_get_size(sblock); + + _sieve_binary_emit_data(sblock, &byte, 1); + + return address; +} + +void sieve_binary_update_data(struct sieve_binary_block *sblock, + sieve_size_t address, const void *data, + sieve_size_t size) +{ + _sieve_binary_update_data(sblock, address, data, size); +} + +/* Offset emission functions */ + +sieve_size_t sieve_binary_emit_offset(struct sieve_binary_block *sblock, + sieve_offset_t offset) +{ + sieve_size_t address = _sieve_binary_block_get_size(sblock); + uint8_t encoded[sizeof(offset)]; + int i; + + for (i = sizeof(offset)-1; i >= 0; i--) { + encoded[i] = (uint8_t)offset; + offset >>= 8; + } + + _sieve_binary_emit_data(sblock, encoded, sizeof(offset)); + + return address; +} + +void sieve_binary_resolve_offset(struct sieve_binary_block *sblock, + sieve_size_t address) +{ + sieve_size_t cur_address = _sieve_binary_block_get_size(sblock); + sieve_offset_t offset; + uint8_t encoded[sizeof(offset)]; + int i; + + i_assert(cur_address > address); + i_assert((cur_address - address) <= (sieve_offset_t)-1); + offset = cur_address - address; + for (i = sizeof(offset)-1; i >= 0; i--) { + encoded[i] = (uint8_t)offset; + offset >>= 8; + } + + _sieve_binary_update_data(sblock, address, encoded, sizeof(offset)); +} + +/* Literal emission */ + +sieve_size_t sieve_binary_emit_integer(struct sieve_binary_block *sblock, + sieve_number_t integer) +{ + sieve_size_t address = _sieve_binary_block_get_size(sblock); + uint8_t buffer[sizeof(sieve_number_t) + 1]; + int bufpos = sizeof(buffer) - 1; + + /* Encode last byte [0xxxxxxx]; msb == 0 marks the last byte */ + buffer[bufpos] = integer & 0x7F; + bufpos--; + + /* Encode first bytes [1xxxxxxx] */ + integer >>= 7; + while (integer > 0) { + buffer[bufpos] = (integer & 0x7F) | 0x80; + bufpos--; + integer >>= 7; + } + + /* Emit encoded integer */ + bufpos++; + _sieve_binary_emit_data(sblock, buffer + bufpos, sizeof(buffer) - bufpos); + + return address; +} + +static inline sieve_size_t +sieve_binary_emit_dynamic_data(struct sieve_binary_block *sblock, + const void *data, sieve_size_t size) +{ + sieve_size_t address = + sieve_binary_emit_integer(sblock, (sieve_number_t)size); + + _sieve_binary_emit_data(sblock, data, size); + + return address; +} + +sieve_size_t sieve_binary_emit_cstring(struct sieve_binary_block *sblock, + const char *str) +{ + sieve_size_t address = + sieve_binary_emit_dynamic_data(sblock, (void *)str, + (sieve_size_t)strlen(str)); + + _sieve_binary_emit_byte(sblock, 0); + return address; +} + +sieve_size_t sieve_binary_emit_string(struct sieve_binary_block *sblock, + const string_t *str) +{ + sieve_size_t address = + sieve_binary_emit_dynamic_data(sblock, (void *)str_data(str), + (sieve_size_t)str_len(str)); + + _sieve_binary_emit_byte(sblock, 0); + return address; +} + +/* + * Extension emission + */ + +sieve_size_t sieve_binary_emit_extension(struct sieve_binary_block *sblock, + const struct sieve_extension *ext, + unsigned int offset) +{ + sieve_size_t address = _sieve_binary_block_get_size(sblock); + struct sieve_binary_extension_reg *ereg = NULL; + + (void)sieve_binary_extension_register(sblock->sbin, ext, &ereg); + + i_assert(ereg != NULL); + + _sieve_binary_emit_byte(sblock, offset + ereg->index); + return address; +} + +void sieve_binary_emit_extension_object( + struct sieve_binary_block *sblock, + const struct sieve_extension_objects *objs, unsigned int code) +{ + if (objs->count > 1) + _sieve_binary_emit_byte(sblock, code); +} + +/* + * Code retrieval + */ + +#define ADDR_CODE_READ(block) \ + size_t _code_size; \ + const int8_t *_code = buffer_get_data((block)->data, &_code_size) + +#define ADDR_CODE_AT(address) \ + ((int8_t)(_code[*address])) +#define ADDR_DATA_AT(address) \ + ((uint8_t)(_code[*address])) +#define ADDR_POINTER(address) \ + ((const int8_t *)(&_code[*address])) + +#define ADDR_BYTES_LEFT(address) \ + ((*address) > _code_size ? 0 : ((_code_size) - (*address))) +#define ADDR_JUMP(address, offset) \ + (*address) += offset + +/* Literals */ + +bool sieve_binary_read_byte(struct sieve_binary_block *sblock, + sieve_size_t *address, unsigned int *byte_r) +{ + ADDR_CODE_READ(sblock); + + if (ADDR_BYTES_LEFT(address) >= 1) { + if (byte_r != NULL) + *byte_r = ADDR_DATA_AT(address); + ADDR_JUMP(address, 1); + + return TRUE; + } + + if (byte_r != NULL) + *byte_r = 0; + return FALSE; +} + +bool sieve_binary_read_code(struct sieve_binary_block *sblock, + sieve_size_t *address, signed int *code_r) +{ + ADDR_CODE_READ(sblock); + + if (ADDR_BYTES_LEFT(address) >= 1) { + if (code_r != NULL) + *code_r = ADDR_CODE_AT(address); + ADDR_JUMP(address, 1); + + return TRUE; + } + + if (code_r != NULL) + *code_r = 0; + return FALSE; +} + + +bool sieve_binary_read_offset(struct sieve_binary_block *sblock, + sieve_size_t *address, sieve_offset_t *offset_r) +{ + sieve_offset_t offs = 0; + ADDR_CODE_READ(sblock); + + if (ADDR_BYTES_LEFT(address) >= 4) { + int i; + + for (i = 0; i < 4; i++) { + offs = (offs << 8) + ADDR_DATA_AT(address); + ADDR_JUMP(address, 1); + } + + if (offset_r != NULL) + *offset_r = offs; + + return TRUE; + } + return FALSE; +} + +/* FIXME: might need negative numbers in the future */ +bool sieve_binary_read_integer(struct sieve_binary_block *sblock, + sieve_size_t *address, sieve_number_t *int_r) +{ + int bits = sizeof(sieve_number_t) * 8; + sieve_number_t integer = 0; + + ADDR_CODE_READ(sblock); + + if (ADDR_BYTES_LEFT(address) == 0) + return FALSE; + + /* Read first integer bytes [1xxxxxxx] */ + while ((ADDR_DATA_AT(address) & 0x80) > 0) { + if (ADDR_BYTES_LEFT(address) > 0 && bits > 0) { + integer |= ADDR_DATA_AT(address) & 0x7F; + ADDR_JUMP(address, 1); + + /* Each byte encodes 7 bits of the integer */ + integer <<= 7; + bits -= 7; + } else { + /* This is an error */ + return FALSE; + } + } + + /* Read last byte [0xxxxxxx] */ + integer |= ADDR_DATA_AT(address) & 0x7F; + ADDR_JUMP(address, 1); + + if (int_r != NULL) + *int_r = integer; + return TRUE; +} + +bool sieve_binary_read_string(struct sieve_binary_block *sblock, + sieve_size_t *address, string_t **str_r) +{ + unsigned int strlen = 0; + const char *strdata; + + ADDR_CODE_READ(sblock); + + if (!sieve_binary_read_unsigned(sblock, address, &strlen)) + return FALSE; + + if (strlen > ADDR_BYTES_LEFT(address)) + return FALSE; + + strdata = (const char *)ADDR_POINTER(address); + ADDR_JUMP(address, strlen); + + if (ADDR_CODE_AT(address) != 0) + return FALSE; + + if (str_r != NULL) + *str_r = t_str_new_const(strdata, strlen); + + ADDR_JUMP(address, 1); + + return TRUE; +} + +bool sieve_binary_read_extension(struct sieve_binary_block *sblock, + sieve_size_t *address, unsigned int *offset_r, + const struct sieve_extension **ext_r) +{ + unsigned int code; + unsigned int offset = *offset_r; + const struct sieve_extension *ext = NULL; + + ADDR_CODE_READ(sblock); + + if (ADDR_BYTES_LEFT(address) == 0) + return FALSE; + + *offset_r = code = ADDR_DATA_AT(address); + ADDR_JUMP(address, 1); + + if (code >= offset) { + ext = sieve_binary_extension_get_by_index(sblock->sbin, + (code - offset)); + if (ext == NULL) + return FALSE; + } + + if (ext_r != NULL) + *ext_r = ext; + return TRUE; +} + +const void * +sieve_binary_read_extension_object(struct sieve_binary_block *sblock, + sieve_size_t *address, + const struct sieve_extension_objects *objs) +{ + unsigned int code; + + ADDR_CODE_READ(sblock); + + if (objs->count == 0) + return NULL; + if (objs->count == 1) + return objs->objects; + if (ADDR_BYTES_LEFT(address) == 0) + return NULL; + + code = ADDR_DATA_AT(address); + ADDR_JUMP(address, 1); + + if (code >= objs->count) + return NULL; + return ((const void *const *)objs->objects)[code]; +} diff --git a/pigeonhole/src/lib-sieve/sieve-binary-debug.c b/pigeonhole/src/lib-sieve/sieve-binary-debug.c new file mode 100644 index 0000000..5e8b13a --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-binary-debug.c @@ -0,0 +1,276 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-code.h" + +#include "sieve-binary-private.h" + +/* Quick 'n dirty debug */ +#if 0 +#define debug_printf(...) printf ("lineinfo: " __VA_ARGS__) +#else +#define debug_printf(...) +#endif + +/* + * Opcodes + */ + +enum { + LINPROG_OP_COPY, + LINPROG_OP_ADVANCE_PC, + LINPROG_OP_ADVANCE_LINE, + LINPROG_OP_SET_COLUMN, + LINPROG_OP_SPECIAL_BASE +}; + +#define LINPROG_LINE_BASE 0 +#define LINPROG_LINE_RANGE 4 + +/* + * Lineinfo writer + */ + +struct sieve_binary_debug_writer { + struct sieve_binary_block *sblock; + + sieve_size_t address; + unsigned int line; + unsigned int column; +}; + +struct sieve_binary_debug_writer * +sieve_binary_debug_writer_init(struct sieve_binary_block *sblock) +{ + struct sieve_binary_debug_writer *dwriter; + + dwriter = i_new(struct sieve_binary_debug_writer, 1); + dwriter->sblock = sblock; + + return dwriter; +} + +void sieve_binary_debug_writer_deinit( + struct sieve_binary_debug_writer **dwriter) +{ + i_free(*dwriter); + *dwriter = NULL; +} + +void sieve_binary_debug_emit(struct sieve_binary_debug_writer *dwriter, + sieve_size_t code_address, unsigned int code_line, + unsigned int code_column) +{ + i_assert(code_address >= dwriter->address); + + struct sieve_binary_block *sblock = dwriter->sblock; + sieve_size_t address_inc = code_address - dwriter->address; + int line_inc = (code_line > dwriter->line ? + (int)(code_line - dwriter->line) : + -(int)(dwriter->line - code_line)); + unsigned int sp_opcode = 0; + + /* Check for applicability of special opcode */ + if (line_inc > 0 && + (LINPROG_LINE_BASE + LINPROG_LINE_RANGE - 1) >= line_inc) { + sp_opcode = LINPROG_OP_SPECIAL_BASE + + (line_inc - LINPROG_LINE_BASE) + + (LINPROG_LINE_RANGE * address_inc); + + if (sp_opcode > 255) + sp_opcode = 0; + } + + /* Update line and address */ + if (sp_opcode == 0) { + if (line_inc != 0) { + (void)sieve_binary_emit_byte(sblock, + LINPROG_OP_ADVANCE_LINE); + (void)sieve_binary_emit_unsigned( + sblock, (unsigned int)line_inc); + } + + if (address_inc > 0) { + (void)sieve_binary_emit_byte(sblock, + LINPROG_OP_ADVANCE_PC); + (void)sieve_binary_emit_unsigned(sblock, address_inc); + } + } else { + (void)sieve_binary_emit_byte(sblock, sp_opcode); + } + + /* Set column */ + if (dwriter->column != code_column) { + (void)sieve_binary_emit_byte(sblock, LINPROG_OP_SET_COLUMN); + (void)sieve_binary_emit_unsigned(sblock, code_column); + } + + /* Generate matrix row */ + (void)sieve_binary_emit_byte(sblock, LINPROG_OP_COPY); + + dwriter->address = code_address; + dwriter->line = code_line; + dwriter->column = code_column; +} + +/* + * Debug reader + */ + +struct sieve_binary_debug_reader { + struct sieve_binary_block *sblock; + + sieve_size_t address, last_address; + unsigned int line, last_line; + + unsigned int column; + + sieve_size_t state; +}; + +struct sieve_binary_debug_reader * +sieve_binary_debug_reader_init(struct sieve_binary_block *sblock) +{ + struct sieve_binary_debug_reader *dreader; + + dreader = i_new(struct sieve_binary_debug_reader, 1); + dreader->sblock = sblock; + + return dreader; +} + +void sieve_binary_debug_reader_deinit( + struct sieve_binary_debug_reader **dreader) +{ + i_free(*dreader); + *dreader = NULL; +} + +void sieve_binary_debug_reader_reset(struct sieve_binary_debug_reader *dreader) +{ + dreader->address = 0; + dreader->line = 0; + dreader->column = 0; + dreader->state = 0; +} + +unsigned int +sieve_binary_debug_read_line(struct sieve_binary_debug_reader *dreader, + sieve_size_t code_address) +{ + size_t linprog_size; + sieve_size_t address; + unsigned int line; + + if (code_address < dreader->last_address) + sieve_binary_debug_reader_reset(dreader); + + if (code_address >= dreader->last_address && + code_address < dreader->address) { + debug_printf("%08llx: NOOP [%08llx]\n", + (unsigned long long)dreader->state, + (unsigned long long)code_address); + return dreader->last_line; + } + + address = dreader->address; + line = dreader->line; + + debug_printf("%08llx: READ [%08llx]\n", + (unsigned long long)dreader->state, + (unsigned long long)code_address); + + linprog_size = sieve_binary_block_get_size(dreader->sblock); + while (dreader->state < linprog_size) { + unsigned int opcode; + unsigned int value; + int line_inc; + + if (sieve_binary_read_byte(dreader->sblock, + &dreader->state, &opcode)) { + switch (opcode) { + case LINPROG_OP_COPY: + debug_printf("%08llx: COPY ==> %08llx: %ld\n", + (unsigned long long)dreader->state, + (unsigned long long)address, line); + + dreader->last_address = dreader->address; + dreader->last_line = dreader->line; + + dreader->address = address; + dreader->line = line; + + if (code_address < address) + return dreader->last_line; + else if (code_address == address) + return dreader->line; + break; + case LINPROG_OP_ADVANCE_PC: + debug_printf("%08llx: ADV_PC\n", + (unsigned long long)dreader->state); + if (!sieve_binary_read_unsigned( + dreader->sblock, &dreader->state, + &value)) { + sieve_binary_debug_reader_reset(dreader); + return 0; + } + debug_printf(" : + %d\n", value); + address += value; + break; + case LINPROG_OP_ADVANCE_LINE: + debug_printf("%08llx: ADV_LINE\n", + (unsigned long long)dreader->state); + if (!sieve_binary_read_unsigned( + dreader->sblock, &dreader->state, + &value)) { + sieve_binary_debug_reader_reset(dreader); + return 0; + } + line_inc = (int)value; + debug_printf(" : + %d\n", line_inc); + line = (line_inc > 0 ? + line + (unsigned int)line_inc : + line - (unsigned int)-line_inc); + break; + case LINPROG_OP_SET_COLUMN: + debug_printf("%08llx: SET_COL\n", + (unsigned long long)dreader->state); + if (!sieve_binary_read_unsigned( + dreader->sblock, &dreader->state, + &value)) { + sieve_binary_debug_reader_reset(dreader); + return 0; + } + debug_printf(" : = %d\n", value); + dreader->column = value; + break; + default: + opcode -= LINPROG_OP_SPECIAL_BASE; + + address += (opcode / LINPROG_LINE_RANGE); + line += LINPROG_LINE_BASE + + (opcode % LINPROG_LINE_RANGE); + + debug_printf("%08llx: SPECIAL\n", + (unsigned long long)dreader->state); + debug_printf(" : +A %d +L %d\n", + (opcode / LINPROG_LINE_RANGE), + LINPROG_LINE_BASE + + (opcode % LINPROG_LINE_RANGE)); + break; + } + } else { + debug_printf("OPCODE READ FAILED\n"); + sieve_binary_debug_reader_reset(dreader); + return 0; + } + } + + return dreader->line; +} + diff --git a/pigeonhole/src/lib-sieve/sieve-binary-dumper.c b/pigeonhole/src/lib-sieve/sieve-binary-dumper.c new file mode 100644 index 0000000..3b3bb4b --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-binary-dumper.c @@ -0,0 +1,326 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "ostream.h" +#include "array.h" +#include "buffer.h" +#include "time-util.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-dump.h" +#include "sieve-script.h" + +#include "sieve-binary-private.h" + +/* + * Binary dumper object + */ + +struct sieve_binary_dumper { + pool_t pool; + + /* Dumptime environment */ + struct sieve_dumptime_env dumpenv; +}; + +struct sieve_binary_dumper * +sieve_binary_dumper_create(struct sieve_binary *sbin) +{ + pool_t pool; + struct sieve_binary_dumper *dumper; + + pool = pool_alloconly_create("sieve_binary_dumper", 4096); + dumper = p_new(pool, struct sieve_binary_dumper, 1); + dumper->pool = pool; + dumper->dumpenv.dumper = dumper; + + dumper->dumpenv.sbin = sbin; + sieve_binary_ref(sbin); + + dumper->dumpenv.svinst = sieve_binary_svinst(sbin); + + return dumper; +} + +void sieve_binary_dumper_free(struct sieve_binary_dumper **dumper) +{ + sieve_binary_unref(&(*dumper)->dumpenv.sbin); + pool_unref(&((*dumper)->pool)); + + *dumper = NULL; +} + +pool_t sieve_binary_dumper_pool(struct sieve_binary_dumper *dumper) +{ + return dumper->pool; +} + +/* + * Formatted output + */ + +void sieve_binary_dumpf(const struct sieve_dumptime_env *denv, + const char *fmt, ...) +{ + string_t *outbuf = t_str_new(128); + va_list args; + + va_start(args, fmt); + str_vprintfa(outbuf, fmt, args); + va_end(args); + + o_stream_nsend(denv->stream, str_data(outbuf), str_len(outbuf)); +} + +void sieve_binary_dump_sectionf(const struct sieve_dumptime_env *denv, + const char *fmt, ...) +{ + string_t *outbuf = t_str_new(128); + va_list args; + + va_start(args, fmt); + str_printfa(outbuf, "\n* "); + str_vprintfa(outbuf, fmt, args); + str_printfa(outbuf, ":\n\n"); + va_end(args); + + o_stream_nsend(denv->stream, str_data(outbuf), str_len(outbuf)); +} + +/* + * Dumping the binary + */ + +bool sieve_binary_dumper_run(struct sieve_binary_dumper *dumper, + struct ostream *stream, bool verbose) +{ + struct sieve_binary *sbin = dumper->dumpenv.sbin; + struct sieve_script *script = sieve_binary_script(sbin); + struct sieve_dumptime_env *denv = &(dumper->dumpenv); + const struct sieve_binary_header *header = &sbin->header; + struct sieve_binary_block *sblock; + bool success = TRUE; + sieve_size_t offset; + int count, i; + + dumper->dumpenv.stream = stream; + + /* Dump header */ + + sieve_binary_dump_sectionf(denv, "Header"); + + sieve_binary_dumpf(denv, + "version = %"PRIu16".%"PRIu16"\n" + "flags = 0x%08"PRIx32"\n", + header->version_major, header->version_minor, + header->flags); + if (header->resource_usage.update_time != 0) { + time_t update_time = + (time_t)header->resource_usage.update_time; + sieve_binary_dumpf(denv, + "resource usage:\n" + " update time = %s\n" + " cpu time = %"PRIu32" ms\n", + t_strflocaltime("%Y-%m-%d %H:%M:%S", + update_time), + header->resource_usage.cpu_time_msecs); + } + + /* Dump list of binary blocks */ + + if (verbose) { + count = sieve_binary_block_count(sbin); + + sieve_binary_dump_sectionf(denv, "Binary blocks (count: %d)", + count); + + for (i = 0; i < count; i++) { + struct sieve_binary_block *sblock = + sieve_binary_block_get(sbin, i); + + sieve_binary_dumpf( + denv, "%3d: size: %zu bytes\n", + i, sieve_binary_block_get_size(sblock)); + } + } + + /* Dump script metadata */ + + sieve_binary_dump_sectionf(denv, "Script metadata (block: %d)", + SBIN_SYSBLOCK_SCRIPT_DATA); + sblock = sieve_binary_block_get(sbin, SBIN_SYSBLOCK_SCRIPT_DATA); + + T_BEGIN { + offset = 0; + success = sieve_script_binary_dump_metadata( + script, denv, sblock, &offset); + } T_END; + + if (!success) + return FALSE; + + /* Dump list of used extensions */ + + count = sieve_binary_extensions_count(sbin); + if (count > 0) { + sieve_binary_dump_sectionf( + denv, "Required extensions (block: %d)", + SBIN_SYSBLOCK_EXTENSIONS); + + for (i = 0; i < count; i++) { + const struct sieve_extension *ext = + sieve_binary_extension_get_by_index(sbin, i); + + sblock = sieve_binary_extension_get_block(sbin, ext); + + if (sblock == NULL) { + sieve_binary_dumpf( + denv, "%3d: %s (id: %d)\n", + i, sieve_extension_name(ext), ext->id); + } else { + sieve_binary_dumpf( + denv, "%3d: %s (id: %d; block: %d)\n", + i, sieve_extension_name(ext), ext->id, + sieve_binary_block_get_id(sblock)); + } + } + } + + /* Dump extension-specific elements of the binary */ + + count = sieve_binary_extensions_count(sbin); + if (count > 0) { + for (i = 0; i < count; i++) { + success = TRUE; + + T_BEGIN { + const struct sieve_extension *ext = + sieve_binary_extension_get_by_index( + sbin, i); + + if (ext->def != NULL && + ext->def->binary_dump != NULL) { + success = ext->def->binary_dump( + ext, denv); + } + } T_END; + + if (!success) + return FALSE; + } + } + + /* Dump main program */ + + sieve_binary_dump_sectionf(denv, "Main program (block: %d)", + SBIN_SYSBLOCK_MAIN_PROGRAM); + + dumper->dumpenv.sblock = + sieve_binary_block_get(sbin, SBIN_SYSBLOCK_MAIN_PROGRAM); + dumper->dumpenv.cdumper = sieve_code_dumper_create(&(dumper->dumpenv)); + + if (dumper->dumpenv.cdumper != NULL) { + sieve_code_dumper_run(dumper->dumpenv.cdumper); + + sieve_code_dumper_free(&dumper->dumpenv.cdumper); + } + + /* Finish with empty line */ + sieve_binary_dumpf(denv, "\n"); + + return TRUE; +} + +/* + * Hexdump production + */ + +void sieve_binary_dumper_hexdump(struct sieve_binary_dumper *dumper, + struct ostream *stream) +{ + struct sieve_binary *sbin = dumper->dumpenv.sbin; + struct sieve_dumptime_env *denv = &(dumper->dumpenv); + int count, i; + + dumper->dumpenv.stream = stream; + + count = sieve_binary_block_count(sbin); + + /* Block overview */ + + sieve_binary_dump_sectionf(denv, "Binary blocks (count: %d)", count); + + for (i = 0; i < count; i++) { + struct sieve_binary_block *sblock = + sieve_binary_block_get(sbin, i); + + sieve_binary_dumpf(denv, "%3d: size: %zu bytes\n", + i, sieve_binary_block_get_size(sblock)); + } + + /* Hexdump for each block */ + + for (i = 0; i < count; i++) { + struct sieve_binary_block *sblock = + sieve_binary_block_get(sbin, i); + buffer_t *blockbuf = sieve_binary_block_get_buffer(sblock); + string_t *line; + size_t data_size; + const unsigned char *data; + size_t offset; + + data = buffer_get_data(blockbuf, &data_size); + + // FIXME: calculate offset more nicely. + sieve_binary_dump_sectionf( + denv, "Block %d (%zu bytes, file offset %08llx)", i, data_size, + (unsigned long long int)sblock->offset + 8); + + line = t_str_new(128); + offset = 0; + while (offset < data_size) { + size_t len = (data_size - offset >= 16 ? + 16 : data_size - offset); + size_t b; + + str_printfa(line, "%08llx ", + (unsigned long long)offset); + + for (b = 0; b < len; b++) { + str_printfa(line, "%02x ", data[offset+b]); + if (b == 7) + str_append_c(line, ' '); + } + + if (len < 16) { + if (len <= 7) + str_append_c(line, ' '); + + for (b = len; b < 16; b++) + str_append(line, " "); + } + + str_append(line, " |"); + + for (b = 0; b < len; b++) { + const unsigned char c = data[offset+b]; + + if (c >= 32 && c <= 126) + str_append_c(line, (const char)c); + else + str_append_c(line, '.'); + } + + str_append(line, "|\n"); + o_stream_nsend(stream, str_data(line), str_len(line)); + str_truncate(line, 0); + offset += len; + } + + str_printfa(line, "%08llx\n", (unsigned long long)offset); + o_stream_nsend(stream, str_data(line), str_len(line)); + } +} diff --git a/pigeonhole/src/lib-sieve/sieve-binary-dumper.h b/pigeonhole/src/lib-sieve/sieve-binary-dumper.h new file mode 100644 index 0000000..4343190 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-binary-dumper.h @@ -0,0 +1,41 @@ +#ifndef SIEVE_BINARY_DUMPER_H +#define SIEVE_BINARY_DUMPER_H + +#include "sieve-common.h" + +/* + * Binary dumper object + */ + +struct sieve_binary_dumper; + +struct sieve_binary_dumper * +sieve_binary_dumper_create(struct sieve_binary *sbin); +void sieve_binary_dumper_free(struct sieve_binary_dumper **dumper); + +pool_t sieve_binary_dumper_pool(struct sieve_binary_dumper *dumper); + +/* + * Formatted output + */ + +void sieve_binary_dumpf(const struct sieve_dumptime_env *denv, + const char *fmt, ...) ATTR_FORMAT(2, 3); +void sieve_binary_dump_sectionf(const struct sieve_dumptime_env *denv, + const char *fmt, ...) ATTR_FORMAT(2, 3); + +/* + * Dumping the binary + */ + +bool sieve_binary_dumper_run(struct sieve_binary_dumper *dumper, + struct ostream *stream, bool verbose); + +/* + * Hexdump production + */ + +void sieve_binary_dumper_hexdump(struct sieve_binary_dumper *dumper, + struct ostream *stream); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-binary-file.c b/pigeonhole/src/lib-sieve/sieve-binary-file.c new file mode 100644 index 0000000..8eedbc2 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-binary-file.c @@ -0,0 +1,1042 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" +#include "mempool.h" +#include "buffer.h" +#include "hash.h" +#include "array.h" +#include "ostream.h" +#include "eacces-error.h" +#include "safe-mkstemp.h" +#include "file-lock.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-extensions.h" +#include "sieve-code.h" +#include "sieve-script.h" + +#include "sieve-binary-private.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> + +/* + * Macros + */ + +#define SIEVE_BINARY_MAGIC 0xcafebabe +#define SIEVE_BINARY_MAGIC_OTHER_ENDIAN 0xbebafeca + +#define SIEVE_BINARY_ALIGN(offset) \ + (((offset) + 3) & ~3U) +#define SIEVE_BINARY_ALIGN_PTR(ptr) \ + ((void *) SIEVE_BINARY_ALIGN(((size_t) ptr))) + +#define SIEVE_BINARY_PRE_HDR_SIZE_MAJOR 1 +#define SIEVE_BINARY_PRE_HDR_SIZE_MINOR 4 +#define SIEVE_BINARY_PRE_HDR_SIZE_HDR_SIZE 12 + +/* + * Header and record structures of the binary on disk + */ + +struct sieve_binary_block_index { + uint32_t id; + uint32_t size; + uint32_t offset; + uint32_t ext_id; +}; + +struct sieve_binary_block_header { + uint32_t id; + uint32_t size; +}; + +/* + * Header manipulation + */ + +static int +sieve_binary_file_read_header(struct sieve_binary *sbin, int fd, + struct sieve_binary_header *header_r, + enum sieve_error *error_r) +{ + struct sieve_binary_header header; + enum sieve_error error; + ssize_t rret; + + if (error_r == NULL) + error_r = &error; + *error_r = SIEVE_ERROR_NONE; + + rret = pread(fd, &header, sizeof(header), 0); + if (rret == 0) { + e_error(sbin->event, "read: " + "file is not large enough to contain the header"); + *error_r = SIEVE_ERROR_NOT_VALID; + return -1; + } else if (rret < 0) { + e_error(sbin->event, "read: " + "failed to read from binary: %m"); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } else if (rret != sizeof(header)) { + e_error(sbin->event, "read: " + "header read only partially %zd/%zu", + rret, sizeof(header)); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + + /* Check header validity */ + if (header.magic != SIEVE_BINARY_MAGIC) { + if (header.magic != SIEVE_BINARY_MAGIC_OTHER_ENDIAN) { + e_error(sbin->event, "read: " + "binary has corrupted header " + "(0x%08x) or it is not a Sieve binary", + header.magic); + } else { + e_error(sbin->event, "read: " + "binary stored with in different endian format " + "(automatically fixed when re-compiled)"); + } + *error_r = SIEVE_ERROR_NOT_VALID; + return -1; + } + /* Check binary version */ + if (header.version_major == SIEVE_BINARY_PRE_HDR_SIZE_MAJOR && + header.version_minor == SIEVE_BINARY_PRE_HDR_SIZE_MINOR) { + /* Old header without hdr_size; clear new fields */ + static const size_t old_header_size = + SIEVE_BINARY_PRE_HDR_SIZE_HDR_SIZE; + memset(PTR_OFFSET(&header, old_header_size), 0, + (sizeof(header) - old_header_size)); + header.hdr_size = old_header_size; + } else if (header.version_major != SIEVE_BINARY_VERSION_MAJOR) { + /* Binary is of different major version. Caller will have to + recompile */ + e_error(sbin->event, "read: " + "binary stored with different major version %d.%d " + "(!= %d.%d; automatically fixed when re-compiled)", + (int)header.version_major, (int)header.version_minor, + SIEVE_BINARY_VERSION_MAJOR, SIEVE_BINARY_VERSION_MINOR); + *error_r = SIEVE_ERROR_NOT_VALID; + return -1; + } else if (header.hdr_size < SIEVE_BINARY_BASE_HEADER_SIZE) { + /* Header size is smaller than base size */ + e_error(sbin->event, "read: " + "binary is corrupt: header size is too small"); + *error_r = SIEVE_ERROR_NOT_VALID; + return -1; + } + /* Check block content */ + if (header.blocks == 0) { + e_error(sbin->event, "read: " + "binary is corrupt: it contains no blocks"); + *error_r = SIEVE_ERROR_NOT_VALID; + return -1; + } + /* Valid */ + *header_r = header; + return 0; +} + +static int +sieve_binary_file_write_header(struct sieve_binary *sbin, int fd, + struct sieve_binary_header *header, + enum sieve_error *error_r) ATTR_NULL(4) +{ + ssize_t wret; + + wret = pwrite(fd, header, sizeof(*header), 0); + if (wret < 0) { + e_error(sbin->event, "update: " + "failed to write to binary: %m"); + if (error_r != NULL) + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } else if (wret != sizeof(*header)) { + e_error(sbin->event, "update: " + "header written partially %zd/%zu", + wret, sizeof(*header)); + if (error_r != NULL) + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + return 0; +} + +static void sieve_binary_file_update_header(struct sieve_binary *sbin) +{ + struct sieve_binary_header *header = &sbin->header; + struct sieve_resource_usage rusage; + + sieve_binary_get_resource_usage(sbin, &rusage); + + i_zero(&header->resource_usage); + if (HAS_ALL_BITS(header->flags, SIEVE_BINARY_FLAG_RESOURCE_LIMIT) || + sieve_resource_usage_is_high(sbin->svinst, &rusage)) { + header->resource_usage.update_time = ioloop_time; + header->resource_usage.cpu_time_msecs = rusage.cpu_time_msecs; + } + + sieve_resource_usage_init(&sbin->rusage); + sbin->rusage_updated = FALSE; + + (void)sieve_binary_check_resource_usage(sbin); +} + +/* + * Saving the binary to a file. + */ + +static inline bool +_save_skip(struct sieve_binary *sbin, struct ostream *stream, size_t size) +{ + if ((o_stream_seek(stream, stream->offset + size)) <= 0) { + e_error(sbin->event, "save: " + "failed to skip output stream to position " + "%"PRIuUOFF_T": %s", stream->offset + size, + strerror(stream->stream_errno)); + return FALSE; + } + + return TRUE; +} + +static inline bool +_save_skip_aligned(struct sieve_binary *sbin, struct ostream *stream, + size_t size, uoff_t *offset) +{ + uoff_t aligned_offset = SIEVE_BINARY_ALIGN(stream->offset); + + if ((o_stream_seek(stream, aligned_offset + size)) <= 0) { + e_error(sbin->event, "save: " + "failed to skip output stream to position " + "%"PRIuUOFF_T": %s", aligned_offset + size, + strerror(stream->stream_errno)); + return FALSE; + } + + if (offset != NULL) + *offset = aligned_offset; + return TRUE; +} + +/* FIXME: Is this even necessary for a file? */ +static bool +_save_full(struct sieve_binary *sbin, struct ostream *stream, + const void *data, size_t size) +{ + size_t bytes_left = size; + const void *pdata = data; + + while (bytes_left > 0) { + ssize_t ret; + + ret = o_stream_send(stream, pdata, bytes_left); + if (ret <= 0) { + e_error(sbin->event, "save: " + "failed to write %zu bytes " + "to output stream: %s", bytes_left, + strerror(stream->stream_errno)); + return FALSE; + } + + pdata = PTR_OFFSET(pdata, ret); + bytes_left -= ret; + } + + return TRUE; +} + +static bool +_save_aligned(struct sieve_binary *sbin, struct ostream *stream, + const void *data, size_t size, uoff_t *offset) +{ + uoff_t aligned_offset = SIEVE_BINARY_ALIGN(stream->offset); + + o_stream_cork(stream); + + /* Align the data by adding zeroes to the output stream */ + if (stream->offset < aligned_offset) { + if (!_save_skip(sbin, stream, + (aligned_offset - stream->offset))) + return FALSE; + } + + if (!_save_full(sbin, stream, data, size)) + return FALSE; + + o_stream_uncork(stream); + + if (offset != NULL) + *offset = aligned_offset; + return TRUE; +} + +static bool +_save_block(struct sieve_binary *sbin, struct ostream *stream, unsigned int id) +{ + struct sieve_binary_block_header block_header; + struct sieve_binary_block *block; + const void *data; + size_t size; + + block = sieve_binary_block_get(sbin, id); + if (block == NULL) + return FALSE; + + data = buffer_get_data(block->data, &size); + + block_header.id = id; + block_header.size = size; + + if (!_save_aligned(sbin, stream, &block_header, sizeof(block_header), + &block->offset)) + return FALSE; + + return _save_aligned(sbin, stream, data, size, NULL); +} + +static bool +_save_block_index_record(struct sieve_binary *sbin, struct ostream *stream, + unsigned int id) +{ + struct sieve_binary_block *block; + struct sieve_binary_block_index header; + + block = sieve_binary_block_get(sbin, id); + if (block == NULL) + return FALSE; + + header.id = id; + header.size = buffer_get_used_size(block->data); + header.ext_id = block->ext_index; + header.offset = block->offset; + + if (!_save_full(sbin, stream, &header, sizeof(header))) { + e_error(sbin->event, "save: " + "failed to save block index header %d", id); + return FALSE; + } + + return TRUE; +} + +static bool +sieve_binary_save_to_stream(struct sieve_binary *sbin, struct ostream *stream) +{ + struct sieve_binary_header *header = &sbin->header; + struct sieve_binary_block *ext_block; + unsigned int ext_count, blk_count, i; + uoff_t block_index; + + blk_count = sieve_binary_block_count(sbin); + + /* Create header */ + + header->magic = SIEVE_BINARY_MAGIC; + header->version_major = SIEVE_BINARY_VERSION_MAJOR; + header->version_minor = SIEVE_BINARY_VERSION_MINOR; + header->blocks = blk_count; + header->hdr_size = sizeof(*header); + + header->flags &= ENUM_NEGATE(SIEVE_BINARY_FLAG_RESOURCE_LIMIT); + sieve_binary_file_update_header(sbin); + + if (!_save_aligned(sbin, stream, header, sizeof(*header), NULL)) { + e_error(sbin->event, "save: failed to save header"); + return FALSE; + } + + /* Skip block index for now */ + + if (!_save_skip_aligned( + sbin, stream, + (sizeof(struct sieve_binary_block_index) * blk_count), + &block_index)) + return FALSE; + + /* Create block containing all used extensions */ + + ext_block = sieve_binary_block_get(sbin, SBIN_SYSBLOCK_EXTENSIONS); + i_assert(ext_block != NULL); + sieve_binary_block_clear(ext_block); + + ext_count = array_count(&sbin->linked_extensions); + sieve_binary_emit_unsigned(ext_block, ext_count); + + for (i = 0; i < ext_count; i++) { + struct sieve_binary_extension_reg * const *ext = + array_idx(&sbin->linked_extensions, i); + + sieve_binary_emit_cstring( + ext_block, sieve_extension_name((*ext)->extension)); + sieve_binary_emit_unsigned( + ext_block, sieve_extension_version((*ext)->extension)); + sieve_binary_emit_unsigned(ext_block, (*ext)->block_id); + } + + /* Save all blocks into the binary */ + + for (i = 0; i < blk_count; i++) { + if (!_save_block(sbin, stream, i)) + return FALSE; + } + + /* Create the block index */ + o_stream_seek(stream, block_index); + for (i = 0; i < blk_count; i++) { + if (!_save_block_index_record(sbin, stream, i)) + return FALSE; + } + + return TRUE; +} + +static int +sieve_binary_do_save(struct sieve_binary *sbin, const char *path, bool update, + mode_t save_mode, enum sieve_error *error_r) +{ + int result, fd; + string_t *temp_path; + struct ostream *stream; + struct sieve_binary_extension_reg *const *regs; + unsigned int ext_count, i; + + if (error_r != NULL) + *error_r = SIEVE_ERROR_NONE; + + /* Check whether saving is necessary */ + if (!update && sbin->path != NULL && strcmp(sbin->path, path) == 0) { + e_debug(sbin->event, "save: " + "not saving binary, because it is already stored"); + return 0; + } + + /* Open it as temp file first, as not to overwrite an existing just yet */ + temp_path = t_str_new(256); + str_append(temp_path, path); + str_append_c(temp_path, '.'); + fd = safe_mkstemp_hostpid(temp_path, save_mode, (uid_t)-1, (gid_t)-1); + if (fd < 0) { + if (errno == EACCES) { + e_error(sbin->event, "save: " + "failed to create temporary file: %s", + eacces_error_get_creating("open", + str_c(temp_path))); + if (error_r != NULL) + *error_r = SIEVE_ERROR_NO_PERMISSION; + } else { + e_error(sbin->event, "save: " + "failed to create temporary file: " + "open(%s) failed: %m", str_c(temp_path)); + if (error_r != NULL) + *error_r = SIEVE_ERROR_TEMP_FAILURE; + } + return -1; + } + + /* Signal all extensions that we're about to save the binary */ + regs = array_get(&sbin->extensions, &ext_count); + for (i = 0; i < ext_count; i++) { + const struct sieve_binary_extension *binext = regs[i]->binext; + + if (binext != NULL && binext->binary_pre_save != NULL && + !binext->binary_pre_save(regs[i]->extension, sbin, + regs[i]->context, error_r)) + return -1; + } + + /* Save binary */ + result = 1; + stream = o_stream_create_fd(fd, 0); + if (!sieve_binary_save_to_stream(sbin, stream)) { + result = -1; + if (error_r != NULL) + *error_r = SIEVE_ERROR_TEMP_FAILURE; + } + o_stream_destroy(&stream); + + /* Close saved binary */ + if (close(fd) < 0) { + e_error(sbin->event, "save: " + "failed to close temporary file: " + "close(fd=%s) failed: %m", str_c(temp_path)); + } + + /* Replace any original binary atomically */ + if (result > 0 && (rename(str_c(temp_path), path) < 0)) { + if (errno == EACCES) { + e_error(sbin->event, "save: " + "failed to save binary: %s", + eacces_error_get_creating("rename", path)); + if (error_r != NULL) + *error_r = SIEVE_ERROR_NO_PERMISSION; + } else { + e_error(sbin->event, "save: " + "failed to save binary: " + "rename(%s, %s) failed: %m", + str_c(temp_path), path); + if (error_r != NULL) + *error_r = SIEVE_ERROR_TEMP_FAILURE; + } + result = -1; + } + + if (result < 0) { + /* Get rid of temp output (if any) */ + if (unlink(str_c(temp_path)) < 0 && errno != ENOENT) { + e_error(sbin->event, "save: " + "failed to clean up after error: " + "unlink(%s) failed: %m", str_c(temp_path)); + } + } else { + if (sbin->path == NULL) + sbin->path = p_strdup(sbin->pool, path); + + /* Signal all extensions that we successfully saved the binary. + */ + regs = array_get(&sbin->extensions, &ext_count); + for (i = 0; i < ext_count; i++) { + const struct sieve_binary_extension *binext = + regs[i]->binext; + + if (binext != NULL && + binext->binary_post_save != NULL && + !binext->binary_post_save(regs[i]->extension, sbin, + regs[i]->context, + error_r)) { + result = -1; + break; + } + } + + if (result < 0 && unlink(path) < 0 && errno != ENOENT) { + e_error(sbin->event, "failed to clean up after error: " + "unlink(%s) failed: %m", path); + } + } + + return result; +} + +int sieve_binary_save(struct sieve_binary *sbin, const char *path, bool update, + mode_t save_mode, enum sieve_error *error_r) +{ + int ret; + + sieve_binary_update_event(sbin, path); + ret = sieve_binary_do_save(sbin, path, update, save_mode, error_r); + sieve_binary_update_event(sbin, NULL); + + return ret; +} + + +/* + * Binary file management + */ + +static int +sieve_binary_fd_open(struct sieve_binary *sbin, const char *path, + int open_flags, enum sieve_error *error_r) +{ + int fd; + + if (error_r != NULL) + *error_r = SIEVE_ERROR_NONE; + + fd = open(path, open_flags); + if (fd < 0) { + switch (errno) { + case ENOENT: + if (error_r != NULL) + *error_r = SIEVE_ERROR_NOT_FOUND; + break; + case EACCES: + e_error(sbin->event, "open: " + "failed to open: %s", + eacces_error_get("open", path)); + if (error_r != NULL) + *error_r = SIEVE_ERROR_NO_PERMISSION; + break; + default: + e_error(sbin->event, "open: " + "failed to open: open(%s) failed: %m", path); + if (error_r != NULL) + *error_r = SIEVE_ERROR_TEMP_FAILURE; + break; + } + return -1; + } + return fd; +} + +static int +sieve_binary_file_open(struct sieve_binary *sbin, const char *path, + struct sieve_binary_file **file_r, + enum sieve_error *error_r) +{ + int fd, ret = 0; + struct stat st; + + if (error_r != NULL) + *error_r = SIEVE_ERROR_NONE; + + fd = sieve_binary_fd_open(sbin, path, O_RDONLY, error_r); + if (fd < 0) + return -1; + + if (fstat(fd, &st) < 0) { + if (errno != ENOENT) + e_error(sbin->event, "open: fstat() failed: %m"); + ret = -1; + } + + if (ret == 0 && !S_ISREG(st.st_mode)) { + e_error(sbin->event, "open: " + "binary is not a regular file"); + ret = -1; + } + + if (ret < 0) { + if (close(fd) < 0) { + e_error(sbin->event, "open: " + "close() failed after error: %m"); + } + return -1; + } + + pool_t pool; + struct sieve_binary_file *file; + + pool = pool_alloconly_create("sieve_binary_file", 4096); + file = p_new(pool, struct sieve_binary_file, 1); + file->pool = pool; + file->path = p_strdup(pool, path); + file->fd = fd; + file->st = st; + file->sbin = sbin; + + *file_r = file; + return 0; +} + +void sieve_binary_file_close(struct sieve_binary_file **_file) +{ + struct sieve_binary_file *file = *_file; + + *_file = NULL; + if (file == NULL) + return; + + if (file->fd != -1) { + if (close(file->fd) < 0) { + e_error(file->sbin->event, "close: " + "failed to close: close() failed: %m"); + } + } + + pool_unref(&file->pool); +} + +static int +sieve_binary_file_read(struct sieve_binary_file *file, off_t *offset, + void *buffer, size_t size) +{ + struct sieve_binary *sbin = file->sbin; + int ret; + void *indata = buffer; + size_t insize = size; + + *offset = SIEVE_BINARY_ALIGN(*offset); + + /* Seek to the correct position */ + if (*offset != file->offset && + lseek(file->fd, *offset, SEEK_SET) == (off_t)-1) { + e_error(sbin->event, "read: " + "failed to seek(fd, %lld, SEEK_SET): %m", + (long long) *offset); + return -1; + } + + /* Read record into memory */ + while (insize > 0) { + ret = read(file->fd, indata, insize); + if (ret <= 0) { + if (ret == 0) { + e_error(sbin->event, "read: " + "binary is truncated " + "(more data expected)"); + } else { + e_error(sbin->event, "read: " + "failed to read from binary: %m"); + } + break; + } + + indata = PTR_OFFSET(indata, ret); + insize -= ret; + } + + if (insize != 0) { + /* Failed to read the whole requested record */ + return 0; + } + + *offset += size; + file->offset = *offset; + return 1; +} + +static const void * +sieve_binary_file_load_data(struct sieve_binary_file *file, + off_t *offset, size_t size) +{ + void *data = t_malloc_no0(size); + + if (sieve_binary_file_read(file, offset, data, size) > 0) + return data; + + return NULL; +} + +static buffer_t * +sieve_binary_file_load_buffer(struct sieve_binary_file *file, + off_t *offset, size_t size) +{ + buffer_t *buffer = buffer_create_dynamic(file->pool, size); + + if (sieve_binary_file_read(file, offset, + buffer_get_space_unsafe(buffer, 0, size), + size) > 0) + return buffer; + + return NULL; +} + +/* + * Load binary from a file + */ + +#define LOAD_HEADER(sbin, offset, header) \ + (header *)sieve_binary_file_load_data(sbin->file, offset, \ + sizeof(header)) + +bool sieve_binary_load_block(struct sieve_binary_block *sblock) +{ + struct sieve_binary *sbin = sblock->sbin; + unsigned int id = sblock->id; + off_t offset = sblock->offset; + const struct sieve_binary_block_header *header = + LOAD_HEADER(sbin, &offset, + const struct sieve_binary_block_header); + + if (header == NULL) { + e_error(sbin->event, "load: binary is corrupt: " + "failed to read header of block %d", id); + return FALSE; + } + + if (header->id != id) { + e_error(sbin->event, "load: binary is corrupt: " + "header of block %d has non-matching id %d", + id, header->id); + return FALSE; + } + + sblock->data = sieve_binary_file_load_buffer(sbin->file, &offset, + header->size); + if (sblock->data == NULL) { + e_error(sbin->event, "load: " + "failed to read block %d of binary (size=%d)", + id, header->size); + return FALSE; + } + + return TRUE; +} + +static bool +_read_block_index_record(struct sieve_binary *sbin, off_t *offset, + unsigned int id) +{ + const struct sieve_binary_block_index *record = + LOAD_HEADER(sbin, offset, + const struct sieve_binary_block_index); + struct sieve_binary_block *block; + + if (record == NULL) { + e_error(sbin->event, "open: binary is corrupt: " + "failed to load block index record %d", id); + return FALSE; + } + + if (record->id != id) { + e_error(sbin->event, "open: binary is corrupt: " + "block index record %d has unexpected id %d", + id, record->id); + return FALSE; + } + + block = sieve_binary_block_create_id(sbin, id); + block->ext_index = record->ext_id; + block->offset = record->offset; + + return TRUE; +} + +static int _read_extensions(struct sieve_binary_block *sblock) +{ + struct sieve_binary *sbin = sblock->sbin; + sieve_size_t offset = 0; + unsigned int i, count; + int result = 1; + + if (!sieve_binary_read_unsigned(sblock, &offset, &count)) + return -1; + + for (i = 0; result > 0 && i < count; i++) { + T_BEGIN { + string_t *extension; + const struct sieve_extension *ext; + unsigned int version; + + if (sieve_binary_read_string(sblock, &offset, + &extension)) { + ext = sieve_extension_get_by_name( + sbin->svinst, str_c(extension)); + + if (ext == NULL) { + e_error(sbin->event, "open: " + "binary requires unknown extension `%s'", + str_sanitize(str_c(extension), 128)); + result = 0; + } else { + struct sieve_binary_extension_reg *ereg = NULL; + + (void)sieve_binary_extension_register(sbin, ext, &ereg); + if (!sieve_binary_read_unsigned(sblock, &offset, &version) || + !sieve_binary_read_unsigned(sblock, &offset, &ereg->block_id)) { + result = -1; + } else if (!sieve_extension_version_is(ext, version)) { + e_debug(sbin->event, "open: " + "binary was compiled with different version " + "of the `%s' extension (compiled v%d, expected v%d;" + "automatically fixed when re-compiled)", + sieve_extension_name(ext), version, + sieve_extension_version(ext)); + result = 0; + } + } + } else { + result = -1; + } + } T_END; + } + + return result; +} + +static bool +_sieve_binary_open(struct sieve_binary *sbin, enum sieve_error *error_r) +{ + bool result = TRUE; + off_t offset = 0; + struct sieve_binary_block *ext_block; + unsigned int i; + int ret; + + /* Read header */ + + ret = sieve_binary_file_read_header(sbin, sbin->file->fd, + &sbin->header, error_r); + if (ret < 0) + return FALSE; + offset = sbin->header.hdr_size; + + /* Load block index */ + + for (i = 0; i < sbin->header.blocks && result; i++) { + T_BEGIN { + if (!_read_block_index_record(sbin, &offset, i)) + result = FALSE; + } T_END; + } + + if (!result) { + if (error_r != NULL) + *error_r = SIEVE_ERROR_NOT_VALID; + return FALSE; + } + + /* Load extensions used by this binary */ + + T_BEGIN { + ext_block = sieve_binary_block_get( + sbin, SBIN_SYSBLOCK_EXTENSIONS); + if (ext_block == NULL) { + result = FALSE; + } else if ((ret = _read_extensions(ext_block)) <= 0) { + if (ret < 0) { + e_error(sbin->event, "open: binary is corrupt: " + "failed to load extension block"); + } + result = FALSE; + } + } T_END; + + if (!result) { + if (error_r != NULL) + *error_r = SIEVE_ERROR_NOT_VALID; + return FALSE; + } + return TRUE; +} + +struct sieve_binary * +sieve_binary_open(struct sieve_instance *svinst, const char *path, + struct sieve_script *script, enum sieve_error *error_r) +{ + struct sieve_binary_extension_reg *const *regs; + unsigned int ext_count, i; + struct sieve_binary *sbin; + struct sieve_binary_file *file; + + i_assert(script == NULL || sieve_script_svinst(script) == svinst); + + /* Create binary object */ + sbin = sieve_binary_create(svinst, script); + sbin->path = p_strdup(sbin->pool, path); + + if (sieve_binary_file_open(sbin, path, &file, error_r) < 0) { + sieve_binary_unref(&sbin); + return NULL; + } + + sbin->file = file; + + event_set_append_log_prefix( + sbin->event, + t_strdup_printf("binary %s: ", path)); + + if (!_sieve_binary_open(sbin, error_r)) { + sieve_binary_unref(&sbin); + return NULL; + } + + sieve_binary_activate(sbin); + + /* Signal open event to extensions */ + regs = array_get(&sbin->extensions, &ext_count); + for (i = 0; i < ext_count; i++) { + const struct sieve_binary_extension *binext = regs[i]->binext; + + if (binext != NULL && binext->binary_open != NULL && + !binext->binary_open(regs[i]->extension, sbin, + regs[i]->context)) { + /* Extension thinks its corrupt */ + if (error_r != NULL) + *error_r = SIEVE_ERROR_NOT_VALID; + sieve_binary_unref(&sbin); + return NULL; + } + } + return sbin; +} + +int sieve_binary_check_executable(struct sieve_binary *sbin, + enum sieve_error *error_r, + const char **client_error_r) +{ + if (error_r != NULL) + *error_r = SIEVE_ERROR_NONE; + *client_error_r = NULL; + + if (HAS_ALL_BITS(sbin->header.flags, + SIEVE_BINARY_FLAG_RESOURCE_LIMIT)) { + e_debug(sbin->event, + "Binary execution is blocked: " + "Cumulative resource usage limit exceeded " + "(resource limit flag is set)"); + if (error_r != NULL) + *error_r = SIEVE_ERROR_RESOURCE_LIMIT; + *client_error_r = "cumulative resource usage limit exceeded"; + return 0; + } + return 1; +} + +/* + * Resource usage + */ + +static int +sieve_binary_file_do_update_resource_usage( + struct sieve_binary *sbin, int fd, enum sieve_error *error_r) +{ + struct sieve_binary_header *header = &sbin->header; + struct file_lock *lock; + const char *error; + int ret; + + struct file_lock_settings lock_set = { + .lock_method = FILE_LOCK_METHOD_FCNTL, + }; + ret = file_wait_lock(fd, sbin->path, F_WRLCK, &lock_set, + SIEVE_BINARY_FILE_LOCK_TIMEOUT, &lock, &error); + if (ret <= 0) { + e_error(sbin->event, "%s", error); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + + ret = sieve_binary_file_read_header(sbin, fd, header, error_r); + if (ret == 0) { + sieve_binary_file_update_header(sbin); + ret = sieve_binary_file_write_header(sbin, fd, header, error_r); + } + + file_lock_free(&lock); + + return ret; +} + +int sieve_binary_file_update_resource_usage(struct sieve_binary *sbin, + enum sieve_error *error_r) +{ + enum sieve_error error; + int fd, ret = 0; + + if (error_r == NULL) + error_r = &error; + *error_r = SIEVE_ERROR_NONE; + + sieve_binary_file_close(&sbin->file); + + if (sbin->path == NULL) + return 0; + if (sbin->header.version_major != SIEVE_BINARY_VERSION_MAJOR) + return sieve_binary_save(sbin, sbin->path, TRUE, 0600, error_r); + + fd = sieve_binary_fd_open(sbin, sbin->path, O_RDWR, error_r); + if (fd < 0) + return -1; + + ret = sieve_binary_file_do_update_resource_usage(sbin, fd, error_r); + + if (close(fd) < 0) { + e_error(sbin->event, "update: " + "failed to close: close() failed: %m"); + } + + return ret; +} diff --git a/pigeonhole/src/lib-sieve/sieve-binary-private.h b/pigeonhole/src/lib-sieve/sieve-binary-private.h new file mode 100644 index 0000000..73d2d75 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-binary-private.h @@ -0,0 +1,240 @@ +#ifndef SIEVE_BINARY_PRIVATE_H +#define SIEVE_BINARY_PRIVATE_H + +#include "sieve-common.h" +#include "sieve-binary.h" +#include "sieve-extensions.h" + +#include <sys/stat.h> + +#define SIEVE_BINARY_FILE_LOCK_TIMEOUT 10 + +/* + * Binary file + */ + +enum SIEVE_BINARY_FLAGS { + SIEVE_BINARY_FLAG_RESOURCE_LIMIT = BIT(0), +}; + +struct sieve_binary_header { + uint32_t magic; + uint16_t version_major; + uint16_t version_minor; + uint32_t blocks; + + uint32_t hdr_size; + uint32_t flags; + + struct { + uint64_t update_time; + uint32_t cpu_time_msecs; + } resource_usage; +}; + +struct sieve_binary_file { + pool_t pool; + const char *path; + struct sieve_binary *sbin; + + struct stat st; + int fd; + off_t offset; +}; + +void sieve_binary_file_close(struct sieve_binary_file **_file); + +/* + * Internal structures + */ + +/* Extension registration */ + +struct sieve_binary_extension_reg { + /* The identifier of the extension within this binary */ + int index; + + /* Global extension object */ + const struct sieve_extension *extension; + + /* Extension to the binary; typically used to manage extension-specific + blocks in the binary and as a means to get a binary_free notification + to release references held by extensions. + */ + const struct sieve_binary_extension *binext; + + /* Context data associated to the binary by this extension */ + void *context; + + /* Main block for this extension */ + unsigned int block_id; +}; + +/* Block */ + +struct sieve_binary_block { + struct sieve_binary *sbin; + unsigned int id; + int ext_index; + + buffer_t *data; + + uoff_t offset; +}; + +/* + * Binary object + */ + +struct sieve_binary { + pool_t pool; + int refcount; + struct sieve_instance *svinst; + struct event *event; + + struct sieve_script *script; + + struct sieve_binary_file *file; + struct sieve_binary_header header; + struct sieve_resource_usage rusage; + + /* When the binary is loaded into memory or when it is being constructed + by the generator, extensions can be associated to the binary. The + extensions array is a sequential list of all linked extensions. The + extension_index array is a mapping ext_id -> binary_extension. This + is used to obtain the index code associated with an extension for + this particular binary. The linked_extensions list all extensions + linked to this binary object other than the preloaded language + features implemented as 'extensions'. + + All arrays refer to the same extension registration objects. Upon + loading a binary, the 'require'd extensions will sometimes need to + associate context data to the binary object in memory. This is stored + in these registration objects as well. + */ + ARRAY(struct sieve_binary_extension_reg *) extensions; + ARRAY(struct sieve_binary_extension_reg *) extension_index; + ARRAY(struct sieve_binary_extension_reg *) linked_extensions; + + /* Attributes of a loaded binary */ + const char *path; + + /* Blocks */ + ARRAY(struct sieve_binary_block *) blocks; + + bool rusage_updated:1; +}; + +void sieve_binary_update_event(struct sieve_binary *sbin, const char *new_path) + ATTR_NULL(2); + +struct sieve_binary * +sieve_binary_create(struct sieve_instance *svinst, struct sieve_script *script); + +/* Blocks management */ + +static inline struct sieve_binary_block * +sieve_binary_block_index(struct sieve_binary *sbin, unsigned int id) +{ + struct sieve_binary_block * const *sblock; + + if (id >= array_count(&sbin->blocks)) + return NULL; + + sblock = array_idx(&sbin->blocks, id); + if (*sblock == NULL) + return NULL; + return *sblock; +} + +static inline size_t +_sieve_binary_block_get_size(const struct sieve_binary_block *sblock) +{ + return buffer_get_used_size(sblock->data); +} + +struct sieve_binary_block * +sieve_binary_block_create_id(struct sieve_binary *sbin, unsigned int id); + +buffer_t *sieve_binary_block_get_buffer(struct sieve_binary_block *sblock); + +/* Extension registration */ + +static inline struct sieve_binary_extension_reg * +sieve_binary_extension_create_reg(struct sieve_binary *sbin, + const struct sieve_extension *ext) +{ + int index = array_count(&sbin->extensions); + struct sieve_binary_extension_reg *ereg; + + if (ext->id < 0) + return NULL; + + ereg = p_new(sbin->pool, struct sieve_binary_extension_reg, 1); + ereg->index = index; + ereg->extension = ext; + + array_idx_set(&sbin->extensions, (unsigned int) index, &ereg); + array_idx_set(&sbin->extension_index, (unsigned int) ext->id, &ereg); + + return ereg; +} + +static inline struct sieve_binary_extension_reg * +sieve_binary_extension_get_reg(struct sieve_binary *sbin, + const struct sieve_extension *ext, + bool create) +{ + struct sieve_binary_extension_reg *reg = NULL; + + if (ext->id >= 0 && + ext->id < (int)array_count(&sbin->extension_index)) { + struct sieve_binary_extension_reg * const *ereg = + array_idx(&sbin->extension_index, + (unsigned int)ext->id); + + reg = *ereg; + } + + /* Register if not known */ + if (reg == NULL && create) + return sieve_binary_extension_create_reg(sbin, ext); + return reg; +} + +static inline int +sieve_binary_extension_register(struct sieve_binary *sbin, + const struct sieve_extension *ext, + struct sieve_binary_extension_reg **reg_r) +{ + struct sieve_binary_extension_reg *ereg; + + if ((ereg = sieve_binary_extension_get_reg(sbin, ext, FALSE)) == NULL) { + ereg = sieve_binary_extension_create_reg(sbin, ext); + + if (ereg == NULL) + return -1; + + array_append(&sbin->linked_extensions, &ereg, 1); + } + + if (reg_r != NULL) + *reg_r = ereg; + return ereg->index; +} + +/* Load/Save */ + +bool sieve_binary_load_block(struct sieve_binary_block *); + +/* + * Resource limits + */ + +bool sieve_binary_check_resource_usage(struct sieve_binary *sbin); + +int sieve_binary_file_update_resource_usage(struct sieve_binary *sbin, + enum sieve_error *error_r) + ATTR_NULL(2); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-binary.c b/pigeonhole/src/lib-sieve/sieve-binary.c new file mode 100644 index 0000000..06cf598 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-binary.c @@ -0,0 +1,606 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" +#include "mempool.h" +#include "buffer.h" +#include "hash.h" +#include "array.h" +#include "ostream.h" +#include "eacces-error.h" +#include "safe-mkstemp.h" + +#include "sieve-error.h" +#include "sieve-extensions.h" +#include "sieve-code.h" +#include "sieve-script.h" + +#include "sieve-binary-private.h" + +/* + * Forward declarations + */ + +static inline struct sieve_binary_extension_reg * +sieve_binary_extension_get_reg(struct sieve_binary *sbin, + const struct sieve_extension *ext, bool create); + +static inline int +sieve_binary_extension_register(struct sieve_binary *sbin, + const struct sieve_extension *ext, + struct sieve_binary_extension_reg **reg); + +/* + * Binary object + */ + +void sieve_binary_update_event(struct sieve_binary *sbin, const char *new_path) +{ + if (new_path != NULL) { + event_set_append_log_prefix( + sbin->event, t_strdup_printf("binary %s: ", new_path)); + } else if (sbin->path != NULL) { + event_set_append_log_prefix( + sbin->event, + t_strdup_printf("binary %s: ", sbin->path)); + } else if (sbin->script != NULL) { + event_set_append_log_prefix( + sbin->event, + t_strdup_printf("binary %s: ", + sieve_script_name(sbin->script))); + } else { + event_set_append_log_prefix(sbin->event, "binary: "); + } +} + +struct sieve_binary * +sieve_binary_create(struct sieve_instance *svinst, struct sieve_script *script) +{ + pool_t pool; + struct sieve_binary *sbin; + const struct sieve_extension *const *ext_preloaded; + unsigned int i, ext_count; + + pool = pool_alloconly_create("sieve_binary", 16384); + sbin = p_new(pool, struct sieve_binary, 1); + sbin->pool = pool; + sbin->refcount = 1; + sbin->svinst = svinst; + + sbin->header.version_major = SIEVE_BINARY_VERSION_MAJOR; + sbin->header.version_minor = SIEVE_BINARY_VERSION_MINOR; + + sbin->script = script; + if (script != NULL) + sieve_script_ref(script); + + sbin->event = event_create(svinst->event); + + ext_count = sieve_extensions_get_count(svinst); + + p_array_init(&sbin->linked_extensions, pool, ext_count); + p_array_init(&sbin->extensions, pool, ext_count); + p_array_init(&sbin->extension_index, pool, ext_count); + + p_array_init(&sbin->blocks, pool, 16); + + /* Pre-load core language features implemented as 'extensions' */ + ext_preloaded = sieve_extensions_get_preloaded(svinst, &ext_count); + for (i = 0; i < ext_count; i++) { + const struct sieve_extension_def *ext_def = ext_preloaded[i]->def; + + if (ext_def != NULL && ext_def->binary_load != NULL) + (void)ext_def->binary_load(ext_preloaded[i], sbin); + } + + return sbin; +} + +struct sieve_binary *sieve_binary_create_new(struct sieve_script *script) +{ + struct sieve_binary *sbin = + sieve_binary_create(sieve_script_svinst(script), script); + struct sieve_binary_block *sblock; + unsigned int i; + + sieve_binary_update_event(sbin, NULL); + + /* Create script metadata block */ + sblock = sieve_binary_block_create(sbin); + sieve_script_binary_write_metadata(script, sblock); + + /* Create other system blocks */ + for (i = 1; i < SBIN_SYSBLOCK_LAST; i++) + (void)sieve_binary_block_create(sbin); + + return sbin; +} + +void sieve_binary_ref(struct sieve_binary *sbin) +{ + sbin->refcount++; +} + +static inline void sieve_binary_extensions_free(struct sieve_binary *sbin) +{ + struct sieve_binary_extension_reg *const *regs; + unsigned int ext_count, i; + + /* Cleanup binary extensions */ + regs = array_get(&sbin->extensions, &ext_count); + for (i = 0; i < ext_count; i++) { + const struct sieve_binary_extension *binext = regs[i]->binext; + + if (binext != NULL && binext->binary_free != NULL) { + binext->binary_free(regs[i]->extension, sbin, + regs[i]->context); + } + } +} + +static void sieve_binary_update_resource_usage(struct sieve_binary *sbin) +{ + enum sieve_error error; + + if (sbin->rusage_updated) + (void)sieve_binary_file_update_resource_usage(sbin, &error); + sbin->rusage_updated = FALSE; +} + +void sieve_binary_unref(struct sieve_binary **_sbin) +{ + struct sieve_binary *sbin = *_sbin; + + *_sbin = NULL; + if (sbin == NULL) + return; + + i_assert(sbin->refcount > 0); + if (--sbin->refcount != 0) + return; + + sieve_binary_file_close(&sbin->file); + sieve_binary_update_resource_usage(sbin); + sieve_binary_extensions_free(sbin); + + if (sbin->script != NULL) + sieve_script_unref(&sbin->script); + + event_unref(&sbin->event); + pool_unref(&sbin->pool); +} + +void sieve_binary_close(struct sieve_binary **_sbin) +{ + struct sieve_binary *sbin = *_sbin; + + *_sbin = NULL; + if (sbin == NULL) + return; + + sieve_binary_file_close(&sbin->file); + sieve_binary_update_resource_usage(sbin); + sieve_binary_unref(&sbin); +} + +/* + * Resource usage + */ + +void sieve_binary_get_resource_usage(struct sieve_binary *sbin, + struct sieve_resource_usage *rusage_r) +{ + struct sieve_binary_header *header = &sbin->header; + time_t update_time = header->resource_usage.update_time; + unsigned int timeout = sbin->svinst->resource_usage_timeout_secs; + + if (update_time != 0 && (ioloop_time - update_time) > timeout) + i_zero(&header->resource_usage); + + sieve_resource_usage_init(rusage_r); + rusage_r->cpu_time_msecs = header->resource_usage.cpu_time_msecs; + sieve_resource_usage_add(rusage_r, &sbin->rusage); +} + +bool sieve_binary_check_resource_usage(struct sieve_binary *sbin) +{ + struct sieve_binary_header *header = &sbin->header; + struct sieve_resource_usage rusage; + + sieve_binary_get_resource_usage(sbin, &rusage); + + if (sieve_resource_usage_is_excessive(sbin->svinst, &rusage)) { + header->flags |= SIEVE_BINARY_FLAG_RESOURCE_LIMIT; + return FALSE; + } + return TRUE; +} + +bool sieve_binary_record_resource_usage( + struct sieve_binary *sbin, const struct sieve_resource_usage *rusage) +{ + struct sieve_resource_usage rusage_total; + + if (sbin == NULL) + return TRUE; + if (!sieve_resource_usage_is_high(sbin->svinst, rusage)) + return TRUE; + + sieve_resource_usage_add(&sbin->rusage, rusage); + sbin->rusage_updated = TRUE; + + sieve_binary_get_resource_usage(sbin, &rusage_total); + + e_debug(sbin->event, "Updated cumulative resource usage: %s", + sieve_resource_usage_get_summary(&rusage_total)); + + return sieve_binary_check_resource_usage(sbin); +} + +void sieve_binary_set_resource_usage(struct sieve_binary *sbin, + const struct sieve_resource_usage *rusage) +{ + struct sieve_binary_header *header = &sbin->header; + + i_zero(&header->resource_usage); + sbin->rusage = *rusage; + sbin->rusage_updated = TRUE; + + (void)sieve_binary_check_resource_usage(sbin); +} + +/* + * Accessors + */ + +pool_t sieve_binary_pool(struct sieve_binary *sbin) +{ + return sbin->pool; +} + +struct sieve_script *sieve_binary_script(struct sieve_binary *sbin) +{ + return sbin->script; +} + +const char *sieve_binary_path(struct sieve_binary *sbin) +{ + return sbin->path; +} + +bool sieve_binary_saved(struct sieve_binary *sbin) +{ + return (sbin->path != NULL); +} + +bool sieve_binary_loaded(struct sieve_binary *sbin) +{ + return (sbin->file != NULL); +} + +const char *sieve_binary_source(struct sieve_binary *sbin) +{ + if (sbin->script != NULL && (sbin->path == NULL || sbin->file == NULL)) + return sieve_script_location(sbin->script); + + return sbin->path; +} + +struct sieve_instance *sieve_binary_svinst(struct sieve_binary *sbin) +{ + return sbin->svinst; +} + +time_t sieve_binary_mtime(struct sieve_binary *sbin) +{ + i_assert(sbin->file != NULL); + return sbin->file->st.st_mtime; +} + +const struct stat *sieve_binary_stat(struct sieve_binary *sbin) +{ + i_assert(sbin->file != NULL); + return &sbin->file->st; +} + +const char *sieve_binary_script_name(struct sieve_binary *sbin) +{ + return (sbin->script == NULL ? + NULL : sieve_script_name(sbin->script)); +} + +const char *sieve_binary_script_location(struct sieve_binary *sbin) +{ + return (sbin->script == NULL ? + NULL : sieve_script_location(sbin->script)); +} + +/* + * Utility + */ + +const char *sieve_binfile_from_name(const char *name) +{ + return t_strconcat(name, "."SIEVE_BINARY_FILEEXT, NULL); +} + +/* + * Block management + */ + +unsigned int sieve_binary_block_count(struct sieve_binary *sbin) +{ + return array_count(&sbin->blocks); +} + +struct sieve_binary_block *sieve_binary_block_create(struct sieve_binary *sbin) +{ + unsigned int id = sieve_binary_block_count(sbin); + struct sieve_binary_block *sblock; + + sblock = p_new(sbin->pool, struct sieve_binary_block, 1); + sblock->data = buffer_create_dynamic(sbin->pool, 64); + sblock->sbin = sbin; + sblock->id = id; + + array_append(&sbin->blocks, &sblock, 1); + + return sblock; +} + +struct sieve_binary_block * +sieve_binary_block_create_id(struct sieve_binary *sbin, unsigned int id) +{ + struct sieve_binary_block *sblock; + + sblock = p_new(sbin->pool, struct sieve_binary_block, 1); + + array_idx_set(&sbin->blocks, id, &sblock); + sblock->data = NULL; + sblock->sbin = sbin; + sblock->id = id; + + return sblock; +} + +static bool sieve_binary_block_fetch(struct sieve_binary_block *sblock) +{ + struct sieve_binary *sbin = sblock->sbin; + + if (sbin->file != NULL) { + /* Try to acces the block in the binary on disk (apparently we + were lazy) + */ + if (!sieve_binary_load_block(sblock) || sblock->data == NULL) + return FALSE; + } else { + sblock->data = buffer_create_dynamic(sbin->pool, 64); + return TRUE; + } + + return TRUE; +} + +struct sieve_binary_block * +sieve_binary_block_get(struct sieve_binary *sbin, unsigned int id) +{ + struct sieve_binary_block *sblock = sieve_binary_block_index(sbin, id); + + if (sblock == NULL) + return NULL; + + if (sblock->data == NULL && !sieve_binary_block_fetch(sblock)) + return NULL; + + return sblock; +} + +void sieve_binary_block_clear(struct sieve_binary_block *sblock) +{ + buffer_set_used_size(sblock->data, 0); +} + +buffer_t *sieve_binary_block_get_buffer(struct sieve_binary_block *sblock) +{ + if (sblock->data == NULL && !sieve_binary_block_fetch(sblock)) + return NULL; + + return sblock->data; +} + +struct sieve_binary * +sieve_binary_block_get_binary(const struct sieve_binary_block *sblock) +{ + return sblock->sbin; +} + +unsigned int sieve_binary_block_get_id(const struct sieve_binary_block *sblock) +{ + return sblock->id; +} + +size_t sieve_binary_block_get_size(const struct sieve_binary_block *sblock) +{ + return _sieve_binary_block_get_size(sblock); +} + +/* + * Up-to-date checking + */ + +bool sieve_binary_up_to_date(struct sieve_binary *sbin, + enum sieve_compile_flags cpflags) +{ + struct sieve_binary_extension_reg *const *regs; + struct sieve_binary_block *sblock; + sieve_size_t offset = 0; + unsigned int ext_count, i; + int ret; + + i_assert(sbin->file != NULL); + + sblock = sieve_binary_block_get(sbin, SBIN_SYSBLOCK_SCRIPT_DATA); + if (sblock == NULL || sbin->script == NULL) + return FALSE; + + if ((ret = sieve_script_binary_read_metadata(sbin->script, sblock, + &offset)) <= 0) { + if (ret < 0) { + e_debug(sbin->event, "up-to-date: " + "failed to read script metadata from binary"); + } else { + e_debug(sbin->event, "up-to-date: " + "script metadata indicates that binary is not up-to-date"); + } + return FALSE; + } + + regs = array_get(&sbin->extensions, &ext_count); + for (i = 0; i < ext_count; i++) { + const struct sieve_binary_extension *binext = regs[i]->binext; + + if (binext != NULL && binext->binary_up_to_date != NULL && + !binext->binary_up_to_date(regs[i]->extension, sbin, + regs[i]->context, cpflags)) { + e_debug(sbin->event, "up-to-date: " + "the %s extension indicates binary is not up-to-date", + sieve_extension_name(regs[i]->extension)); + return FALSE; + } + } + return TRUE; +} + +/* + * Activate the binary (after code generation) + */ + +void sieve_binary_activate(struct sieve_binary *sbin) +{ + struct sieve_binary_extension_reg *const *regs; + unsigned int i, ext_count; + + /* Load other extensions into binary */ + regs = array_get(&sbin->linked_extensions, &ext_count); + for (i = 0; i < ext_count; i++) { + const struct sieve_extension *ext = regs[i]->extension; + + if (ext != NULL && ext->def != NULL && + ext->def->binary_load != NULL) + ext->def->binary_load(ext, sbin); + } +} + +/* + * Extension handling + */ + +void sieve_binary_extension_set_context(struct sieve_binary *sbin, + const struct sieve_extension *ext, + void *context) +{ + struct sieve_binary_extension_reg *ereg = + sieve_binary_extension_get_reg(sbin, ext, TRUE); + + if (ereg != NULL) + ereg->context = context; +} + +const void * +sieve_binary_extension_get_context(struct sieve_binary *sbin, + const struct sieve_extension *ext) +{ + struct sieve_binary_extension_reg *ereg = + sieve_binary_extension_get_reg(sbin, ext, TRUE); + + if (ereg != NULL) + return ereg->context; + + return NULL; +} + +void sieve_binary_extension_set(struct sieve_binary *sbin, + const struct sieve_extension *ext, + const struct sieve_binary_extension *bext, + void *context) +{ + struct sieve_binary_extension_reg *ereg = + sieve_binary_extension_get_reg(sbin, ext, TRUE); + + if (ereg != NULL) { + ereg->binext = bext; + + if (context != NULL) + ereg->context = context; + } +} + +struct sieve_binary_block * +sieve_binary_extension_create_block(struct sieve_binary *sbin, + const struct sieve_extension *ext) +{ + struct sieve_binary_block *sblock; + struct sieve_binary_extension_reg *ereg = + sieve_binary_extension_get_reg(sbin, ext, TRUE); + + i_assert(ereg != NULL); + + sblock = sieve_binary_block_create(sbin); + + if (ereg->block_id < SBIN_SYSBLOCK_LAST) + ereg->block_id = sblock->id; + sblock->ext_index = ereg->index; + + return sblock; +} + +struct sieve_binary_block * +sieve_binary_extension_get_block(struct sieve_binary *sbin, + const struct sieve_extension *ext) +{ + struct sieve_binary_extension_reg *ereg = + sieve_binary_extension_get_reg(sbin, ext, TRUE); + + i_assert(ereg != NULL); + + if (ereg->block_id < SBIN_SYSBLOCK_LAST) + return NULL; + + return sieve_binary_block_get(sbin, ereg->block_id); +} + +int sieve_binary_extension_link(struct sieve_binary *sbin, + const struct sieve_extension *ext) +{ + return sieve_binary_extension_register(sbin, ext, NULL); +} + +const struct sieve_extension * +sieve_binary_extension_get_by_index(struct sieve_binary *sbin, int index) +{ + struct sieve_binary_extension_reg * const *ereg; + + if (index < (int)array_count(&sbin->extensions)) { + ereg = array_idx(&sbin->extensions, (unsigned int)index); + + return (*ereg)->extension; + } + + return NULL; +} + +int sieve_binary_extension_get_index(struct sieve_binary *sbin, + const struct sieve_extension *ext) +{ + struct sieve_binary_extension_reg *ereg = + sieve_binary_extension_get_reg(sbin, ext, FALSE); + + return (ereg == NULL ? -1 : ereg->index); +} + +int sieve_binary_extensions_count(struct sieve_binary *sbin) +{ + return (int)array_count(&sbin->extensions); +} diff --git a/pigeonhole/src/lib-sieve/sieve-binary.h b/pigeonhole/src/lib-sieve/sieve-binary.h new file mode 100644 index 0000000..0b8b66e --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-binary.h @@ -0,0 +1,291 @@ +#ifndef SIEVE_BINARY_H +#define SIEVE_BINARY_H + +#include "lib.h" + +#include "sieve-common.h" + +/* + * Config + */ + +#define SIEVE_BINARY_VERSION_MAJOR 2 +#define SIEVE_BINARY_VERSION_MINOR 0 + +#define SIEVE_BINARY_BASE_HEADER_SIZE 20 + +/* + * Binary object + */ + +struct sieve_binary; + +struct sieve_binary *sieve_binary_create_new(struct sieve_script *script); +void sieve_binary_ref(struct sieve_binary *sbin); +void sieve_binary_unref(struct sieve_binary **_sbin); + +void sieve_binary_close(struct sieve_binary **_sbin); + +/* + * Resource usage + */ + +void sieve_binary_get_resource_usage(struct sieve_binary *sbin, + struct sieve_resource_usage *rusage_r); +bool sieve_binary_record_resource_usage( + struct sieve_binary *sbin, const struct sieve_resource_usage *rusage) + ATTR_NULL(1); +void sieve_binary_set_resource_usage(struct sieve_binary *sbin, + const struct sieve_resource_usage *rusage); +/* + * Accessors + */ + +pool_t sieve_binary_pool(struct sieve_binary *sbin); +struct sieve_instance *sieve_binary_svinst(struct sieve_binary *sbin); +const char *sieve_binary_path(struct sieve_binary *sbin); +struct sieve_script *sieve_binary_script(struct sieve_binary *sbin); + +time_t sieve_binary_mtime(struct sieve_binary *sbin); +const struct stat *sieve_binary_stat(struct sieve_binary *sbin); + +const char *sieve_binary_script_name(struct sieve_binary *sbin); +const char *sieve_binary_script_location(struct sieve_binary *sbin); + +const char *sieve_binary_source(struct sieve_binary *sbin); +bool sieve_binary_loaded(struct sieve_binary *sbin); +bool sieve_binary_saved(struct sieve_binary *sbin); + +/* + * Utility + */ + +const char *sieve_binfile_from_name(const char *name); + +/* + * Activation after code generation + */ + +void sieve_binary_activate(struct sieve_binary *sbin); + +/* + * Saving the binary + */ + +int sieve_binary_save(struct sieve_binary *sbin, const char *path, bool update, + mode_t save_mode, enum sieve_error *error_r); + +/* + * Loading the binary + */ + +struct sieve_binary * +sieve_binary_open(struct sieve_instance *svinst, const char *path, + struct sieve_script *script, enum sieve_error *error_r); +bool sieve_binary_up_to_date(struct sieve_binary *sbin, + enum sieve_compile_flags cpflags); + +int sieve_binary_check_executable(struct sieve_binary *sbin, + enum sieve_error *error_r, + const char **client_error_r); + +/* + * Block management + */ + +enum sieve_binary_system_block { + SBIN_SYSBLOCK_SCRIPT_DATA, + SBIN_SYSBLOCK_EXTENSIONS, + SBIN_SYSBLOCK_MAIN_PROGRAM, + SBIN_SYSBLOCK_LAST +}; + +struct sieve_binary_block *sieve_binary_block_create(struct sieve_binary *sbin); + +unsigned int sieve_binary_block_count(struct sieve_binary *sbin); + +struct sieve_binary_block * +sieve_binary_block_get(struct sieve_binary *sbin, unsigned int id); + +void sieve_binary_block_clear(struct sieve_binary_block *sblock); + +size_t sieve_binary_block_get_size(const struct sieve_binary_block *sblock); + +struct sieve_binary * +sieve_binary_block_get_binary(const struct sieve_binary_block *sblock); + +unsigned int sieve_binary_block_get_id(const struct sieve_binary_block *sblock); + +/* + * Extension support + */ + +struct sieve_binary_extension { + const struct sieve_extension_def *extension; + + bool (*binary_pre_save)(const struct sieve_extension *ext, + struct sieve_binary *sbin, void *context, + enum sieve_error *error_r); + bool (*binary_post_save)(const struct sieve_extension *ext, + struct sieve_binary *sbin, void *context, + enum sieve_error *error_r); + bool (*binary_open)(const struct sieve_extension *ext, + struct sieve_binary *sbin, void *context); + + void (*binary_free)(const struct sieve_extension *ext, + struct sieve_binary *sbin, void *context); + + bool (*binary_up_to_date)(const struct sieve_extension *ext, + struct sieve_binary *sbin, void *context, + enum sieve_compile_flags cpflags); +}; + +void sieve_binary_extension_set_context(struct sieve_binary *sbin, + const struct sieve_extension *ext, + void *context); +const void * +sieve_binary_extension_get_context(struct sieve_binary *sbin, + const struct sieve_extension *ext); + +void sieve_binary_extension_set(struct sieve_binary *sbin, + const struct sieve_extension *ext, + const struct sieve_binary_extension *bext, + void *context); + +struct sieve_binary_block * +sieve_binary_extension_create_block(struct sieve_binary *sbin, + const struct sieve_extension *ext); +struct sieve_binary_block * +sieve_binary_extension_get_block(struct sieve_binary *sbin, + const struct sieve_extension *ext); + +int sieve_binary_extension_link(struct sieve_binary *sbin, + const struct sieve_extension *ext); +const struct sieve_extension * +sieve_binary_extension_get_by_index(struct sieve_binary *sbin, int index); +int sieve_binary_extension_get_index(struct sieve_binary *sbin, + const struct sieve_extension *ext); +int sieve_binary_extensions_count(struct sieve_binary *sbin); + +/* + * Code emission + */ + +/* Low-level emission functions */ + +sieve_size_t sieve_binary_emit_data(struct sieve_binary_block *sblock, + const void *data, sieve_size_t size); +sieve_size_t sieve_binary_emit_byte(struct sieve_binary_block *sblock, + uint8_t byte); +void sieve_binary_update_data(struct sieve_binary_block *sblock, + sieve_size_t address, const void *data, + sieve_size_t size); + +/* Offset emission functions */ + +sieve_size_t sieve_binary_emit_offset(struct sieve_binary_block *sblock, + sieve_offset_t offset); +void sieve_binary_resolve_offset(struct sieve_binary_block *sblock, + sieve_size_t address); + +/* Literal emission functions */ + +sieve_size_t sieve_binary_emit_integer(struct sieve_binary_block *sblock, + sieve_number_t integer); +sieve_size_t sieve_binary_emit_string(struct sieve_binary_block *sblock, + const string_t *str); +sieve_size_t sieve_binary_emit_cstring(struct sieve_binary_block *sblock, + const char *str); + +static inline sieve_size_t +sieve_binary_emit_unsigned(struct sieve_binary_block *sblock, + unsigned int count) +{ + return sieve_binary_emit_integer(sblock, count); +} + +/* Extension emission functions */ + +sieve_size_t sieve_binary_emit_extension(struct sieve_binary_block *sblock, + const struct sieve_extension *ext, + unsigned int offset); +void sieve_binary_emit_extension_object( + struct sieve_binary_block *sblock, + const struct sieve_extension_objects *objs, unsigned int code); + +/* + * Code retrieval + */ + +/* Literals */ + +bool sieve_binary_read_byte(struct sieve_binary_block *sblock, + sieve_size_t *address, unsigned int *byte_r) + ATTR_NULL(3); +bool sieve_binary_read_code(struct sieve_binary_block *sblock, + sieve_size_t *address, signed int *code_r) + ATTR_NULL(3); +bool sieve_binary_read_offset(struct sieve_binary_block *sblock, + sieve_size_t *address, sieve_offset_t *offset_r) + ATTR_NULL(3); +bool sieve_binary_read_integer(struct sieve_binary_block *sblock, + sieve_size_t *address, sieve_number_t *int_r) + ATTR_NULL(3); +bool sieve_binary_read_string(struct sieve_binary_block *sblock, + sieve_size_t *address, string_t **str_r) + ATTR_NULL(3); + +static inline bool ATTR_NULL(3) +sieve_binary_read_unsigned(struct sieve_binary_block *sblock, + sieve_size_t *address, unsigned int *count_r) +{ + sieve_number_t integer = 0; + + if (!sieve_binary_read_integer(sblock, address, &integer)) + return FALSE; + if (count_r != NULL) + *count_r = integer; + return TRUE; +} + +/* Extensions */ + +bool sieve_binary_read_extension(struct sieve_binary_block *sblock, + sieve_size_t *address, unsigned int *offset_r, + const struct sieve_extension **ext_r); +const void * +sieve_binary_read_extension_object(struct sieve_binary_block *sblock, + sieve_size_t *address, + const struct sieve_extension_objects *objs); + +/* + * Debug info + */ + +/* Writer */ + +struct sieve_binary_debug_writer; + +struct sieve_binary_debug_writer * +sieve_binary_debug_writer_init(struct sieve_binary_block *sblock); +void sieve_binary_debug_writer_deinit( + struct sieve_binary_debug_writer **dwriter); + +void sieve_binary_debug_emit(struct sieve_binary_debug_writer *dwriter, + sieve_size_t code_address, unsigned int code_line, + unsigned int code_column); + +/* Reader */ + +struct sieve_binary_debug_reader * +sieve_binary_debug_reader_init(struct sieve_binary_block *sblock); +void sieve_binary_debug_reader_deinit( + struct sieve_binary_debug_reader **dreader); + +void sieve_binary_debug_reader_reset(struct sieve_binary_debug_reader *dreader); + +unsigned int +sieve_binary_debug_read_line(struct sieve_binary_debug_reader *dreader, + sieve_size_t code_address); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-code-dumper.c b/pigeonhole/src/lib-sieve/sieve-code-dumper.c new file mode 100644 index 0000000..17e2768 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-code-dumper.c @@ -0,0 +1,351 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include <stdio.h> +#include <string.h> + +#include "lib.h" +#include "str.h" +#include "mempool.h" +#include "ostream.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-actions.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-result.h" +#include "sieve-comparators.h" + +#include "sieve-dump.h" + +/* + * Code dumper extension + */ + +struct sieve_code_dumper_extension_reg { + const struct sieve_code_dumper_extension *cdmpext; + const struct sieve_extension *ext; + void *context; +}; + +struct sieve_code_dumper { + pool_t pool; + + /* Dump status */ + struct sieve_operation oprtn; + sieve_size_t mark_address; + unsigned int mark_line; + unsigned int mark_last_line; + unsigned int indent; + + /* Dump environment */ + struct sieve_dumptime_env *dumpenv; + + struct sieve_binary_debug_reader *dreader; + + ARRAY(struct sieve_code_dumper_extension_reg) extensions; +}; + +struct sieve_code_dumper *sieve_code_dumper_create +(struct sieve_dumptime_env *denv) +{ + pool_t pool; + struct sieve_code_dumper *cdumper; + + pool = pool_alloconly_create("sieve_code_dumper", 4096); + cdumper = p_new(pool, struct sieve_code_dumper, 1); + cdumper->pool = pool; + cdumper->dumpenv = denv; + + /* Setup storage for extension contexts */ + p_array_init(&cdumper->extensions, pool, + sieve_extensions_get_count(denv->svinst)); + + return cdumper; +} + +void sieve_code_dumper_free(struct sieve_code_dumper **_cdumper) +{ + struct sieve_code_dumper *cdumper = *_cdumper; + const struct sieve_code_dumper_extension_reg *eregs; + unsigned int count, i; + + sieve_binary_debug_reader_deinit(&cdumper->dreader); + + /* Signal registered extensions that the dumper is being destroyed */ + eregs = array_get(&cdumper->extensions, &count); + for ( i = 0; i < count; i++ ) { + if ( eregs[i].cdmpext != NULL && eregs[i].cdmpext->free != NULL ) + eregs[i].cdmpext->free(cdumper, eregs[i].context); + } + + pool_unref(&cdumper->pool); + *_cdumper = NULL; +} + +pool_t sieve_code_dumper_pool(struct sieve_code_dumper *cdumper) +{ + return cdumper->pool; +} + +/* EXtension support */ + +void sieve_dump_extension_register +(struct sieve_code_dumper *cdumper, const struct sieve_extension *ext, + const struct sieve_code_dumper_extension *cdmpext, void *context) +{ + struct sieve_code_dumper_extension_reg *reg; + + if ( ext->id < 0 ) return; + + reg = array_idx_get_space(&cdumper->extensions, (unsigned int) ext->id); + reg->cdmpext = cdmpext; + reg->ext = ext; + reg->context = context; +} + +void sieve_dump_extension_set_context +(struct sieve_code_dumper *cdumper, const struct sieve_extension *ext, + void *context) +{ + struct sieve_code_dumper_extension_reg *reg; + + if ( ext->id < 0 ) return; + + reg = array_idx_get_space(&cdumper->extensions, (unsigned int) ext->id); + reg->context = context; +} + +void *sieve_dump_extension_get_context +(struct sieve_code_dumper *cdumper, const struct sieve_extension *ext) +{ + const struct sieve_code_dumper_extension_reg *reg; + + if ( ext->id < 0 || ext->id >= (int) array_count(&cdumper->extensions) ) + return NULL; + + reg = array_idx(&cdumper->extensions, (unsigned int) ext->id); + + return reg->context; +} + +/* Dump functions */ + +void sieve_code_dumpf +(const struct sieve_dumptime_env *denv, const char *fmt, ...) +{ + struct sieve_code_dumper *cdumper = denv->cdumper; + unsigned tab = cdumper->indent; + + string_t *outbuf = t_str_new(128); + va_list args; + + va_start(args, fmt); + str_printfa(outbuf, "%08llx: ", (unsigned long long) cdumper->mark_address); + + if ( cdumper->mark_line > 0 && (cdumper->indent == 0 || + cdumper->mark_line != cdumper->mark_last_line) ) { + str_printfa(outbuf, "%4u: ", cdumper->mark_line); + cdumper->mark_last_line = cdumper->mark_line; + } else { + str_append(outbuf, " "); + } + + while ( tab > 0 ) { + str_append(outbuf, " "); + tab--; + } + + str_vprintfa(outbuf, fmt, args); + str_append_c(outbuf, '\n'); + va_end(args); + + o_stream_nsend(denv->stream, str_data(outbuf), str_len(outbuf)); +} + +static inline void sieve_code_line_mark +(const struct sieve_dumptime_env *denv, sieve_size_t location) +{ + if ( denv->cdumper->dreader != NULL ) { + denv->cdumper->mark_line = sieve_binary_debug_read_line + (denv->cdumper->dreader, location); + } +} + +void sieve_code_mark(const struct sieve_dumptime_env *denv) +{ + denv->cdumper->mark_address = denv->offset; + sieve_code_line_mark(denv, denv->offset); +} + +void sieve_code_mark_specific +(const struct sieve_dumptime_env *denv, sieve_size_t location) +{ + denv->cdumper->mark_address = location; + sieve_code_line_mark(denv, location); +} + +void sieve_code_descend(const struct sieve_dumptime_env *denv) +{ + denv->cdumper->indent++; +} + +void sieve_code_ascend(const struct sieve_dumptime_env *denv) +{ + if ( denv->cdumper->indent > 0 ) + denv->cdumper->indent--; +} + +/* Code Dump */ + +static bool sieve_code_dumper_print_operation +(struct sieve_code_dumper *cdumper) +{ + struct sieve_dumptime_env *denv = cdumper->dumpenv; + struct sieve_operation *oprtn = &(cdumper->oprtn); + sieve_size_t *address = &(denv->offset); + + /* Mark start address of operation */ + cdumper->indent = 0; + cdumper->mark_address = *address; + + sieve_code_line_mark(denv, *address); + + /* Read operation */ + if ( sieve_operation_read(denv->sblock, address, oprtn) ) { + const struct sieve_operation_def *opdef = oprtn->def; + + if ( opdef->dump != NULL ) + return opdef->dump(denv, address); + else if ( opdef->mnemonic != NULL ) + sieve_code_dumpf(denv, "%s", opdef->mnemonic); + else + return FALSE; + + return TRUE; + } + + sieve_code_dumpf(denv, "Failed to read opcode."); + return FALSE; +} + +static bool sieve_code_dumper_print_extension +(struct sieve_code_dumper *cdumper) +{ + struct sieve_dumptime_env *denv = cdumper->dumpenv; + sieve_size_t *address = &(denv->offset); + struct sieve_binary_block *sblock = denv->sblock; + unsigned int code = 0, deferred; + const struct sieve_extension *ext; + + sieve_code_mark(denv); + + if ( !sieve_binary_read_extension + (sblock, address, &code, &ext) || + !sieve_binary_read_byte + (sblock, address, &deferred) ) { + return FALSE; + } + + if ( ext->def == NULL) { + sieve_code_dumpf(denv, "[undefined]"); + + } else { + sieve_code_dumpf(denv, "%s%s", + sieve_extension_name(ext), + (deferred > 0 ? " (deferred)" : "")); + + if (ext->def->code_dump != NULL ) { + sieve_code_descend(denv); + if ( !ext->def->code_dump(ext, denv, address) ) + return FALSE; + sieve_code_ascend(denv); + } + } + return TRUE; +} + +void sieve_code_dumper_run(struct sieve_code_dumper *cdumper) +{ + struct sieve_dumptime_env *denv = cdumper->dumpenv; + struct sieve_binary *sbin = denv->sbin; + struct sieve_binary_block *sblock = denv->sblock; + unsigned int debug_block_id, ext_count; + bool success; + sieve_size_t *address; + + denv->offset = 0; + denv->oprtn = &(cdumper->oprtn); + address = &(denv->offset); + + /* Heading */ + o_stream_nsend_str(denv->stream, "Address Line Code\n"); + + /* Load debug block */ + sieve_code_mark(denv); + + if ( sieve_binary_read_unsigned(sblock, address, &debug_block_id) ) { + struct sieve_binary_block *debug_block = + sieve_binary_block_get(sbin, debug_block_id); + + if ( debug_block == NULL ) { + sieve_code_dumpf(denv, "Invalid id %d for debug block.", debug_block_id); + return; + } else { + /* Initialize debug reader */ + cdumper->dreader = sieve_binary_debug_reader_init(debug_block); + + /* Dump block id */ + sieve_code_dumpf(denv, "DEBUG BLOCK: %d", debug_block_id); + } + } else { + sieve_code_dumpf(denv, "Binary code header is corrupt."); + return; + } + + /* Load and dump extensions listed in code */ + sieve_code_mark(denv); + + success = TRUE; + if ( sieve_binary_read_unsigned(sblock, address, &ext_count) ) { + unsigned int i; + + sieve_code_dumpf(denv, "EXTENSIONS [%d]:", ext_count); + sieve_code_descend(denv); + + for ( i = 0; success && (i < ext_count); i++ ) { + T_BEGIN { + success = success && + sieve_code_dumper_print_extension(cdumper); + } T_END; + } + + sieve_code_ascend(denv); + } else + success = FALSE; + + if ( !success ) { + sieve_code_dumpf(denv, "Binary code header is corrupt."); + return; + } + + while ( *address < sieve_binary_block_get_size(sblock) ) { + + T_BEGIN { + success = sieve_code_dumper_print_operation(cdumper); + } T_END; + + if ( !success ) { + sieve_code_dumpf(denv, "Binary is corrupt."); + return; + } + } + + /* Mark end of the binary */ + cdumper->indent = 0; + cdumper->mark_address = sieve_binary_block_get_size(sblock); + sieve_code_dumpf(denv, "[End of code]"); +} diff --git a/pigeonhole/src/lib-sieve/sieve-code-dumper.h b/pigeonhole/src/lib-sieve/sieve-code-dumper.h new file mode 100644 index 0000000..651bd11 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-code-dumper.h @@ -0,0 +1,55 @@ +#ifndef SIEVE_CODE_DUMPER_H +#define SIEVE_CODE_DUMPER_H + +#include "sieve-common.h" + +struct sieve_code_dumper; + +struct sieve_code_dumper *sieve_code_dumper_create + (struct sieve_dumptime_env *denv); +void sieve_code_dumper_free + (struct sieve_code_dumper **_dumper); +pool_t sieve_code_dumper_pool + (struct sieve_code_dumper *dumper); + +/* + * Extension support + */ + +struct sieve_code_dumper_extension { + const struct sieve_extension_def *ext; + + void (*free)(struct sieve_code_dumper *dumper, void *context); +}; + +void sieve_dump_extension_register +(struct sieve_code_dumper *dumper, const struct sieve_extension *ext, + const struct sieve_code_dumper_extension *dump_ext, void *context); +void sieve_dump_extension_set_context + (struct sieve_code_dumper *dumper, const struct sieve_extension *ext, + void *context); +void *sieve_dump_extension_get_context + (struct sieve_code_dumper *dumper, const struct sieve_extension *ext); + +/* Dump functions */ + +void sieve_code_dumpf + (const struct sieve_dumptime_env *denv, const char *fmt, ...) + ATTR_FORMAT(2, 3); + +void sieve_code_mark(const struct sieve_dumptime_env *denv); +void sieve_code_mark_specific + (const struct sieve_dumptime_env *denv, sieve_size_t location); +void sieve_code_descend(const struct sieve_dumptime_env *denv); +void sieve_code_ascend(const struct sieve_dumptime_env *denv); + +/* Operations and operands */ + +bool sieve_code_dumper_print_optional_operands + (const struct sieve_dumptime_env *denv, sieve_size_t *address); + +/* Code dump (debugging purposes) */ + +void sieve_code_dumper_run(struct sieve_code_dumper *dumper); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-code.c b/pigeonhole/src/lib-sieve/sieve-code.c new file mode 100644 index 0000000..82bd7f1 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-code.c @@ -0,0 +1,1169 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-limits.h" +#include "sieve-extensions.h" +#include "sieve-stringlist.h" +#include "sieve-actions.h" +#include "sieve-binary.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "sieve-code.h" + +#include <stdio.h> + +/* + * Code stringlist + */ + +/* Forward declarations */ + +static int sieve_code_stringlist_next_item + (struct sieve_stringlist *_strlist, string_t **str_r); +static void sieve_code_stringlist_reset + (struct sieve_stringlist *_strlist); +static int sieve_code_stringlist_get_length + (struct sieve_stringlist *_strlist); + +/* Coded stringlist object */ + +struct sieve_code_stringlist { + struct sieve_stringlist strlist; + + sieve_size_t start_address; + sieve_size_t end_address; + sieve_size_t current_offset; + int length; + int index; +}; + +static struct sieve_stringlist *sieve_code_stringlist_create +(const struct sieve_runtime_env *renv, + sieve_size_t start_address, unsigned int length, sieve_size_t end) +{ + struct sieve_code_stringlist *strlist; + + if ( end > sieve_binary_block_get_size(renv->sblock) ) + return NULL; + + strlist = t_new(struct sieve_code_stringlist, 1); + strlist->strlist.runenv = renv; + strlist->strlist.exec_status = SIEVE_EXEC_OK; + strlist->strlist.next_item = sieve_code_stringlist_next_item; + strlist->strlist.reset = sieve_code_stringlist_reset; + strlist->strlist.get_length = sieve_code_stringlist_get_length; + strlist->start_address = start_address; + strlist->current_offset = start_address; + strlist->end_address = end; + strlist->length = length; + strlist->index = 0; + + return &strlist->strlist; +} + +/* Stringlist implementation */ + +static int sieve_code_stringlist_next_item +(struct sieve_stringlist *_strlist, string_t **str_r) +{ + struct sieve_code_stringlist *strlist = + (struct sieve_code_stringlist *) _strlist; + sieve_size_t address; + *str_r = NULL; + int ret; + + /* Check for end of list */ + if ( strlist->index >= strlist->length ) + return 0; + + /* Read next item */ + address = strlist->current_offset; + if ( (ret=sieve_opr_string_read(_strlist->runenv, &address, NULL, str_r)) + == SIEVE_EXEC_OK ) { + strlist->index++; + strlist->current_offset = address; + return 1; + } + + _strlist->exec_status = ret; + return -1; +} + +static void sieve_code_stringlist_reset +(struct sieve_stringlist *_strlist) +{ + struct sieve_code_stringlist *strlist = + (struct sieve_code_stringlist *) _strlist; + + strlist->current_offset = strlist->start_address; + strlist->index = 0; +} + +static int sieve_code_stringlist_get_length +(struct sieve_stringlist *_strlist) +{ + struct sieve_code_stringlist *strlist = + (struct sieve_code_stringlist *) _strlist; + + return strlist->length; +} + +static bool sieve_code_stringlist_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address, + unsigned int length, sieve_size_t end, const char *field_name) +{ + unsigned int i; + + if ( end > sieve_binary_block_get_size(denv->sblock) ) + return FALSE; + + if ( field_name != NULL ) + sieve_code_dumpf(denv, "%s: STRLIST [%u] (end: %08llx)", + field_name, length, (unsigned long long) end); + else + sieve_code_dumpf(denv, "STRLIST [%u] (end: %08llx)", + length, (unsigned long long) end); + + sieve_code_descend(denv); + + for ( i = 0; i < length; i++ ) { + bool success = TRUE; + + T_BEGIN { + success = sieve_opr_string_dump(denv, address, NULL); + } T_END; + + if ( !success || *address > end ) + return FALSE; + } + + if ( *address != end ) return FALSE; + + sieve_code_ascend(denv); + + return TRUE; +} + +/* + * Core operands + */ + +extern const struct sieve_operand_def comparator_operand; +extern const struct sieve_operand_def match_type_operand; +extern const struct sieve_operand_def address_part_operand; + +const struct sieve_operand_def *sieve_operands[] = { + &omitted_operand, /* SIEVE_OPERAND_OPTIONAL */ + &number_operand, + &string_operand, + &stringlist_operand, + &comparator_operand, + &match_type_operand, + &address_part_operand, + &catenated_string_operand +}; + +const unsigned int sieve_operand_count = + N_ELEMENTS(sieve_operands); + +/* + * Operand functions + */ + +sieve_size_t sieve_operand_emit +(struct sieve_binary_block *sblock, const struct sieve_extension *ext, + const struct sieve_operand_def *opr_def) +{ + sieve_size_t address; + + if ( ext != NULL ) { + address = sieve_binary_emit_extension + (sblock, ext, sieve_operand_count); + + sieve_binary_emit_extension_object + (sblock, &opr_def->ext_def->operands, opr_def->code); + + return address; + } + + return sieve_binary_emit_byte(sblock, opr_def->code); +} + +bool sieve_operand_read +(struct sieve_binary_block *sblock, sieve_size_t *address, + const char *field_name, struct sieve_operand *operand) +{ + unsigned int code = sieve_operand_count; + + operand->address = *address; + operand->field_name = field_name; + operand->ext = NULL; + operand->def = NULL; + + if ( !sieve_binary_read_extension(sblock, address, &code, &operand->ext) ) + return FALSE; + + if ( operand->ext == NULL ) { + if ( code < sieve_operand_count ) + operand->def = sieve_operands[code]; + + return ( operand->def != NULL ); + } + + if ( operand->ext->def == NULL ) + return FALSE; + + operand->def = (const struct sieve_operand_def *) + sieve_binary_read_extension_object(sblock, address, + &operand->ext->def->operands); + + return ( operand->def != NULL ); +} + +/* + * Optional operand + */ + +int sieve_opr_optional_next +(struct sieve_binary_block *sblock, sieve_size_t *address, signed int *opt_code) +{ + /* Start of optional operand block */ + if ( *opt_code == 0 ) { + sieve_size_t tmp_addr = *address; + unsigned int op; + + if ( !sieve_binary_read_byte(sblock, &tmp_addr, &op) || + op != SIEVE_OPERAND_OPTIONAL ) + return 0; + + *address = tmp_addr; + } + + /* Read optional operand code */ + if ( !sieve_binary_read_code(sblock, address, opt_code) ) + return -1; + + /* Return 0 at end of list */ + return ( *opt_code != 0 ? 1 : 0 ); +} + +/* + * Operand definitions + */ + +/* Omitted */ + +const struct sieve_operand_class omitted_class = + { "OMITTED" }; + +const struct sieve_operand_def omitted_operand = { + .name = "@OMITTED", + .code = SIEVE_OPERAND_OPTIONAL, + .class = &omitted_class +}; + +/* Number */ + +static bool opr_number_dump + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); +static int opr_number_read + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, sieve_number_t *number_r); + +const struct sieve_opr_number_interface number_interface = { + opr_number_dump, + opr_number_read +}; + +const struct sieve_operand_class number_class = + { "number" }; + +const struct sieve_operand_def number_operand = { + .name = "@number", + .code = SIEVE_OPERAND_NUMBER, + .class = &number_class, + .interface = &number_interface +}; + +/* String */ + +static bool opr_string_dump + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); +static int opr_string_read + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r); + +const struct sieve_opr_string_interface string_interface ={ + opr_string_dump, + opr_string_read +}; + +const struct sieve_operand_class string_class = + { "string" }; + +const struct sieve_operand_def string_operand = { + .name = "@string", + .code = SIEVE_OPERAND_STRING, + .class = &string_class, + .interface = &string_interface +}; + +/* String List */ + +static bool opr_stringlist_dump + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); +static int opr_stringlist_read + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, struct sieve_stringlist **strlist_r); + +const struct sieve_opr_stringlist_interface stringlist_interface = { + opr_stringlist_dump, + opr_stringlist_read +}; + +const struct sieve_operand_class stringlist_class = + { "string-list" }; + +const struct sieve_operand_def stringlist_operand = { + .name = "@string-list", + .code = SIEVE_OPERAND_STRING_LIST, + .class = &stringlist_class, + .interface = &stringlist_interface +}; + +/* Catenated String */ + +static bool opr_catenated_string_dump + (const struct sieve_dumptime_env *denv, const struct sieve_operand *operand, + sieve_size_t *address); +static int opr_catenated_string_read + (const struct sieve_runtime_env *renv, const struct sieve_operand *operand, + sieve_size_t *address, string_t **str); + +const struct sieve_opr_string_interface catenated_string_interface = { + opr_catenated_string_dump, + opr_catenated_string_read +}; + +const struct sieve_operand_def catenated_string_operand = { + .name = "@catenated-string", + .code = SIEVE_OPERAND_CATENATED_STRING, + .class = &string_class, + .interface = &catenated_string_interface +}; + +/* + * Operand implementations + */ + +/* Omitted */ + +void sieve_opr_omitted_emit(struct sieve_binary_block *sblock) +{ + (void) sieve_operand_emit(sblock, NULL, &omitted_operand); +} + +/* Number */ + +void sieve_opr_number_emit +(struct sieve_binary_block *sblock, sieve_number_t number) +{ + (void) sieve_operand_emit(sblock, NULL, &number_operand); + (void) sieve_binary_emit_integer(sblock, number); +} + +bool sieve_opr_number_dump_data +(const struct sieve_dumptime_env *denv, struct sieve_operand *oprnd, + sieve_size_t *address, const char *field_name) +{ + const struct sieve_opr_number_interface *intf; + + oprnd->field_name = field_name; + + if ( !sieve_operand_is_number(oprnd) ) + return FALSE; + + intf = (const struct sieve_opr_number_interface *) oprnd->def->interface; + + if ( intf->dump == NULL ) + return FALSE; + + return intf->dump(denv, oprnd, address); +} + +bool sieve_opr_number_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address, + const char *field_name) +{ + struct sieve_operand operand; + + sieve_code_mark(denv); + + if ( !sieve_operand_read(denv->sblock, address, field_name, &operand) ) + return FALSE; + + return sieve_opr_number_dump_data(denv, &operand, address, field_name); +} + +int sieve_opr_number_read_data +(const struct sieve_runtime_env *renv, struct sieve_operand *oprnd, + sieve_size_t *address, const char *field_name, sieve_number_t *number_r) +{ + const struct sieve_opr_number_interface *intf; + + oprnd->field_name = field_name; + + if ( !sieve_operand_is_number(oprnd) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "expected number operand but found %s", sieve_operand_name(oprnd)); + return SIEVE_EXEC_BIN_CORRUPT; + } + + intf = (const struct sieve_opr_number_interface *) oprnd->def->interface; + + if ( intf->read == NULL ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "number operand not implemented"); + return SIEVE_EXEC_FAILURE; + } + + return intf->read(renv, oprnd, address, number_r); +} + +int sieve_opr_number_read +(const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, sieve_number_t *number_r) +{ + struct sieve_operand operand; + int ret; + + if ( (ret=sieve_operand_runtime_read(renv, address, field_name, &operand)) + <= 0) + return ret; + + return sieve_opr_number_read_data + (renv, &operand, address, field_name, number_r); +} + +static bool opr_number_dump +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) +{ + sieve_number_t number = 0; + + if (sieve_binary_read_integer(denv->sblock, address, &number) ) { + if ( oprnd->field_name != NULL ) + sieve_code_dumpf(denv, "%s: NUM %llu", oprnd->field_name, + (unsigned long long) number); + else + sieve_code_dumpf(denv, "NUM %llu", (unsigned long long) number); + + return TRUE; + } + + return FALSE; +} + +static int opr_number_read +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, sieve_number_t *number_r) +{ + if ( !sieve_binary_read_integer(renv->sblock, address, number_r) ) { + sieve_runtime_trace_operand_error(renv, oprnd, "invalid number operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + return SIEVE_EXEC_OK; +} + +/* String */ + +void sieve_opr_string_emit(struct sieve_binary_block *sblock, string_t *str) +{ + (void) sieve_operand_emit(sblock, NULL, &string_operand); + (void) sieve_binary_emit_string(sblock, str); +} + +bool sieve_opr_string_dump_data +(const struct sieve_dumptime_env *denv, struct sieve_operand *oprnd, + sieve_size_t *address, const char *field_name) +{ + const struct sieve_opr_string_interface *intf; + + oprnd->field_name = field_name; + + if ( !sieve_operand_is_string(oprnd) ) { + sieve_code_dumpf(denv, "ERROR: INVALID STRING OPERAND %s", + sieve_operand_name(oprnd)); + return FALSE; + } + + intf = (const struct sieve_opr_string_interface *) oprnd->def->interface; + + if ( intf->dump == NULL ) { + sieve_code_dumpf(denv, "ERROR: DUMP STRING OPERAND"); + return FALSE; + } + + return intf->dump(denv, oprnd, address); +} + +bool sieve_opr_string_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address, + const char *field_name) +{ + struct sieve_operand operand; + + sieve_code_mark(denv); + + if ( !sieve_operand_read(denv->sblock, address, field_name, &operand) ) { + sieve_code_dumpf(denv, "ERROR: INVALID OPERAND"); + return FALSE; + } + + return sieve_opr_string_dump_data(denv, &operand, address, field_name); +} + +bool sieve_opr_string_dump_ex +(const struct sieve_dumptime_env *denv, sieve_size_t *address, + const char *field_name, const char *omitted_value) +{ + struct sieve_operand operand; + + sieve_code_mark(denv); + if ( !sieve_operand_read(denv->sblock, address, field_name, &operand) ) { + sieve_code_dumpf(denv, "ERROR: INVALID OPERAND"); + return FALSE; + } + + if ( omitted_value != NULL && sieve_operand_is_omitted(&operand) ) { + if ( *omitted_value != '\0' ) + sieve_code_dumpf(denv, "%s: %s", field_name, omitted_value); + return TRUE; + } + + return sieve_opr_string_dump_data(denv, &operand, address, field_name); +} + +int sieve_opr_string_read_data +(const struct sieve_runtime_env *renv, struct sieve_operand *oprnd, + sieve_size_t *address, const char *field_name, string_t **str_r) +{ + const struct sieve_opr_string_interface *intf; + + oprnd->field_name = field_name; + + if ( !sieve_operand_is_string(oprnd) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "expected string operand but found %s", sieve_operand_name(oprnd)); + return SIEVE_EXEC_BIN_CORRUPT; + } + + intf = (const struct sieve_opr_string_interface *) oprnd->def->interface; + + if ( intf->read == NULL ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "string operand not implemented"); + return SIEVE_EXEC_FAILURE; + } + + return intf->read(renv, oprnd, address, str_r); +} + +int sieve_opr_string_read +(const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, string_t **str_r) +{ + struct sieve_operand operand; + int ret; + + if ( (ret=sieve_operand_runtime_read(renv, address, field_name, &operand)) + <= 0 ) + return ret; + + return sieve_opr_string_read_data(renv, &operand, address, field_name, str_r); +} + +int sieve_opr_string_read_ex +(const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, bool optional, string_t **str_r, bool *literal_r) +{ + struct sieve_operand operand; + int ret; + + if ( (ret=sieve_operand_runtime_read(renv, address, field_name, &operand)) + <= 0 ) + return ret; + + if ( optional && sieve_operand_is_omitted(&operand) ) { + *str_r = NULL; + return 1; + } + + if ( literal_r != NULL ) + *literal_r = sieve_operand_is_string_literal(&operand); + + return sieve_opr_string_read_data(renv, &operand, address, field_name, str_r); +} + +static void _dump_string +(const struct sieve_dumptime_env *denv, string_t *str, + const char *field_name) +{ + if ( str_len(str) > 80 ) { + if ( field_name != NULL ) + sieve_code_dumpf(denv, "%s: STR[%ld] \"%s", + field_name, (long) str_len(str), str_sanitize(str_c(str), 80)); + else + sieve_code_dumpf(denv, "STR[%ld] \"%s", + (long) str_len(str), str_sanitize(str_c(str), 80)); + } else { + if ( field_name != NULL ) + sieve_code_dumpf(denv, "%s: STR[%ld] \"%s\"", + field_name, (long) str_len(str), str_sanitize(str_c(str), 80)); + else + sieve_code_dumpf(denv, "STR[%ld] \"%s\"", + (long) str_len(str), str_sanitize(str_c(str), 80)); + } +} + +bool opr_string_dump +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) +{ + string_t *str; + + if ( sieve_binary_read_string(denv->sblock, address, &str) ) { + _dump_string(denv, str, oprnd->field_name); + + return TRUE; + } + + return FALSE; +} + +static int opr_string_read +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r) +{ + if ( !sieve_binary_read_string(renv->sblock, address, str_r) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "invalid string operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + return SIEVE_EXEC_OK; +} + +/* String list */ + +void sieve_opr_stringlist_emit_start +(struct sieve_binary_block *sblock, unsigned int listlen, void **context) +{ + sieve_size_t *end_offset = t_new(sieve_size_t, 1); + + /* Emit byte identifying the type of operand */ + (void) sieve_operand_emit(sblock, NULL, &stringlist_operand); + + /* Give the interpreter an easy way to skip over this string list */ + *end_offset = sieve_binary_emit_offset(sblock, 0); + *context = (void *) end_offset; + + /* Emit the length of the list */ + (void) sieve_binary_emit_unsigned(sblock, listlen); +} + +void sieve_opr_stringlist_emit_item +(struct sieve_binary_block *sblock, void *context ATTR_UNUSED, string_t *item) +{ + (void) sieve_opr_string_emit(sblock, item); +} + +void sieve_opr_stringlist_emit_end +(struct sieve_binary_block *sblock, void *context) +{ + sieve_size_t *end_offset = (sieve_size_t *) context; + + (void) sieve_binary_resolve_offset(sblock, *end_offset); +} + +bool sieve_opr_stringlist_dump_data +(const struct sieve_dumptime_env *denv, struct sieve_operand *oprnd, + sieve_size_t *address, const char *field_name) +{ + if ( oprnd == NULL || oprnd->def == NULL ) + return FALSE; + + oprnd->field_name = field_name; + + if ( oprnd->def->class == &stringlist_class ) { + const struct sieve_opr_stringlist_interface *intf = + (const struct sieve_opr_stringlist_interface *) oprnd->def->interface; + + if ( intf->dump == NULL ) + return FALSE; + + return intf->dump(denv, oprnd, address); + } else if ( oprnd->def->class == &string_class ) { + const struct sieve_opr_string_interface *intf = + (const struct sieve_opr_string_interface *) oprnd->def->interface; + + if ( intf->dump == NULL ) + return FALSE; + + return intf->dump(denv, oprnd, address); + } + + return FALSE; +} + +bool sieve_opr_stringlist_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address, + const char *field_name) +{ + struct sieve_operand operand; + + sieve_code_mark(denv); + + if ( !sieve_operand_read(denv->sblock, address, field_name, &operand) ) { + return FALSE; + } + + return sieve_opr_stringlist_dump_data(denv, &operand, address, field_name); +} + +bool sieve_opr_stringlist_dump_ex +(const struct sieve_dumptime_env *denv, sieve_size_t *address, + const char *field_name, const char *omitted_value) +{ + struct sieve_operand operand; + + sieve_code_mark(denv); + + if ( !sieve_operand_read(denv->sblock, address, field_name, &operand) ) { + return FALSE; + } + + if ( omitted_value != NULL && sieve_operand_is_omitted(&operand) ) { + if ( *omitted_value != '\0' ) + sieve_code_dumpf(denv, "%s: %s", field_name, omitted_value); + return TRUE; + } + + return sieve_opr_stringlist_dump_data(denv, &operand, address, field_name); +} + +int sieve_opr_stringlist_read_data +(const struct sieve_runtime_env *renv, struct sieve_operand *oprnd, + sieve_size_t *address, const char *field_name, + struct sieve_stringlist **strlist_r) +{ + if ( oprnd == NULL || oprnd->def == NULL ) + return SIEVE_EXEC_FAILURE; + + oprnd->field_name = field_name; + + if ( oprnd->def->class == &stringlist_class ) { + const struct sieve_opr_stringlist_interface *intf = + (const struct sieve_opr_stringlist_interface *) oprnd->def->interface; + int ret; + + if ( intf->read == NULL ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "stringlist operand not implemented"); + return SIEVE_EXEC_FAILURE; + } + + if ( (ret=intf->read(renv, oprnd, address, strlist_r)) <= 0 ) + return ret; + + return SIEVE_EXEC_OK; + } else if ( oprnd->def->class == &string_class ) { + /* Special case, accept single string as string list as well. */ + const struct sieve_opr_string_interface *intf = + (const struct sieve_opr_string_interface *) oprnd->def->interface; + int ret; + + if ( intf->read == NULL ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "stringlist string operand not implemented"); + return SIEVE_EXEC_FAILURE; + } + + if ( strlist_r == NULL ) { + if ( (ret=intf->read(renv, oprnd, address, NULL)) <= 0 ) + return ret; + } else { + string_t *stritem; + if ( (ret=intf->read(renv, oprnd, address, &stritem)) <= 0 ) + return ret; + + *strlist_r = sieve_single_stringlist_create + (renv, stritem, FALSE); + } + return SIEVE_EXEC_OK; + } + + sieve_runtime_trace_operand_error(renv, oprnd, + "expected stringlist or string operand but found %s", + sieve_operand_name(oprnd)); + return SIEVE_EXEC_BIN_CORRUPT; +} + +int sieve_opr_stringlist_read +(const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, struct sieve_stringlist **strlist_r) +{ + struct sieve_operand operand; + int ret; + + if ( (ret=sieve_operand_runtime_read(renv, address, field_name, &operand)) + <= 0 ) + return ret; + + return sieve_opr_stringlist_read_data + (renv, &operand, address, field_name, strlist_r); +} + +int sieve_opr_stringlist_read_ex +(const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, bool optional, struct sieve_stringlist **strlist_r) +{ + struct sieve_operand operand; + int ret; + + if ( (ret=sieve_operand_runtime_read(renv, address, field_name, &operand)) + <= 0 ) + return ret; + + if ( optional && sieve_operand_is_omitted(&operand) ) { + *strlist_r = NULL; + return 1; + } + + return sieve_opr_stringlist_read_data + (renv, &operand, address, field_name, strlist_r); +} + +static bool opr_stringlist_dump +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) +{ + sieve_size_t pc = *address; + sieve_size_t end; + unsigned int length = 0; + sieve_offset_t end_offset; + + if ( !sieve_binary_read_offset(denv->sblock, address, &end_offset) ) + return FALSE; + + end = pc + end_offset; + + if ( !sieve_binary_read_unsigned(denv->sblock, address, &length) ) + return FALSE; + + return sieve_code_stringlist_dump + (denv, address, length, end, oprnd->field_name); +} + +static int opr_stringlist_read +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, struct sieve_stringlist **strlist_r) +{ + sieve_size_t pc = *address; + sieve_size_t end; + unsigned int length = 0; + sieve_offset_t end_offset; + + if ( !sieve_binary_read_offset(renv->sblock, address, &end_offset) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "stringlist corrupt: invalid end offset"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + end = pc + end_offset; + + if ( !sieve_binary_read_unsigned(renv->sblock, address, &length) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "stringlist corrupt: invalid length data"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( strlist_r != NULL ) + *strlist_r = sieve_code_stringlist_create + (renv, *address, (unsigned int) length, end); + + /* Skip over the string list for now */ + *address = end; + + return SIEVE_EXEC_OK; +} + +/* Catenated String */ + +void sieve_opr_catenated_string_emit +(struct sieve_binary_block *sblock, unsigned int elements) +{ + (void) sieve_operand_emit(sblock, NULL, &catenated_string_operand); + (void) sieve_binary_emit_unsigned(sblock, elements); +} + +static bool opr_catenated_string_dump +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) +{ + unsigned int elements = 0; + unsigned int i; + + if ( !sieve_binary_read_unsigned(denv->sblock, address, &elements) ) + return FALSE; + + if ( oprnd->field_name != NULL ) + sieve_code_dumpf(denv, "%s: CAT-STR [%ld]:", + oprnd->field_name, (long) elements); + else + sieve_code_dumpf(denv, "CAT-STR [%ld]:", (long) elements); + + sieve_code_descend(denv); + for ( i = 0; i < (unsigned int) elements; i++ ) { + if ( !sieve_opr_string_dump(denv, address, NULL) ) + return FALSE; + } + sieve_code_ascend(denv); + + return TRUE; +} + +static int opr_catenated_string_read +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str) +{ + unsigned int elements = 0; + unsigned int i; + int ret; + + if ( !sieve_binary_read_unsigned(renv->sblock, address, &elements) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "catenated string corrupt: invalid element count data"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + /* Parameter str can be NULL if we are requested to only skip and not + * actually read the argument. + */ + if ( str == NULL ) { + for ( i = 0; i < (unsigned int) elements; i++ ) { + if ( (ret=sieve_opr_string_read(renv, address, NULL, NULL)) <= 0 ) + return ret; + } + } else { + string_t *strelm; + string_t **elm = &strelm; + + *str = t_str_new(128); + for ( i = 0; i < (unsigned int) elements; i++ ) { + + if ( (ret=sieve_opr_string_read(renv, address, NULL, elm)) <= 0 ) + return ret; + + if ( elm != NULL ) { + str_append_str(*str, strelm); + + if ( str_len(*str) > SIEVE_MAX_STRING_LEN ) { + str_truncate(*str, SIEVE_MAX_STRING_LEN); + elm = NULL; + } + } + } + } + + return SIEVE_EXEC_OK; +} + +/* + * Core operations + */ + +/* Forward declarations */ + +static bool opc_jmp_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); + +static int opc_jmp_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); +static int opc_jmptrue_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); +static int opc_jmpfalse_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +/* Operation objects defined in this file */ + +const struct sieve_operation_def sieve_jmp_operation = { + .mnemonic = "JMP", + .code = SIEVE_OPERATION_JMP, + .dump = opc_jmp_dump, + .execute = opc_jmp_execute +}; + +const struct sieve_operation_def sieve_jmptrue_operation = { + .mnemonic = "JMPTRUE", + .code = SIEVE_OPERATION_JMPTRUE, + .dump = opc_jmp_dump, + .execute = opc_jmptrue_execute +}; + +const struct sieve_operation_def sieve_jmpfalse_operation = { + .mnemonic = "JMPFALSE", + .code = SIEVE_OPERATION_JMPFALSE, + .dump = opc_jmp_dump, + .execute = opc_jmpfalse_execute +}; + +/* Operation objects defined in other files */ + +extern const struct sieve_operation_def cmd_stop_operation; +extern const struct sieve_operation_def cmd_keep_operation; +extern const struct sieve_operation_def cmd_discard_operation; +extern const struct sieve_operation_def cmd_redirect_operation; + +extern const struct sieve_operation_def tst_address_operation; +extern const struct sieve_operation_def tst_header_operation; +extern const struct sieve_operation_def tst_exists_operation; +extern const struct sieve_operation_def tst_size_over_operation; +extern const struct sieve_operation_def tst_size_under_operation; + +const struct sieve_operation_def *sieve_operations[] = { + NULL, + + &sieve_jmp_operation, + &sieve_jmptrue_operation, + &sieve_jmpfalse_operation, + + &cmd_stop_operation, + &cmd_keep_operation, + &cmd_discard_operation, + &cmd_redirect_operation, + + &tst_address_operation, + &tst_header_operation, + &tst_exists_operation, + &tst_size_over_operation, + &tst_size_under_operation +}; + +const unsigned int sieve_operation_count = + N_ELEMENTS(sieve_operations); + +/* + * Operation functions + */ + +sieve_size_t sieve_operation_emit +(struct sieve_binary_block *sblock, const struct sieve_extension *ext, + const struct sieve_operation_def *op_def) +{ + sieve_size_t address; + + if ( ext != NULL ) { + i_assert( op_def->ext_def != NULL ); + address = sieve_binary_emit_extension + (sblock, ext, sieve_operation_count); + + sieve_binary_emit_extension_object + (sblock, &op_def->ext_def->operations, op_def->code); + return address; + } + + i_assert( op_def->ext_def == NULL ); + return sieve_binary_emit_byte(sblock, op_def->code); +} + +bool sieve_operation_read +(struct sieve_binary_block *sblock, sieve_size_t *address, + struct sieve_operation *oprtn) +{ + unsigned int code = sieve_operation_count; + + oprtn->address = *address; + oprtn->def = NULL; + oprtn->ext = NULL; + + if ( !sieve_binary_read_extension(sblock, address, &code, &oprtn->ext) ) + return FALSE; + + if ( oprtn->ext == NULL ) { + if ( code < sieve_operation_count ) { + oprtn->def = sieve_operations[code]; + } + + return ( oprtn->def != NULL ); + } + + oprtn->def = (const struct sieve_operation_def *) + sieve_binary_read_extension_object(sblock, address, + &oprtn->ext->def->operations); + + return ( oprtn->def != NULL ); +} + +/* + * Jump operations + */ + +/* Code dump */ + +static bool opc_jmp_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + const struct sieve_operation *oprtn = denv->oprtn; + unsigned int pc = *address; + sieve_offset_t offset; + + if ( sieve_binary_read_offset(denv->sblock, address, &offset) ) + sieve_code_dumpf(denv, "%s %d [%08x]", + sieve_operation_mnemonic(oprtn), offset, pc + offset); + else + return FALSE; + + return TRUE; +} + +/* Code execution */ + +static int opc_jmp_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED) +{ + return sieve_interpreter_program_jump(renv->interp, TRUE, FALSE); +} + +static int opc_jmptrue_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED) +{ + bool result = sieve_interpreter_get_test_result(renv->interp); + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "jump if result is true"); + sieve_runtime_trace_descend(renv); + + return sieve_interpreter_program_jump(renv->interp, result, FALSE); +} + +static int opc_jmpfalse_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED) +{ + bool result = sieve_interpreter_get_test_result(renv->interp); + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "jump if result is false"); + sieve_runtime_trace_descend(renv); + + return sieve_interpreter_program_jump(renv->interp, !result, FALSE); +} diff --git a/pigeonhole/src/lib-sieve/sieve-code.h b/pigeonhole/src/lib-sieve/sieve-code.h new file mode 100644 index 0000000..00bf68b --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-code.h @@ -0,0 +1,351 @@ +#ifndef SIEVE_CODE_H +#define SIEVE_CODE_H + +#include "lib.h" +#include "buffer.h" +#include "mempool.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-runtime.h" +#include "sieve-runtime-trace.h" +#include "sieve-dump.h" + +/* + * Operand object + */ + +struct sieve_operand_class { + const char *name; +}; + +struct sieve_operand_def { + const char *name; + + const struct sieve_extension_def *ext_def; + unsigned int code; + + const struct sieve_operand_class *class; + const void *interface; +}; + +struct sieve_operand { + const struct sieve_operand_def *def; + const struct sieve_extension *ext; + sieve_size_t address; + const char *field_name; +}; + +#define sieve_operand_name(opr) \ + ( (opr)->def == NULL ? "(NULL)" : (opr)->def->name ) +#define sieve_operand_is(opr, definition) \ + ( (opr)->def == &(definition) ) + +sieve_size_t sieve_operand_emit + (struct sieve_binary_block *sblock, const struct sieve_extension *ext, + const struct sieve_operand_def *oprnd); +bool sieve_operand_read + (struct sieve_binary_block *sblock, sieve_size_t *address, + const char *field_name, struct sieve_operand *oprnd); + +static inline int sieve_operand_runtime_read +(const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, struct sieve_operand *operand) +{ + if ( !sieve_operand_read(renv->sblock, address, field_name, operand) ) { + sieve_runtime_trace_operand_error(renv, operand, "invalid operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + return SIEVE_EXEC_OK; +} + +/* + * Optional operands + */ + +int sieve_opr_optional_next +(struct sieve_binary_block *sblock, sieve_size_t *address, + signed int *opt_code); + +static inline int sieve_opr_optional_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address, + signed int *opt_code) +{ + sieve_size_t pc = *address; + int ret; + + if ( (ret=sieve_opr_optional_next(denv->sblock, address, opt_code)) <= 0 ) + return ret; + + sieve_code_mark_specific(denv, pc); + return ret; +} + +static inline int sieve_opr_optional_read +(const struct sieve_runtime_env *renv, sieve_size_t *address, + signed int *opt_code) +{ + int ret; + + if ( (ret=sieve_opr_optional_next(renv->sblock, address, opt_code)) < 0 ) + sieve_runtime_trace_error(renv, "invalid optional operand code"); + + return ret; +} + +/* + * Core operands + */ + +/* Operand codes */ + +enum sieve_core_operand { + SIEVE_OPERAND_OPTIONAL = 0x00, + SIEVE_OPERAND_NUMBER, + SIEVE_OPERAND_STRING, + SIEVE_OPERAND_STRING_LIST, + SIEVE_OPERAND_COMPARATOR, + SIEVE_OPERAND_MATCH_TYPE, + SIEVE_OPERAND_ADDRESS_PART, + SIEVE_OPERAND_CATENATED_STRING, + + SIEVE_OPERAND_CUSTOM +}; + +/* Operand classes */ + +extern const struct sieve_operand_class number_class; +extern const struct sieve_operand_class string_class; +extern const struct sieve_operand_class stringlist_class; + +/* Operand objects */ + +extern const struct sieve_operand_def omitted_operand; +extern const struct sieve_operand_def number_operand; +extern const struct sieve_operand_def string_operand; +extern const struct sieve_operand_def stringlist_operand; +extern const struct sieve_operand_def catenated_string_operand; + +extern const struct sieve_operand_def *sieve_operands[]; +extern const unsigned int sieve_operand_count; + +/* Operand object interfaces */ + +struct sieve_opr_number_interface { + bool (*dump) + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); + int (*read) + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, sieve_number_t *number_r); +}; + +struct sieve_opr_string_interface { + bool (*dump) + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); + int (*read) + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r); +}; + +struct sieve_opr_stringlist_interface { + bool (*dump) + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); + int (*read) + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, struct sieve_stringlist **strlist_r); +}; + +/* + * Core operand functions + */ + +/* Omitted */ + +void sieve_opr_omitted_emit(struct sieve_binary_block *sblock); + +static inline bool sieve_operand_is_omitted +(const struct sieve_operand *operand) +{ + return ( operand != NULL && operand->def != NULL && + operand->def == &omitted_operand ); +} + +/* Number */ + +void sieve_opr_number_emit + (struct sieve_binary_block *sblock, sieve_number_t number); +bool sieve_opr_number_dump_data + (const struct sieve_dumptime_env *denv, struct sieve_operand *operand, + sieve_size_t *address, const char *field_name); +bool sieve_opr_number_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address, + const char *field_name); +int sieve_opr_number_read_data + (const struct sieve_runtime_env *renv, struct sieve_operand *operand, + sieve_size_t *address, const char *field_name, sieve_number_t *number_r); +int sieve_opr_number_read + (const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, sieve_number_t *number_r); + +static inline bool sieve_operand_is_number +(const struct sieve_operand *operand) +{ + return ( operand != NULL && operand->def != NULL && + operand->def->class == &number_class ); +} + +/* String */ + +void sieve_opr_string_emit + (struct sieve_binary_block *sblock, string_t *str); +bool sieve_opr_string_dump_data + (const struct sieve_dumptime_env *denv, struct sieve_operand *operand, + sieve_size_t *address, const char *field_name); +bool sieve_opr_string_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address, + const char *field_name); +bool sieve_opr_string_dump_ex + (const struct sieve_dumptime_env *denv, sieve_size_t *address, + const char *field_name, const char *omitted_value); +int sieve_opr_string_read_data + (const struct sieve_runtime_env *renv, struct sieve_operand *operand, + sieve_size_t *address, const char *field_name, string_t **str_r); +int sieve_opr_string_read + (const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, string_t **str_r); +int sieve_opr_string_read_ex + (const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, bool optional, string_t **str_r, bool *literal_r); + +static inline bool sieve_operand_is_string +(const struct sieve_operand *operand) +{ + return ( operand != NULL && operand->def != NULL && + operand->def->class == &string_class ); +} + +static inline bool sieve_operand_is_string_literal +(const struct sieve_operand *operand) +{ + return ( operand != NULL && sieve_operand_is(operand, string_operand) ); +} + +/* String list */ + +void sieve_opr_stringlist_emit_start + (struct sieve_binary_block *sblock, unsigned int listlen, void **context); +void sieve_opr_stringlist_emit_item + (struct sieve_binary_block *sblock, void *context ATTR_UNUSED, + string_t *item); +void sieve_opr_stringlist_emit_end + (struct sieve_binary_block *sblock, void *context); +bool sieve_opr_stringlist_dump_data + (const struct sieve_dumptime_env *denv, struct sieve_operand *operand, + sieve_size_t *address, const char *field_name); +bool sieve_opr_stringlist_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address, + const char *field_name); +bool sieve_opr_stringlist_dump_ex + (const struct sieve_dumptime_env *denv, sieve_size_t *address, + const char *field_name, const char *omitted_value); +int sieve_opr_stringlist_read_data + (const struct sieve_runtime_env *renv, struct sieve_operand *operand, + sieve_size_t *address, const char *field_name, + struct sieve_stringlist **strlist_r); +int sieve_opr_stringlist_read + (const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, struct sieve_stringlist **strlist_r); +int sieve_opr_stringlist_read_ex + (const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, bool optional, struct sieve_stringlist **strlist_r); + +static inline bool sieve_operand_is_stringlist +(const struct sieve_operand *operand) +{ + return ( operand != NULL && operand->def != NULL && + (operand->def->class == &stringlist_class || + operand->def->class == &string_class) ); +} + +/* Catenated string */ + +void sieve_opr_catenated_string_emit + (struct sieve_binary_block *sblock, unsigned int elements); + +/* + * Operation object + */ + +struct sieve_operation_def { + const char *mnemonic; + + const struct sieve_extension_def *ext_def; + unsigned int code; + + bool (*dump) + (const struct sieve_dumptime_env *denv, sieve_size_t *address); + int (*execute) + (const struct sieve_runtime_env *renv, sieve_size_t *address); +}; + +struct sieve_operation { + const struct sieve_operation_def *def; + const struct sieve_extension *ext; + + sieve_size_t address; +}; + +#define sieve_operation_is(oprtn, definition) \ + ( (oprtn)->def == &(definition) ) +#define sieve_operation_mnemonic(oprtn) \ + ( (oprtn)->def == NULL ? "(NULL)" : (oprtn)->def->mnemonic ) + +sieve_size_t sieve_operation_emit + (struct sieve_binary_block *sblock, const struct sieve_extension *ext, + const struct sieve_operation_def *op_def); +bool sieve_operation_read + (struct sieve_binary_block *sblock, sieve_size_t *address, + struct sieve_operation *oprtn); +const char *sieve_operation_read_string + (struct sieve_binary_block *sblock, sieve_size_t *address); + +/* + * Core operations + */ + +/* Opcodes */ + +enum sieve_operation_code { + SIEVE_OPERATION_INVALID, + SIEVE_OPERATION_JMP, + SIEVE_OPERATION_JMPTRUE, + SIEVE_OPERATION_JMPFALSE, + + SIEVE_OPERATION_STOP, + SIEVE_OPERATION_KEEP, + SIEVE_OPERATION_DISCARD, + SIEVE_OPERATION_REDIRECT, + + SIEVE_OPERATION_ADDRESS, + SIEVE_OPERATION_HEADER, + SIEVE_OPERATION_EXISTS, + SIEVE_OPERATION_SIZE_OVER, + SIEVE_OPERATION_SIZE_UNDER, + + SIEVE_OPERATION_CUSTOM +}; + +/* Operation objects */ + +extern const struct sieve_operation_def sieve_jmp_operation; +extern const struct sieve_operation_def sieve_jmptrue_operation; +extern const struct sieve_operation_def sieve_jmpfalse_operation; + +extern const struct sieve_operation_def *sieve_operations[]; +extern const unsigned int sieve_operations_count; + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-commands.c b/pigeonhole/src/lib-sieve/sieve-commands.c new file mode 100644 index 0000000..324b66d --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-commands.c @@ -0,0 +1,403 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" + +#include "rfc2822.h" + +#include "sieve-common.h" +#include "sieve-ast.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-interpreter.h" + +/* + * Literal arguments + */ + +/* Forward declarations */ + +static bool arg_number_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *context); +static bool arg_string_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *context); +static bool arg_string_list_validate + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *context); +static bool arg_string_list_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *context); + +/* Argument objects */ + +const struct sieve_argument_def number_argument = { + .identifier = "@number", + .generate = arg_number_generate +}; + +const struct sieve_argument_def string_argument = { + .identifier = "@string", + .generate = arg_string_generate +}; + +const struct sieve_argument_def string_list_argument = { + .identifier = "@string-list", + .validate = arg_string_list_validate, + .generate = arg_string_list_generate +}; + +/* Argument implementations */ + +static bool arg_number_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + sieve_opr_number_emit(cgenv->sblock, sieve_ast_argument_number(arg)); + + return TRUE; +} + +static bool arg_string_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + sieve_opr_string_emit(cgenv->sblock, sieve_ast_argument_str(arg)); + + return TRUE; +} + +static bool arg_string_list_validate +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *stritem; + + stritem = sieve_ast_strlist_first(*arg); + while ( stritem != NULL ) { + if ( !sieve_validator_argument_activate(valdtr, cmd, stritem, FALSE) ) + return FALSE; + + stritem = sieve_ast_strlist_next(stritem); + } + + return TRUE; +} + +static bool emit_string_list_operand +(const struct sieve_codegen_env *cgenv, const struct sieve_ast_argument *strlist, + struct sieve_command *cmd) +{ + void *list_context; + struct sieve_ast_argument *stritem; + + sieve_opr_stringlist_emit_start + (cgenv->sblock, sieve_ast_strlist_count(strlist), &list_context); + + stritem = sieve_ast_strlist_first(strlist); + while ( stritem != NULL ) { + if ( !sieve_generate_argument(cgenv, stritem, cmd) ) + return FALSE; + + stritem = sieve_ast_strlist_next(stritem); + } + + sieve_opr_stringlist_emit_end(cgenv->sblock, list_context); + + return TRUE; +} + +static bool arg_string_list_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd) +{ + if ( sieve_ast_argument_type(arg) == SAAT_STRING ) { + return ( sieve_generate_argument(cgenv, arg, cmd) ); + + } else if ( sieve_ast_argument_type(arg) == SAAT_STRING_LIST ) { + bool result = TRUE; + + if ( sieve_ast_strlist_count(arg) == 1 ) + return ( sieve_generate_argument + (cgenv, sieve_ast_strlist_first(arg), cmd) ); + else { + T_BEGIN { + result=emit_string_list_operand(cgenv, arg, cmd); + } T_END; + } + + return result; + } + + return FALSE; +} + +/* + * Abstract arguments + * + * (Generated by processing and not by parsing the grammar) + */ + +/* Catenated string */ + +struct sieve_arg_catenated_string { + struct sieve_ast_arg_list *str_parts; +}; + +struct sieve_arg_catenated_string *sieve_arg_catenated_string_create +(struct sieve_ast_argument *orig_arg) +{ + pool_t pool = sieve_ast_pool(orig_arg->ast); + struct sieve_ast_arg_list *arglist; + struct sieve_arg_catenated_string *catstr; + + arglist = sieve_ast_arg_list_create(pool); + + catstr = p_new(pool, struct sieve_arg_catenated_string, 1); + catstr->str_parts = arglist; + (orig_arg)->argument->data = (void *) catstr; + + return catstr; +} + +void sieve_arg_catenated_string_add_element +(struct sieve_arg_catenated_string *catstr, + struct sieve_ast_argument *element) +{ + sieve_ast_arg_list_add(catstr->str_parts, element); +} + +#define _cat_string_first(catstr) __AST_LIST_FIRST((catstr)->str_parts) +#define _cat_string_count(catstr) __AST_LIST_COUNT((catstr)->str_parts) +#define _cat_string_next(item) __AST_LIST_NEXT(item) + +bool sieve_arg_catenated_string_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd) +{ + struct sieve_arg_catenated_string *catstr = + (struct sieve_arg_catenated_string *) arg->argument->data; + struct sieve_ast_argument *strpart; + + if ( _cat_string_count(catstr) == 1 ) + sieve_generate_argument(cgenv, _cat_string_first(catstr), cmd); + else { + sieve_opr_catenated_string_emit(cgenv->sblock, _cat_string_count(catstr)); + + strpart = _cat_string_first(catstr); + while ( strpart != NULL ) { + if ( !sieve_generate_argument(cgenv, strpart, cmd) ) + return FALSE; + + strpart = _cat_string_next(strpart); + } + } + + return TRUE; +} + +/* + * Argument creation + */ + +struct sieve_argument *sieve_argument_create +(struct sieve_ast *ast, const struct sieve_argument_def *def, + const struct sieve_extension *ext, int id_code) +{ + struct sieve_argument *arg; + pool_t pool; + + pool = sieve_ast_pool(ast); + arg = p_new(pool, struct sieve_argument, 1); + arg->def = def; + arg->ext = ext; + arg->id_code = id_code; + + return arg; +} + +/* + * Core tests and commands + */ + +const struct sieve_command_def *sieve_core_tests[] = { + &tst_false, &tst_true, + &tst_not, &tst_anyof, &tst_allof, + &tst_address, &tst_header, &tst_exists, &tst_size +}; + +const unsigned int sieve_core_tests_count = N_ELEMENTS(sieve_core_tests); + +const struct sieve_command_def *sieve_core_commands[] = { + &cmd_require, + &cmd_stop, &cmd_if, &cmd_elsif, &cmd_else, + &cmd_keep, &cmd_discard, &cmd_redirect +}; + +const unsigned int sieve_core_commands_count = N_ELEMENTS(sieve_core_commands); + +/* + * Command context + */ + +struct sieve_command *sieve_command_prev +(struct sieve_command *cmd) +{ + struct sieve_ast_node *node = sieve_ast_node_prev(cmd->ast_node); + + if ( node != NULL ) { + return node->command; + } + + return NULL; +} + +struct sieve_command *sieve_command_parent +(struct sieve_command *cmd) +{ + struct sieve_ast_node *node = sieve_ast_node_parent(cmd->ast_node); + + return ( node != NULL ? node->command : NULL ); +} + +struct sieve_command *sieve_command_create +(struct sieve_ast_node *cmd_node, const struct sieve_extension *ext, + const struct sieve_command_def *cmd_def, + struct sieve_command_registration *cmd_reg) +{ + struct sieve_command *cmd; + + cmd = p_new(sieve_ast_node_pool(cmd_node), struct sieve_command, 1); + + cmd->ast_node = cmd_node; + cmd->def = cmd_def; + cmd->ext = ext; + cmd->reg = cmd_reg; + + cmd->block_exit_command = NULL; + + return cmd; +} + +const char *sieve_command_def_type_name +(const struct sieve_command_def *cmd_def) +{ + switch ( cmd_def->type ) { + case SCT_NONE: return "command of unspecified type (bug)"; + case SCT_TEST: return "test"; + case SCT_COMMAND: return "command"; + case SCT_HYBRID: return "command or test"; + default: + break; + } + return "??COMMAND-TYPE??"; +} + +const char *sieve_command_type_name + (const struct sieve_command *cmd) +{ + switch ( cmd->def->type ) { + case SCT_NONE: return "command of unspecified type (bug)"; + case SCT_TEST: return "test"; + case SCT_COMMAND: return "command"; + case SCT_HYBRID: + if ( cmd->ast_node->type == SAT_TEST ) + return "test"; + return "command"; + default: + break; + } + return "??COMMAND-TYPE??"; +} + +struct sieve_ast_argument *sieve_command_add_dynamic_tag +(struct sieve_command *cmd, const struct sieve_extension *ext, + const struct sieve_argument_def *tag, int id_code) +{ + struct sieve_ast_argument *arg; + + if ( cmd->first_positional != NULL ) + arg = sieve_ast_argument_tag_insert + (cmd->first_positional, tag->identifier, cmd->ast_node->source_line); + else + arg = sieve_ast_argument_tag_create + (cmd->ast_node, tag->identifier, cmd->ast_node->source_line); + + arg->argument = sieve_argument_create(cmd->ast_node->ast, tag, ext, id_code); + + return arg; +} + +struct sieve_ast_argument *sieve_command_find_argument +(struct sieve_command *cmd, const struct sieve_argument_def *arg_def) +{ + struct sieve_ast_argument *arg = sieve_ast_argument_first(cmd->ast_node); + + /* Visit tagged and optional arguments */ + while ( arg != NULL ) { + if ( arg->argument != NULL && arg->argument->def == arg_def ) + return arg; + + arg = sieve_ast_argument_next(arg); + } + + return arg; +} + +/* Use this function with caution. The command commits to exiting the block. + * When it for some reason does not, the interpretation will break later on, + * because exiting jumps are not generated when they would otherwise be + * necessary. + */ +void sieve_command_exit_block_unconditionally + (struct sieve_command *cmd) +{ + struct sieve_command *parent = sieve_command_parent(cmd); + + /* Only the first unconditional exit is of importance */ + if ( parent != NULL && parent->block_exit_command == NULL ) + parent->block_exit_command = cmd; +} + +bool sieve_command_block_exits_unconditionally + (struct sieve_command *cmd) +{ + return ( cmd->block_exit_command != NULL ); +} + +/* + * Command utility functions + */ + +/* NOTE: this may be moved */ + +static int _verify_header_name_item +(void *context, struct sieve_ast_argument *header) +{ + struct sieve_validator *valdtr = (struct sieve_validator *) context; + string_t *name = sieve_ast_argument_str(header); + + if ( sieve_argument_is_string_literal(header) && + !rfc2822_header_field_name_verify(str_c(name), str_len(name)) ) { + sieve_argument_validate_warning + (valdtr, header, "specified header field name '%s' is invalid", + str_sanitize(str_c(name), 80)); + + return 0; + } + + return 1; +} + +bool sieve_command_verify_headers_argument +(struct sieve_validator *valdtr, struct sieve_ast_argument *headers) +{ + return ( sieve_ast_stringlist_map + (&headers, (void *) valdtr, _verify_header_name_item) >= 0 ); +} diff --git a/pigeonhole/src/lib-sieve/sieve-commands.h b/pigeonhole/src/lib-sieve/sieve-commands.h new file mode 100644 index 0000000..f9b83e3 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-commands.h @@ -0,0 +1,286 @@ +#ifndef SIEVE_COMMANDS_H +#define SIEVE_COMMANDS_H + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-ast.h" + +/* + * Argument definition + */ + +enum sieve_argument_flag { + /* More than one of this (type of) tagged argument is allowed */ + SIEVE_ARGUMENT_FLAG_MULTIPLE = (1 << 0) +}; + +struct sieve_argument_def { + const char *identifier; + enum sieve_argument_flag flags; + + bool (*is_instance_of) + (struct sieve_validator *valdtr, struct sieve_command *cmd, + const struct sieve_extension *ext, const char *identifier, void **data); + + bool (*validate) + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + bool (*validate_context) + (struct sieve_validator *valdtr, struct sieve_ast_argument *arg, + struct sieve_command *cmd); + bool (*validate_persistent) + (struct sieve_validator *valdtr, struct sieve_command *cmd, + const struct sieve_extension *ext); + + bool (*generate) + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd); +}; + +/* + * Argument instance + */ + +struct sieve_argument { + const struct sieve_argument_def *def; + const struct sieve_extension *ext; + int id_code; + + /* Context data */ + void *data; +}; + +#define sieve_argument_is(ast_arg, definition) \ + ( (ast_arg)->argument->def == &(definition) ) +#define sieve_argument_ext(ast_arg) \ + ( (ast_arg)->argument->ext ) +#define sieve_argument_identifier(ast_arg) \ + ( (ast_arg)->argument->def->identifier ) + +/* Utility macros */ + +#define sieve_argument_is_string_literal(arg) \ + ( (arg)->argument->def == &string_argument ) + +/* Error handling */ + +#define sieve_argument_validate_error(validator, arg_node, ...) \ + sieve_validator_error(validator, \ + ((arg_node) == NULL ? 0 : (arg_node)->source_line), \ + __VA_ARGS__) +#define sieve_argument_validate_warning(validator, arg_node, ...) \ + sieve_validator_warning(validator, \ + ((arg_node) == NULL ? 0 : (arg_node)->source_line), \ + __VA_ARGS__) + +#define sieve_argument_generate_error(gentr, arg_node, ...) \ + sieve_generator_error(gentr, \ + ((arg_node) == NULL ? 0 : (arg_node)->source_line), \ + __VA_ARGS__) +#define sieve_argument_generate_warning(gentr, arg_node, ...) \ + sieve_generator_warning(gentr, \ + ((arg_node) == NULL ? 0 : (arg_node)->source_line), \ + __VA_ARGS__) + +/* Argument API */ + +struct sieve_argument *sieve_argument_create + (struct sieve_ast *ast, const struct sieve_argument_def *def, + const struct sieve_extension *ext, int id_code); + +/* Literal arguments */ + +extern const struct sieve_argument_def number_argument; +extern const struct sieve_argument_def string_argument; +extern const struct sieve_argument_def string_list_argument; + +/* Catenated string argument */ + +bool sieve_arg_catenated_string_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *context); + +struct sieve_arg_catenated_string; + +struct sieve_arg_catenated_string *sieve_arg_catenated_string_create + (struct sieve_ast_argument *orig_arg); +void sieve_arg_catenated_string_add_element + (struct sieve_arg_catenated_string *strdata, + struct sieve_ast_argument *element); + +/* + * Command definition + */ + +enum sieve_command_type { + SCT_NONE, + SCT_COMMAND, + SCT_TEST, + SCT_HYBRID +}; + +struct sieve_command_def { + const char *identifier; + enum sieve_command_type type; + + /* High-level command syntax */ + int positional_args; + int subtests; + bool block_allowed; + bool block_required; + + bool (*registered) + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); + bool (*pre_validate) + (struct sieve_validator *valdtr, struct sieve_command *cmd); + bool (*validate) + (struct sieve_validator *valdtr, struct sieve_command *cmd); + bool (*validate_const) + (struct sieve_validator *valdtr, struct sieve_command *cmd, + int *const_current, int const_next); + bool (*generate) + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + bool (*control_generate) + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd, + struct sieve_jumplist *jumps, bool jump_true); +}; + +/* + * Command instance + */ + +struct sieve_command { + const struct sieve_command_def *def; + const struct sieve_extension *ext; + + /* The registration of this command in the validator (sieve-validator.h) */ + struct sieve_command_registration *reg; + + /* The ast node of this command */ + struct sieve_ast_node *ast_node; + + /* First positional argument, found during argument validation */ + struct sieve_ast_argument *first_positional; + + /* The child ast node that unconditionally exits this command's block */ + struct sieve_command *block_exit_command; + + /* Context data*/ + void *data; +}; + +#define sieve_command_is(cmd, definition) \ + ( (cmd)->def == &(definition) ) +#define sieve_command_identifier(cmd) \ + ( (cmd)->def->identifier ) + +#define sieve_commands_equal(cmd1, cmd2) \ + ( (cmd1) != NULL && (cmd2) != NULL && (cmd1)->def == (cmd2)->def ) + +/* Context API */ + +struct sieve_command *sieve_command_create + (struct sieve_ast_node *cmd_node, const struct sieve_extension *ext, + const struct sieve_command_def *cmd_def, + struct sieve_command_registration *cmd_reg); + +const char *sieve_command_def_type_name + (const struct sieve_command_def *cmd_def); +const char *sieve_command_type_name + (const struct sieve_command *cmd); + +struct sieve_command *sieve_command_prev + (struct sieve_command *cmd); +struct sieve_command *sieve_command_parent + (struct sieve_command *cmd); + +struct sieve_ast_argument *sieve_command_add_dynamic_tag + (struct sieve_command *cmd, const struct sieve_extension *ext, + const struct sieve_argument_def *tag, int id_code); +struct sieve_ast_argument *sieve_command_find_argument + (struct sieve_command *cmd, const struct sieve_argument_def *argument); + +void sieve_command_exit_block_unconditionally + (struct sieve_command *cmd); +bool sieve_command_block_exits_unconditionally + (struct sieve_command *cmd); + +/* Error handling */ + +#define sieve_command_validate_error(validator, context, ...) \ + sieve_validator_error(validator, \ + ((context) == NULL ? 0 : (context)->ast_node->source_line), \ + __VA_ARGS__) +#define sieve_command_validate_warning(validator, context, ...) \ + sieve_validator_warning(validator, \ + ((context) == NULL ? 0 : (context)->ast_node->source_line), \ + __VA_ARGS__) + +#define sieve_command_generate_error(gentr, context, ...) \ + sieve_generator_error(gentr, \ + ((context) == NULL ? 0 : (context)->ast_node->source_line), \ + __VA_ARGS__) +#define sieve_command_generate_warning(gentr, context, ...) \ + sieve_generator_warning(gentr, \ + ((context) == NULL ? 0 : (context)->ast_node->source_line), \ + __VA_ARGS__) + +/* Utility macros */ + +#define sieve_command_pool(context) \ + sieve_ast_node_pool((context)->ast_node) + +#define sieve_command_source_line(context) \ + (context)->ast_node->source_line + +#define sieve_command_first_argument(context) \ + sieve_ast_argument_first((context)->ast_node) + +#define sieve_command_is_toplevel(context) \ + ( sieve_ast_node_type(sieve_ast_node_parent((context)->ast_node)) == SAT_ROOT ) +#define sieve_command_is_first(context) \ + ( sieve_ast_node_prev((context)->ast_node) == NULL ) + +/* + * Core commands + */ + +extern const struct sieve_command_def cmd_require; +extern const struct sieve_command_def cmd_stop; +extern const struct sieve_command_def cmd_if; +extern const struct sieve_command_def cmd_elsif; +extern const struct sieve_command_def cmd_else; +extern const struct sieve_command_def cmd_redirect; +extern const struct sieve_command_def cmd_keep; +extern const struct sieve_command_def cmd_discard; + +extern const struct sieve_command_def *sieve_core_commands[]; +extern const unsigned int sieve_core_commands_count; + +/* + * Core tests + */ + +extern const struct sieve_command_def tst_true; +extern const struct sieve_command_def tst_false; +extern const struct sieve_command_def tst_not; +extern const struct sieve_command_def tst_anyof; +extern const struct sieve_command_def tst_allof; +extern const struct sieve_command_def tst_address; +extern const struct sieve_command_def tst_header; +extern const struct sieve_command_def tst_exists; +extern const struct sieve_command_def tst_size; + +extern const struct sieve_command_def *sieve_core_tests[]; +extern const unsigned int sieve_core_tests_count; + +/* + * Command utility functions + */ + +bool sieve_command_verify_headers_argument +(struct sieve_validator *valdtr, struct sieve_ast_argument *headers); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-common.h b/pigeonhole/src/lib-sieve/sieve-common.h new file mode 100644 index 0000000..e79fb4d --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-common.h @@ -0,0 +1,240 @@ +#ifndef SIEVE_COMMON_H +#define SIEVE_COMMON_H + +#include "lib.h" + +#include "sieve.h" + +#include <sys/types.h> + +/* + * Types + */ + +typedef size_t sieve_size_t; +typedef uint32_t sieve_offset_t; +typedef uint64_t sieve_number_t; + +#define SIEVE_MAX_NUMBER ((sieve_number_t)-1) +#define SIEVE_PRI_NUMBER PRIu64 + +/* + * Forward declarations + */ + +/* sieve-error.h */ +struct sieve_error_handler; + +/* sieve-ast.h */ +enum sieve_ast_argument_type; + +struct sieve_ast; +struct sieve_ast_node; +struct sieve_ast_argument; + +/* sieve-commands.h */ +struct sieve_argument; +struct sieve_argument_def; +struct sieve_command; +struct sieve_command_def; +struct sieve_command_context; +struct sieve_command_registration; + +/* sieve-stringlist.h */ +struct sieve_stringlist; + +/* sieve-code.h */ +struct sieve_operation_extension; + +/* sieve-lexer.h */ +struct sieve_lexer; + +/* sieve-parser.h */ +struct sieve_parser; + +/* sieve-validator.h */ +struct sieve_validator; + +/* sieve-generator.h */ +struct sieve_jumplist; +struct sieve_generator; +struct sieve_codegen_env; + +/* sieve-runtime.h */ +struct sieve_runtime_env; + +/* sieve-interpreter.h */ +struct sieve_interpreter; + +/* sieve-dump.h */ +struct sieve_dumptime_env; + +/* sieve-binary-dumper.h */ +struct sieve_binary_dumper; + +/* sieve-code-dumper.h */ +struct sieve_code_dumper; + +/* sieve-extension.h */ +struct sieve_extension; +struct sieve_extension_def; +struct sieve_extension_objects; + +/* sieve-code.h */ +struct sieve_operand; +struct sieve_operand_def; +struct sieve_operand_class; +struct sieve_operation; +struct sieve_coded_stringlist; + +/* sieve-binary.h */ +struct sieve_binary; +struct sieve_binary_block; +struct sieve_binary_debug_writer; +struct sieve_binary_debug_reader; + +/* sieve-execute.h */ +struct sieve_execute; + +/* sieve-objects.h */ +struct sieve_object_def; +struct sieve_object; + +/* sieve-comparator.h */ +struct sieve_comparator; + +/* sieve-match-types.h */ +struct sieve_match_type; + +/* sieve-match.h */ +struct sieve_match_context; + +/* sieve-address.h */ +struct sieve_address_list; + +/* sieve-address-parts.h */ +struct sieve_address_part_def; +struct sieve_address_part; + +/* sieve-result.h */ +struct sieve_result; +struct sieve_side_effects_list; +struct sieve_result_print_env; + +/* sieve-actions.h */ +struct sieve_action_exec_env; +struct sieve_action; +struct sieve_action_def; +struct sieve_side_effect; +struct sieve_side_effect_def; + +/* sieve-script.h */ +struct sieve_script; +struct sieve_script_sequence; + +/* sieve-storage.h */ +struct sieve_storage_class_registry; +struct sieve_storage; + +/* sieve-message.h */ +struct sieve_message_context; +struct sieve_message_override; +struct sieve_message_override_def; + +/* sieve-plugins.h */ +struct sieve_plugin; + +/* sieve.c */ +struct sieve_ast *sieve_parse + (struct sieve_script *script, struct sieve_error_handler *ehandler, + enum sieve_error *error_r); +bool sieve_validate + (struct sieve_ast *ast, struct sieve_error_handler *ehandler, + enum sieve_compile_flags flags, enum sieve_error *error_r); + +/* + * Parent category + */ + +extern struct event_category event_category_sieve; + +/* + * Sieve engine instance + */ + +#include "sieve-address-source.h" + +struct sieve_instance { + /* Main engine pool */ + pool_t pool; + + /* System environment */ + const char *hostname; + const char *domainname; + const char *base_dir; + const char *temp_dir; + + /* User environment */ + const char *username; + const char *home_dir; + + /* Flags */ + enum sieve_flag flags; + + /* Callbacks */ + const struct sieve_callbacks *callbacks; + void *context; + + /* Logging, events, and debug */ + struct event *event; + bool debug; + + /* Extension registry */ + struct sieve_extension_registry *ext_reg; + + /* Storage class registry */ + struct sieve_storage_class_registry *storage_reg; + + /* Plugin modules */ + struct sieve_plugin *plugins; + enum sieve_env_location env_location; + enum sieve_delivery_phase delivery_phase; + + /* Settings */ + size_t max_script_size; + unsigned int max_actions; + unsigned int max_redirects; + unsigned int max_cpu_time_secs; + unsigned int resource_usage_timeout_secs; + const struct smtp_address *user_email, *user_email_implicit; + struct sieve_address_source redirect_from; + unsigned int redirect_duplicate_period; +}; + +/* + * Script trace log + */ + +void sieve_trace_log_write_line + (struct sieve_trace_log *trace_log, const string_t *line) + ATTR_NULL(2); + +/* + * User e-mail address + */ + +const struct smtp_address *sieve_get_user_email + (struct sieve_instance *svinst); + +/* + * Postmaster address + */ + +const struct message_address * +sieve_get_postmaster(const struct sieve_script_env *senv); +const struct smtp_address * +sieve_get_postmaster_smtp(const struct sieve_script_env *senv); +const char * +sieve_get_postmaster_address(const struct sieve_script_env *senv); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-comparators.c b/pigeonhole/src/lib-sieve/sieve-comparators.c new file mode 100644 index 0000000..56c33ab --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-comparators.c @@ -0,0 +1,260 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" +#include "hash.h" +#include "array.h" + +#include "sieve-extensions.h" +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-binary.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "sieve-comparators.h" + +#include <string.h> +#include <stdio.h> + +/* + * Core comparators + */ + +const struct sieve_comparator_def *sieve_core_comparators[] = { + &i_octet_comparator, &i_ascii_casemap_comparator +}; + +const unsigned int sieve_core_comparators_count = + N_ELEMENTS(sieve_core_comparators); + +/* + * Comparator 'extension' + */ + +static bool cmp_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def comparator_extension = { + .name = "@comparators", + .validator_load = cmp_validator_load +}; + +/* + * Validator context: + * name-based comparator registry. + */ + +static struct sieve_validator_object_registry *_get_object_registry +(struct sieve_validator *valdtr) +{ + struct sieve_instance *svinst; + const struct sieve_extension *mcht_ext; + + svinst = sieve_validator_svinst(valdtr); + mcht_ext = sieve_get_comparator_extension(svinst); + return sieve_validator_object_registry_get(valdtr, mcht_ext); +} + +void sieve_comparator_register +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + const struct sieve_comparator_def *cmp) +{ + struct sieve_validator_object_registry *regs = _get_object_registry(valdtr); + + sieve_validator_object_registry_add(regs, ext, &cmp->obj_def); +} + +static struct sieve_comparator *sieve_comparator_create +(struct sieve_validator *valdtr, struct sieve_command *cmd, + const char *identifier) +{ + struct sieve_validator_object_registry *regs = _get_object_registry(valdtr); + struct sieve_object object; + struct sieve_comparator *cmp; + + if ( !sieve_validator_object_registry_find(regs, identifier, &object) ) + return NULL; + + cmp = p_new(sieve_command_pool(cmd), struct sieve_comparator, 1); + cmp->object = object; + cmp->def = (const struct sieve_comparator_def *) object.def; + + return cmp; +} + +bool cmp_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + struct sieve_validator_object_registry *regs = + sieve_validator_object_registry_init(valdtr, ext); + unsigned int i; + + /* Register core comparators */ + for ( i = 0; i < sieve_core_comparators_count; i++ ) { + sieve_validator_object_registry_add + (regs, NULL, &(sieve_core_comparators[i]->obj_def)); + } + + return TRUE; +} + +/* + * Comparator tagged argument + */ + +/* Forward declarations */ + +static bool tag_comparator_validate + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool tag_comparator_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd); + +/* Argument object */ + +const struct sieve_argument_def comparator_tag = { + .identifier = "comparator", + .validate = tag_comparator_validate, + .generate = tag_comparator_generate +}; + +/* Argument implementation */ + +static bool tag_comparator_validate +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + const struct sieve_comparator *cmp; + + /* Skip tag */ + *arg = sieve_ast_argument_next(*arg); + + /* Check syntax: + * ":comparator" <comparator-name: string> + */ + if ( !sieve_validate_tag_parameter + (valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING, FALSE) ) { + return FALSE; + } + + /* FIXME: We can currently only handle string literal argument, so + * variables are not allowed. + */ + if ( !sieve_argument_is_string_literal(*arg) ) { + sieve_argument_validate_error(valdtr, *arg, + "this Sieve implementation currently only supports " + "a literal string argument for the :comparator tag"); + return FALSE; + } + + /* Get comparator from registry */ + cmp = sieve_comparator_create(valdtr, cmd, sieve_ast_argument_strc(*arg)); + + if ( cmp == NULL ) { + sieve_argument_validate_error(valdtr, *arg, + "unknown comparator '%s'", + str_sanitize(sieve_ast_argument_strc(*arg),80)); + + return FALSE; + } + + /* String argument not needed during code generation, so detach it from + * argument list + */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + /* Store comparator in context */ + tag->argument->data = (void *) cmp; + + return TRUE; +} + +static bool tag_comparator_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + const struct sieve_comparator *cmp = + (const struct sieve_comparator *) arg->argument->data; + + sieve_opr_comparator_emit(cgenv->sblock, cmp); + + return TRUE; +} + +/* Functions to enable and evaluate comparator tag for commands */ + +void sieve_comparators_link_tag +(struct sieve_validator *valdtr, struct sieve_command_registration *cmd_reg, + int id_code) +{ + struct sieve_instance *svinst; + const struct sieve_extension *mcht_ext; + + svinst = sieve_validator_svinst(valdtr); + mcht_ext = sieve_get_comparator_extension(svinst); + + sieve_validator_register_tag + (valdtr, cmd_reg, mcht_ext, &comparator_tag, id_code); +} + +bool sieve_comparator_tag_is +(struct sieve_ast_argument *tag, const struct sieve_comparator_def *cmp_def) +{ + const struct sieve_comparator *cmp; + + if ( !sieve_argument_is(tag, comparator_tag) ) + return FALSE; + + cmp = (const struct sieve_comparator *) tag->argument->data; + + return ( cmp->def == cmp_def ); +} + +const struct sieve_comparator *sieve_comparator_tag_get +(struct sieve_ast_argument *tag) +{ + if ( !sieve_argument_is(tag, comparator_tag) ) + return NULL; + + + return (const struct sieve_comparator *) tag->argument->data; +} + +/* + * Comparator coding + */ + +const struct sieve_operand_class sieve_comparator_operand_class = + { "comparator" }; + +static const struct sieve_extension_objects core_comparators = + SIEVE_EXT_DEFINE_COMPARATORS(sieve_core_comparators); + +const struct sieve_operand_def comparator_operand = { + .name = "comparator", + .code = SIEVE_OPERAND_COMPARATOR, + .class = &sieve_comparator_operand_class, + .interface = &core_comparators +}; + +/* + * Trivial/Common comparator method implementations + */ + +bool sieve_comparator_octet_skip + (const struct sieve_comparator *cmp ATTR_UNUSED, + const char **val, const char *val_end) +{ + if ( *val < val_end ) { + (*val)++; + return TRUE; + } + + return FALSE; +} diff --git a/pigeonhole/src/lib-sieve/sieve-comparators.h b/pigeonhole/src/lib-sieve/sieve-comparators.h new file mode 100644 index 0000000..fdfb9ee --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-comparators.h @@ -0,0 +1,153 @@ +#ifndef SIEVE_COMPARATORS_H +#define SIEVE_COMPARATORS_H + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-objects.h" +#include "sieve-code.h" + +/* + * Core comparators + */ + +enum sieve_comparator_code { + SIEVE_COMPARATOR_I_OCTET, + SIEVE_COMPARATOR_I_ASCII_CASEMAP, + SIEVE_COMPARATOR_CUSTOM +}; + +extern const struct sieve_comparator_def i_octet_comparator; +extern const struct sieve_comparator_def i_ascii_casemap_comparator; + +/* + * Comparator flags + */ + +enum sieve_comparator_flags { + SIEVE_COMPARATOR_FLAG_ORDERING = (1 << 0), + SIEVE_COMPARATOR_FLAG_EQUALITY = (1 << 1), + SIEVE_COMPARATOR_FLAG_PREFIX_MATCH = (1 << 2), + SIEVE_COMPARATOR_FLAG_SUBSTRING_MATCH = (1 << 3), +}; + +/* + * Comparator definition + */ + +struct sieve_comparator_def { + struct sieve_object_def obj_def; + + unsigned int flags; + + /* Equality and ordering */ + + int (*compare)(const struct sieve_comparator *cmp, + const char *val1, size_t val1_size, + const char *val2, size_t val2_size); + + /* Prefix and substring match */ + + bool (*char_match)(const struct sieve_comparator *cmp, + const char **val, const char *val_end, + const char **key, const char *key_end); + bool (*char_skip)(const struct sieve_comparator *cmp, + const char **val, const char *val_end); +}; + +/* + * Comparator instance + */ + +struct sieve_comparator { + struct sieve_object object; + + const struct sieve_comparator_def *def; +}; + +#define SIEVE_COMPARATOR_DEFAULT(definition) \ + { SIEVE_OBJECT_DEFAULT(definition), &(definition) } + +#define sieve_comparator_name(cmp) \ + ( (cmp)->object.def->identifier ) +#define sieve_comparator_is(cmp, definition) \ + ( (cmp)->def == &(definition) ) + +static inline const struct sieve_comparator *sieve_comparator_copy +(pool_t pool, const struct sieve_comparator *cmp_orig) +{ + struct sieve_comparator *cmp = p_new(pool, struct sieve_comparator, 1); + + *cmp = *cmp_orig; + + return cmp; +} + +/* + * Comparator tagged argument + */ + +extern const struct sieve_argument_def comparator_tag; + +static inline bool sieve_argument_is_comparator +(struct sieve_ast_argument *arg) +{ + return ( arg->argument != NULL && + (arg->argument->def == &comparator_tag) ); +} + +void sieve_comparators_link_tag + (struct sieve_validator *validator, + struct sieve_command_registration *cmd_reg, int id_code); +bool sieve_comparator_tag_is + (struct sieve_ast_argument *tag, const struct sieve_comparator_def *cmp); +const struct sieve_comparator *sieve_comparator_tag_get + (struct sieve_ast_argument *tag); + +void sieve_comparator_register + (struct sieve_validator *validator, const struct sieve_extension *ext, + const struct sieve_comparator_def *cmp); + +/* + * Comparator operand + */ + +#define SIEVE_EXT_DEFINE_COMPARATOR(OP) SIEVE_EXT_DEFINE_OBJECT(OP) +#define SIEVE_EXT_DEFINE_COMPARATORS(OPS) SIEVE_EXT_DEFINE_OBJECTS(OPS) + +extern const struct sieve_operand_class sieve_comparator_operand_class; +extern const struct sieve_operand_def comparator_operand; + +static inline void sieve_opr_comparator_emit +(struct sieve_binary_block *sblock, const struct sieve_comparator *cmp) +{ + sieve_opr_object_emit(sblock, cmp->object.ext, cmp->object.def); +} +static inline bool sieve_opr_comparator_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + return sieve_opr_object_dump + (denv, &sieve_comparator_operand_class, address, NULL); +} + +static inline int sieve_opr_comparator_read +(const struct sieve_runtime_env *renv, sieve_size_t *address, + struct sieve_comparator *cmp) +{ + if ( !sieve_opr_object_read + (renv, &sieve_comparator_operand_class, address, &cmp->object) ) + return SIEVE_EXEC_BIN_CORRUPT; + + cmp->def = (const struct sieve_comparator_def *) cmp->object.def; + return SIEVE_EXEC_OK; +} + +/* + * Trivial/Common comparator method implementations + */ + +bool sieve_comparator_octet_skip + (const struct sieve_comparator *cmp ATTR_UNUSED, + const char **val, const char *val_end); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-config.h b/pigeonhole/src/lib-sieve/sieve-config.h new file mode 100644 index 0000000..a0fed7c --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-config.h @@ -0,0 +1,16 @@ +#ifndef SIEVE_CONFIG_H +#define SIEVE_CONFIG_H + +#include "pigeonhole-config.h" +#include "pigeonhole-version.h" + +#define SIEVE_IMPLEMENTATION PIGEONHOLE_NAME " Sieve " PIGEONHOLE_VERSION_FULL + +#define SIEVE_SCRIPT_FILEEXT "sieve" +#define SIEVE_BINARY_FILEEXT "svbin" + +#define DEFAULT_ENVELOPE_SENDER "MAILER-DAEMON" + +#define DEFAULT_REDIRECT_DUPLICATE_PERIOD (3600 * 12) + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-dump.h b/pigeonhole/src/lib-sieve/sieve-dump.h new file mode 100644 index 0000000..d704877 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-dump.h @@ -0,0 +1,30 @@ +#ifndef SIEVE_DUMP_H +#define SIEVE_DUMP_H + +#include "sieve-common.h" +#include "sieve-code-dumper.h" +#include "sieve-binary-dumper.h" + +/* + * Dumptime environment + */ + +struct sieve_dumptime_env { + /* Dumpers */ + struct sieve_instance *svinst; + struct sieve_binary_dumper *dumper; + struct sieve_code_dumper *cdumper; + + /* Binary */ + struct sieve_binary *sbin; + struct sieve_binary_block *sblock; + + /* Code position */ + const struct sieve_operation *oprtn; + sieve_size_t offset; + + /* Output stream */ + struct ostream *stream; +}; + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-error-private.h b/pigeonhole/src/lib-sieve/sieve-error-private.h new file mode 100644 index 0000000..e0172b2 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-error-private.h @@ -0,0 +1,67 @@ +#ifndef SIEVE_ERROR_PRIVATE_H +#define SIEVE_ERROR_PRIVATE_H + +#include "sieve-error.h" + +/* + * Initialization + */ + +void sieve_errors_init(struct sieve_instance *svinst); +void sieve_errors_deinit(struct sieve_instance *svinst); + +/* + * Error handler object + */ + +struct sieve_error_handler { + pool_t pool; + int refcount; + + struct sieve_instance *svinst; + + unsigned int max_errors; + + unsigned int errors; + unsigned int warnings; + + void (*log)(struct sieve_error_handler *ehandler, + const struct sieve_error_params *params, + enum sieve_error_flags flags, + const char *message); + + void (*free)(struct sieve_error_handler *ehandler); + + bool master_log:1; /* this logs through master log facility */ + bool log_info:1; /* handle or discard info log */ + bool log_debug:1; /* handle or discard debug log */ +}; + +void sieve_error_handler_init(struct sieve_error_handler *ehandler, + struct sieve_instance *svinst, pool_t pool, + unsigned int max_errors); + +/* + * Direct handler calls + */ + +void sieve_direct_logv(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const struct sieve_error_params *params, + enum sieve_error_flags flags, + const char *fmt, va_list args) ATTR_FORMAT(5, 0); + +static inline void ATTR_FORMAT(5, 6) +sieve_direct_log(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const struct sieve_error_params *params, + enum sieve_error_flags flags, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + sieve_direct_logv(svinst, ehandler, params, flags, fmt, args); + va_end(args); +} + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-error.c b/pigeonhole/src/lib-sieve/sieve-error.c new file mode 100644 index 0000000..aae13a5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-error.c @@ -0,0 +1,1064 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "array.h" +#include "ostream.h" +#include "var-expand.h" +#include "eacces-error.h" + +#include "sieve-common.h" +#include "sieve-script.h" +#include "sieve-error-private.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <ctype.h> + +/* + * Definitions + */ + +#define CRITICAL_MSG \ + "internal error occurred: refer to server log for more information." +#define CRITICAL_MSG_STAMP CRITICAL_MSG " [%Y-%m-%d %H:%M:%S]" + +/* Logfile error handler will rotate log when it exceeds 10k bytes */ +#define LOGFILE_MAX_SIZE (10 * 1024) + +/* + * Utility + */ + +const char * +sieve_error_script_location(const struct sieve_script *script, + unsigned int source_line) +{ + const char *sname; + + sname = (script == NULL ? NULL : sieve_script_name(script)); + + if (sname == NULL || *sname == '\0') { + if (source_line == 0) + return NULL; + + return t_strdup_printf("line %d", source_line); + } + + if (source_line == 0) + return sname; + + return t_strdup_printf("%s: line %d", sname, source_line); +} + +const char *sieve_error_from_external(const char *msg) +{ + char *new_msg; + + if (msg == NULL || *msg == '\0') + return msg; + + new_msg = t_strdup_noconst(msg); + new_msg[0] = i_tolower(new_msg[0]); + + return new_msg; +} + +/* + * Initialization + */ + +void sieve_errors_init(struct sieve_instance *svinst ATTR_UNUSED) +{ + /* nothing */ +} + +void sieve_errors_deinit(struct sieve_instance *svinst ATTR_UNUSED) +{ + /* nothing */ +} + +/* + * Direct handler calls + */ + +static void +sieve_direct_master_log(struct sieve_instance *svinst, + const struct sieve_error_params *params, + const char *message) +{ + struct event_log_params event_params = { + .log_type = params->log_type, + .source_filename = params->csrc.filename, + .source_linenum = params->csrc.linenum, + + .base_event = svinst->event, + }; + struct event *event = (params->event != NULL ? + params->event : svinst->event); + + if (params->location != NULL && *params->location != '\0') { + event_params.base_send_prefix = + t_strconcat(params->location, ": ", NULL); + } + + event_log(event, &event_params, "%s", message); +} + +void sieve_direct_logv(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const struct sieve_error_params *params, + enum sieve_error_flags flags, + const char *fmt, va_list args) +{ + struct event_log_params event_params = { + .log_type = params->log_type, + .source_filename = params->csrc.filename, + .source_linenum = params->csrc.linenum, + .base_event = svinst->event, + .base_str_out = NULL, + .no_send = TRUE, + }; + struct event *event = (params->event != NULL ? + params->event : svinst->event); + bool event_log = FALSE, ehandler_log = FALSE; + + if (ehandler != NULL) { + switch (params->log_type) { + case LOG_TYPE_ERROR: + ehandler_log = sieve_errors_more_allowed(ehandler); + break; + case LOG_TYPE_WARNING: + ehandler_log = TRUE; + break; + case LOG_TYPE_INFO: + ehandler_log = ehandler->log_info; + break; + case LOG_TYPE_DEBUG: + ehandler_log = ehandler->log_debug; + break; + case LOG_TYPE_FATAL: + case LOG_TYPE_PANIC: + case LOG_TYPE_COUNT: + case LOG_TYPE_OPTION: + i_unreached(); + } + } + + if (ehandler != NULL && ehandler->master_log) { + event_log = ehandler_log; + ehandler_log = FALSE; + } + if ((flags & SIEVE_ERROR_FLAG_GLOBAL) != 0) { + event_log = TRUE; + if ((flags & SIEVE_ERROR_FLAG_GLOBAL_MAX_INFO) != 0 && + params->log_type > LOG_TYPE_INFO) + event_params.log_type = LOG_TYPE_INFO; + } + + if (event_log) { + event_params.no_send = FALSE; + if (params->location != NULL && *params->location != '\0') { + event_params.base_send_prefix = + t_strconcat(params->location, ": ", NULL); + } + } + if (ehandler_log) { + if (ehandler->log == NULL) + ehandler_log = FALSE; + else + event_params.base_str_out = t_str_new(128); + } + + if (event_log || ehandler_log) + event_logv(event, &event_params, fmt, args); + + if (ehandler_log) { + ehandler->log(ehandler, params, flags, + str_c(event_params.base_str_out)); + } + + if (ehandler != NULL && ehandler->pool != NULL) { + switch (params->log_type) { + case LOG_TYPE_ERROR: + ehandler->errors++; + break; + case LOG_TYPE_WARNING: + ehandler->warnings++; + break; + default: + break; + } + } +} + +/* + * User errors + */ + +void sieve_global_logv(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const struct sieve_error_params *params, + const char *fmt, va_list args) +{ + sieve_direct_logv(svinst, ehandler, params, + SIEVE_ERROR_FLAG_GLOBAL, fmt, args); +} + +void sieve_global_info_logv(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const struct sieve_error_params *params, + const char *fmt, va_list args) +{ + sieve_direct_logv(svinst, ehandler, params, + (SIEVE_ERROR_FLAG_GLOBAL | + SIEVE_ERROR_FLAG_GLOBAL_MAX_INFO), fmt, args); +} + +#undef sieve_global_error +void sieve_global_error(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_ERROR, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + .location = location, + }; + va_list args; + va_start(args, fmt); + + T_BEGIN { + sieve_global_logv(svinst, ehandler, ¶ms, fmt, args); + } T_END; + + va_end(args); +} + +#undef sieve_global_warning +void sieve_global_warning(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_WARNING, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + .location = location, + }; + va_list args; + va_start(args, fmt); + + T_BEGIN { + sieve_global_logv(svinst, ehandler, ¶ms, fmt, args); + } T_END; + + va_end(args); +} + +#undef sieve_global_info +void sieve_global_info(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_INFO, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + .location = location, + }; + va_list args; + va_start(args, fmt); + + T_BEGIN { + sieve_global_logv(svinst, ehandler, ¶ms, fmt, args); + } T_END; + + va_end(args); +} + +#undef sieve_global_info_error +void sieve_global_info_error(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const char *csrc_filename, + unsigned int csrc_linenum, + const char *location, const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_ERROR, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + .location = location, + }; + va_list args; + va_start(args, fmt); + + T_BEGIN { + sieve_global_info_logv(svinst, ehandler, ¶ms, fmt, args); + } T_END; + + va_end(args); +} + +#undef sieve_global_info_warning +void sieve_global_info_warning(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const char *csrc_filename, + unsigned int csrc_linenum, + const char *location, const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_WARNING, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + .location = location, + }; + va_list args; + va_start(args, fmt); + + T_BEGIN { + sieve_global_info_logv(svinst, ehandler, ¶ms, fmt, args); + } T_END; + + va_end(args); +} + +/* + * Default (user) error functions + */ + +void sieve_internal_error_params(struct sieve_error_handler *ehandler, + const struct sieve_error_params *params, + const char *user_prefix) +{ + char str[256]; + const char *msg; + struct tm *tm; + + if (ehandler == NULL || ehandler->master_log) + return; + + tm = localtime(&ioloop_time); + msg = (strftime(str, sizeof(str), CRITICAL_MSG_STAMP, tm) > 0 ? + str : CRITICAL_MSG); + + if (user_prefix == NULL || *user_prefix == '\0') { + sieve_direct_log(ehandler->svinst, ehandler, params, 0, + "%s", msg); + } else { + sieve_direct_log(ehandler->svinst, ehandler, params, 0, + "%s: %s", user_prefix, msg); + } +} + +#undef sieve_internal_error +void sieve_internal_error(struct sieve_error_handler *ehandler, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *user_prefix) + +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_ERROR, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + .location = location, + }; + + sieve_internal_error_params(ehandler, ¶ms, user_prefix); +} + +void sieve_logv(struct sieve_error_handler *ehandler, + const struct sieve_error_params *params, + const char *fmt, va_list args) +{ + if (ehandler == NULL) return; + + sieve_direct_logv(ehandler->svinst, ehandler, params, 0, fmt, args); +} + +void sieve_event_logv(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + struct event *event, enum log_type log_type, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, enum sieve_error_flags flags, + const char *fmt, va_list args) +{ + struct sieve_error_params params = { + .log_type = log_type, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + .event = event, + .location = location, + }; + + T_BEGIN { + sieve_direct_logv(svinst, ehandler, ¶ms, flags, fmt, args); + } T_END; +} + + +#undef sieve_event_log +void sieve_event_log(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + struct event *event, enum log_type log_type, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, enum sieve_error_flags flags, + const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + + sieve_event_logv(svinst, ehandler, event, log_type, csrc_filename, + csrc_linenum, location, flags, fmt, args); + + va_end(args); +} + +void sieve_criticalv(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const struct sieve_error_params *params, + const char *user_prefix, const char *fmt, va_list args) +{ + struct sieve_error_params new_params = *params; + + new_params.log_type = LOG_TYPE_ERROR; + + sieve_direct_master_log(svinst, &new_params, + t_strdup_vprintf(fmt, args)); + sieve_internal_error_params(ehandler, &new_params, user_prefix); +} + +#undef sieve_error +void sieve_error(struct sieve_error_handler *ehandler, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_ERROR, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + .location = location, + }; + va_list args; + va_start(args, fmt); + + T_BEGIN { + sieve_logv(ehandler, ¶ms, fmt, args); + } T_END; + + va_end(args); +} + +#undef sieve_warning +void sieve_warning(struct sieve_error_handler *ehandler, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_WARNING, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + .location = location, + }; + va_list args; + va_start(args, fmt); + + T_BEGIN { + sieve_logv(ehandler, ¶ms, fmt, args); + } T_END; + + va_end(args); +} + +#undef sieve_info +void sieve_info(struct sieve_error_handler *ehandler, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_INFO, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + .location = location, + }; + va_list args; + va_start(args, fmt); + + T_BEGIN { + sieve_logv(ehandler, ¶ms, fmt, args); + } T_END; + + va_end(args); +} + +#undef sieve_debug +void sieve_debug(struct sieve_error_handler *ehandler, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_DEBUG, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + .location = location, + }; + va_list args; + va_start(args, fmt); + + T_BEGIN { + sieve_logv(ehandler, ¶ms, fmt, args); + } T_END; + + va_end(args); +} + +#undef sieve_critical +void sieve_critical(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *user_prefix, + const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_ERROR, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + .location = location, + }; + va_list args; + + va_start(args, fmt); + + T_BEGIN { + sieve_criticalv(svinst, ehandler, ¶ms, user_prefix, + fmt, args); + } T_END; + + va_end(args); +} + +/* + * Error statistics + */ + +unsigned int sieve_get_errors(struct sieve_error_handler *ehandler) +{ + if (ehandler == NULL || ehandler->pool == NULL) + return 0; + + return ehandler->errors; +} + +unsigned int sieve_get_warnings(struct sieve_error_handler *ehandler) +{ + if (ehandler == NULL || ehandler->pool == NULL) + return 0; + + return ehandler->warnings; +} + +bool sieve_errors_more_allowed(struct sieve_error_handler *ehandler) +{ + if (ehandler == NULL || ehandler->pool == NULL) + return TRUE; + + return (ehandler->max_errors == 0 || + ehandler->errors < ehandler->max_errors); +} + +/* + * Error handler configuration + */ + +void sieve_error_handler_accept_infolog(struct sieve_error_handler *ehandler, + bool enable) +{ + ehandler->log_info = enable; +} + +void sieve_error_handler_accept_debuglog(struct sieve_error_handler *ehandler, + bool enable) +{ + ehandler->log_debug = enable; +} + +/* + * Error handler init + */ + +void sieve_error_handler_init(struct sieve_error_handler *ehandler, + struct sieve_instance *svinst, + pool_t pool, unsigned int max_errors) +{ + ehandler->pool = pool; + ehandler->svinst = svinst; + ehandler->refcount = 1; + ehandler->max_errors = max_errors; + + ehandler->errors = 0; + ehandler->warnings = 0; +} + +void sieve_error_handler_ref(struct sieve_error_handler *ehandler) +{ + if (ehandler == NULL || ehandler->pool == NULL) + return; + + ehandler->refcount++; +} + +void sieve_error_handler_unref(struct sieve_error_handler **ehandler) +{ + if (*ehandler == NULL || (*ehandler)->pool == NULL) + return; + + i_assert((*ehandler)->refcount > 0); + + if (--(*ehandler)->refcount != 0) + return; + + if ((*ehandler)->free != NULL) + (*ehandler)->free(*ehandler); + + pool_unref(&((*ehandler)->pool)); + *ehandler = NULL; +} + +void sieve_error_handler_reset(struct sieve_error_handler *ehandler) +{ + if (ehandler == NULL || ehandler->pool == NULL) + return; + + ehandler->errors = 0; + ehandler->warnings = 0; +} + +/* + * Error params utility + */ + +static void +sieve_error_params_add_prefix(struct sieve_error_handler *ehandler ATTR_UNUSED, + const struct sieve_error_params *params, + string_t *prefix) +{ + if (params->location != NULL && *params->location != '\0') { + str_append(prefix, params->location); + str_append(prefix, ": "); + } + + switch (params->log_type) { + case LOG_TYPE_ERROR: + str_append(prefix, "error: "); + break; + case LOG_TYPE_WARNING: + str_append(prefix, "warning: "); + break; + case LOG_TYPE_INFO: + str_append(prefix, "info: "); + break; + case LOG_TYPE_DEBUG: + str_append(prefix, "debug: "); + break; + default: + i_unreached(); + } +} + +/* + * Master/System error handler + * + * - Output errors directly to Dovecot master log + */ + +struct sieve_error_handler * +sieve_master_ehandler_create(struct sieve_instance *svinst, + unsigned int max_errors) +{ + struct sieve_error_handler *ehandler; + pool_t pool; + + pool = pool_alloconly_create("master_error_handler", 256); + ehandler = p_new(pool, struct sieve_error_handler, 1); + sieve_error_handler_init(ehandler, svinst, pool, max_errors); + ehandler->master_log = TRUE; + ehandler->log_debug = svinst->debug; + + return ehandler; +} + +/* + * STDERR error handler + * + * - Output errors directly to stderror + */ + +static void +sieve_stderr_log(struct sieve_error_handler *ehandler, + const struct sieve_error_params *params, + enum sieve_error_flags flags ATTR_UNUSED, + const char *message) +{ + string_t *prefix = t_str_new(64); + + sieve_error_params_add_prefix(ehandler, params, prefix); + + fprintf(stderr, "%s%s.\n", str_c(prefix), message); +} + +struct sieve_error_handler * +sieve_stderr_ehandler_create(struct sieve_instance *svinst, + unsigned int max_errors) +{ + pool_t pool; + struct sieve_error_handler *ehandler; + + /* Pool is not strictly necessary, but other handler types will need + * a pool, so this one will have one too. + */ + pool = pool_alloconly_create("stderr_error_handler", + sizeof(struct sieve_error_handler)); + ehandler = p_new(pool, struct sieve_error_handler, 1); + sieve_error_handler_init(ehandler, svinst, pool, max_errors); + + ehandler->log = sieve_stderr_log; + + return ehandler; +} + +/* String buffer error handler + * + * - Output errors to a string buffer + */ + +struct sieve_strbuf_ehandler { + struct sieve_error_handler handler; + + string_t *errors; + bool crlf; +}; + +static void +sieve_strbuf_log(struct sieve_error_handler *ehandler, + const struct sieve_error_params *params, + enum sieve_error_flags flags ATTR_UNUSED, const char *message) +{ + struct sieve_strbuf_ehandler *handler = + (struct sieve_strbuf_ehandler *) ehandler; + + sieve_error_params_add_prefix(ehandler, params, handler->errors); + str_append(handler->errors, message); + + if (!handler->crlf) + str_append(handler->errors, ".\n"); + else + str_append(handler->errors, ".\r\n"); +} + +struct sieve_error_handler * +sieve_strbuf_ehandler_create(struct sieve_instance *svinst, string_t *strbuf, + bool crlf, unsigned int max_errors) +{ + pool_t pool; + struct sieve_strbuf_ehandler *ehandler; + + pool = pool_alloconly_create("strbuf_error_handler", 256); + ehandler = p_new(pool, struct sieve_strbuf_ehandler, 1); + ehandler->errors = strbuf; + + sieve_error_handler_init(&ehandler->handler, svinst, pool, max_errors); + + ehandler->handler.log = sieve_strbuf_log; + ehandler->crlf = crlf; + + return &(ehandler->handler); +} + +/* + * Logfile error handler + * + * - Output errors to a log file + */ + +struct sieve_logfile_ehandler { + struct sieve_error_handler handler; + + const char *logfile; + bool started; + int fd; + struct ostream *stream; +}; + +static void +sieve_logfile_write(struct sieve_logfile_ehandler *ehandler, + const struct sieve_error_params *params, + const char *message) +{ + string_t *outbuf; + ssize_t ret = 0, remain; + const char *data; + + if (ehandler->stream == NULL) + return; + + T_BEGIN { + outbuf = t_str_new(256); + sieve_error_params_add_prefix(&ehandler->handler, + params, outbuf); + str_append(outbuf, message); + str_append(outbuf, ".\n"); + + remain = str_len(outbuf); + data = (const char *) str_data(outbuf); + + while (remain > 0) { + if ((ret = o_stream_send(ehandler->stream, + data, remain)) < 0) + break; + + remain -= ret; + data += ret; + } + } T_END; + + if (ret < 0) { + e_error(ehandler->handler.svinst->event, + "o_stream_send() failed on logfile %s: %m", + ehandler->logfile); + } +} + +inline static void ATTR_FORMAT(5, 6) +sieve_logfile_printf(struct sieve_logfile_ehandler *ehandler, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_INFO, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + .location = location, + }; + va_list args; + va_start(args, fmt); + + sieve_logfile_write(ehandler, ¶ms, t_strdup_vprintf(fmt, args)); + + va_end(args); +} + +static void sieve_logfile_start(struct sieve_logfile_ehandler *ehandler) +{ + struct sieve_instance *svinst = ehandler->handler.svinst; + struct ostream *ostream = NULL; + struct stat st; + struct tm *tm; + char buf[256]; + time_t now; + int fd; + + /* Open the logfile */ + + fd = open(ehandler->logfile, O_CREAT | O_APPEND | O_WRONLY, 0600); + if (fd == -1) { + if (errno == EACCES) { + e_error(svinst->event, + "failed to open logfile " + "(LOGGING TO STDERR): %s", + eacces_error_get_creating("open", + ehandler->logfile)); + } else { + e_error(svinst->event, "failed to open logfile " + "(LOGGING TO STDERR): " + "open(%s) failed: %m", ehandler->logfile); + } + fd = STDERR_FILENO; + } else { + /* fd_close_on_exec(fd, TRUE); Necessary? */ + + /* Stat the log file to obtain size information */ + if (fstat(fd, &st) != 0) { + e_error(svinst->event, "failed to stat logfile " + "(logging to STDERR): " + "fstat(fd=%s) failed: %m", ehandler->logfile); + + if (close(fd) < 0) { + e_error(svinst->event, + "failed to close logfile after error: " + "close(fd=%s) failed: %m", + ehandler->logfile); + } + + fd = STDERR_FILENO; + } + + /* Rotate log when it has grown too large */ + if (st.st_size >= LOGFILE_MAX_SIZE) { + const char *rotated; + + /* Close open file */ + if (close(fd) < 0) { + e_error(svinst->event, + "failed to close logfile: " + "close(fd=%s) failed: %m", + ehandler->logfile); + } + + /* Rotate logfile */ + rotated = t_strconcat(ehandler->logfile, ".0", NULL); + if (rename(ehandler->logfile, rotated) < 0 && + errno != ENOENT) { + if (errno == EACCES) { + const char *target = + t_strconcat(ehandler->logfile, + ", ", rotated, NULL); + e_error(svinst->event, + "failed to rotate logfile: %s", + eacces_error_get_creating( + "rename", target)); + } else { + e_error(svinst->event, + "failed to rotate logfile: " + "rename(%s, %s) failed: %m", + ehandler->logfile, rotated); + } + } + + /* Open clean logfile (overwrites existing if rename() failed earlier) */ + fd = open(ehandler->logfile, + O_CREAT | O_APPEND | O_WRONLY | O_TRUNC, 0600); + if (fd == -1) { + if (errno == EACCES) { + e_error(svinst->event, + "failed to open logfile " + "(LOGGING TO STDERR): %s", + eacces_error_get_creating( + "open", ehandler->logfile)); + } else { + e_error(svinst->event, + "failed to open logfile " + "(LOGGING TO STDERR): " + "open(%s) failed: %m", + ehandler->logfile); + } + fd = STDERR_FILENO; + } + } + } + + ostream = o_stream_create_fd(fd, 0); + if (ostream == NULL) { + /* Can't we do anything else in this most awkward situation? */ + e_error(svinst->event, + "failed to open log stream on open file: " + "o_stream_create_fd(fd=%s) failed " + "(non-critical messages are not logged!)", + ehandler->logfile); + } + + ehandler->fd = fd; + ehandler->stream = ostream; + ehandler->started = TRUE; + + if (ostream != NULL) { + now = time(NULL); + tm = localtime(&now); + + if (strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %z", tm) > 0) { + sieve_logfile_printf(ehandler, __FILE__, __LINE__, + "sieve", "started log at %s", buf); + } + } +} + +static void +sieve_logfile_log(struct sieve_error_handler *ehandler, + const struct sieve_error_params *params, + enum sieve_error_flags flags ATTR_UNUSED, + const char *message) +{ + struct sieve_logfile_ehandler *handler = + (struct sieve_logfile_ehandler *) ehandler; + + if (!handler->started) + sieve_logfile_start(handler); + + sieve_logfile_write(handler, params, message); +} + +static void sieve_logfile_free(struct sieve_error_handler *ehandler) +{ + struct sieve_logfile_ehandler *handler = + (struct sieve_logfile_ehandler *) ehandler; + + if (handler->stream != NULL) { + o_stream_destroy(&(handler->stream)); + if (handler->fd != STDERR_FILENO) { + if (close(handler->fd) < 0) { + e_error(ehandler->svinst->event, + "failed to close logfile: " + "close(fd=%s) failed: %m", + handler->logfile); + } + } + } +} + +struct sieve_error_handler * +sieve_logfile_ehandler_create(struct sieve_instance *svinst, + const char *logfile, unsigned int max_errors) +{ + pool_t pool; + struct sieve_logfile_ehandler *ehandler; + + pool = pool_alloconly_create("logfile_error_handler", 512); + ehandler = p_new(pool, struct sieve_logfile_ehandler, 1); + sieve_error_handler_init(&ehandler->handler, svinst, pool, max_errors); + + ehandler->handler.log = sieve_logfile_log; + ehandler->handler.free = sieve_logfile_free; + + /* Don't open logfile until something is actually logged. + * Let's not pullute the sieve directory with useless logfiles. + */ + ehandler->logfile = p_strdup(pool, logfile); + ehandler->started = FALSE; + ehandler->stream = NULL; + ehandler->fd = -1; + + return &(ehandler->handler); +} diff --git a/pigeonhole/src/lib-sieve/sieve-error.h b/pigeonhole/src/lib-sieve/sieve-error.h new file mode 100644 index 0000000..83b26b7 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-error.h @@ -0,0 +1,235 @@ +#ifndef SIEVE_ERROR_H +#define SIEVE_ERROR_H + +#include "lib.h" +#include "compat.h" + +#include <stdarg.h> + +/* + * Forward declarations + */ + +struct var_expand_table; + +struct sieve_instance; +struct sieve_script; +struct sieve_error_handler; + +/* + * Types + */ + +enum sieve_error_flags { + SIEVE_ERROR_FLAG_GLOBAL = (1 << 0), + SIEVE_ERROR_FLAG_GLOBAL_MAX_INFO = (1 << 1), +}; + +struct sieve_error_params { + enum log_type log_type; + struct event *event; + + /* Location log command in C source code */ + struct { + const char *filename; + unsigned int linenum; + } csrc; + + /* Location in Sieve source script */ + const char *location; +}; + +/* + * Utility + */ + +/* Converts external messages to a style that better matches Sieve user errors + */ +const char *sieve_error_from_external(const char *msg); + +/* + * Global (user+system) errors + */ + +void sieve_global_logv(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const struct sieve_error_params *params, + const char *fmt, va_list args) ATTR_FORMAT(4, 0); +void sieve_global_info_logv(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const struct sieve_error_params *params, + const char *fmt, va_list args) ATTR_FORMAT(4, 0); + +void sieve_global_error(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const char *csrc_filename, + unsigned int csrc_linenum, + const char *location, const char *fmt, ...) + ATTR_FORMAT(6, 7); +#define sieve_global_error(svinst, ehandler, ...) \ + sieve_global_error(svinst, ehandler, __FILE__, __LINE__, __VA_ARGS__) +void sieve_global_warning(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const char *csrc_filename, + unsigned int csrc_linenum, + const char *location, const char *fmt, ...) + ATTR_FORMAT(6, 7); +#define sieve_global_warning(svinst, ehandler, ...) \ + sieve_global_warning(svinst, ehandler, __FILE__, __LINE__, __VA_ARGS__) +void sieve_global_info(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const char *csrc_filename, + unsigned int csrc_linenum, + const char *location, const char *fmt, ...) + ATTR_FORMAT(6, 7); +#define sieve_global_info(svinst, ehandler, ...) \ + sieve_global_info(svinst, ehandler, __FILE__, __LINE__, __VA_ARGS__) +void sieve_global_info_error(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const char *csrc_filename, + unsigned int csrc_linenum, + const char *location, const char *fmt, ...) + ATTR_FORMAT(6, 7); +#define sieve_global_info_error(svinst, ehandler, ...) \ + sieve_global_info_error(svinst, ehandler, __FILE__, __LINE__, \ + __VA_ARGS__) +void sieve_global_info_warning(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const char *csrc_filename, + unsigned int csrc_linenum, + const char *location, const char *fmt, ...) + ATTR_FORMAT(6, 7); +#define sieve_global_info_warning(svinst, ehandler, ...) \ + sieve_global_info_warning(svinst, ehandler, __FILE__, __LINE__, \ + __VA_ARGS__) + +/* + * Main (user) error functions + */ + +/* For these functions it is the responsibility of the caller to + * manage the datastack. + */ + +const char * +sieve_error_script_location(const struct sieve_script *script, + unsigned int source_line); + +void sieve_logv(struct sieve_error_handler *ehandler, + const struct sieve_error_params *params, + const char *fmt, va_list args) ATTR_FORMAT(3, 0); + +void sieve_event_logv(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + struct event *event, enum log_type log_type, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, enum sieve_error_flags flags, + const char *fmt, va_list args) ATTR_FORMAT(9, 0); +void sieve_event_log(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + struct event *event, enum log_type log_type, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, enum sieve_error_flags flags, + const char *fmt, ...) ATTR_FORMAT(9, 10); +#define sieve_event_log(svinst, ehandler, event, log_type, ...) \ + sieve_event_log(svinst, ehandler, event, log_type, __FILE__, __LINE__, \ + __VA_ARGS__) + +void sieve_criticalv(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const struct sieve_error_params *params, + const char *user_prefix, const char *fmt, va_list args) + ATTR_FORMAT(5, 0); + +void sieve_error(struct sieve_error_handler *ehandler, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *fmt, ...) ATTR_FORMAT(5, 6); +#define sieve_error(ehandler, ...) \ + sieve_error(ehandler, __FILE__, __LINE__, __VA_ARGS__) +void sieve_warning(struct sieve_error_handler *ehandler, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *fmt, ...) + ATTR_FORMAT(5, 6); +#define sieve_warning(ehandler, ...) \ + sieve_warning(ehandler, __FILE__, __LINE__, __VA_ARGS__) +void sieve_info(struct sieve_error_handler *ehandler, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *fmt, ...) ATTR_FORMAT(5, 6); +#define sieve_info(ehandler, ...) \ + sieve_info(ehandler, __FILE__, __LINE__, __VA_ARGS__) +void sieve_debug(struct sieve_error_handler *ehandler, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *fmt, ...) ATTR_FORMAT(5, 6); +#define sieve_debug(ehandler, ...) \ + sieve_debug(ehandler, __FILE__, __LINE__, __VA_ARGS__) +void sieve_critical(struct sieve_instance *svinst, + struct sieve_error_handler *ehandler, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *user_prefix, + const char *fmt, ...) ATTR_FORMAT(7, 8); +#define sieve_critical(svinst, ehandler, ...) \ + sieve_critical(svinst, ehandler, __FILE__, __LINE__, __VA_ARGS__) + + +void sieve_internal_error_params(struct sieve_error_handler *ehandler, + const struct sieve_error_params *params, + const char *user_prefix); +void sieve_internal_error(struct sieve_error_handler *ehandler, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *user_prefix) + ATTR_NULL(1, 4, 5); +#define sieve_internal_error(ehandler, ...) \ + sieve_internal_error(ehandler, __FILE__, __LINE__, __VA_ARGS__) + +/* + * Error handler configuration + */ + +void sieve_error_handler_accept_infolog(struct sieve_error_handler *ehandler, + bool enable); +void sieve_error_handler_accept_debuglog(struct sieve_error_handler *ehandler, + bool enable); + +/* + * Error handler statistics + */ + +unsigned int sieve_get_errors(struct sieve_error_handler *ehandler); +unsigned int sieve_get_warnings(struct sieve_error_handler *ehandler); + +bool sieve_errors_more_allowed(struct sieve_error_handler *ehandler); + +/* + * Error handler object + */ + +void sieve_error_handler_ref(struct sieve_error_handler *ehandler); +void sieve_error_handler_unref(struct sieve_error_handler **ehandler); + +void sieve_error_handler_reset(struct sieve_error_handler *ehandler); + +/* + * Error handlers + */ + +/* Write errors to dovecot master log */ +struct sieve_error_handler * +sieve_master_ehandler_create(struct sieve_instance *svinst, + unsigned int max_errors); + +/* Write errors to stderr */ +struct sieve_error_handler * +sieve_stderr_ehandler_create(struct sieve_instance *svinst, + unsigned int max_errors); + +/* Write errors into a string buffer */ +struct sieve_error_handler * +sieve_strbuf_ehandler_create(struct sieve_instance *svinst, string_t *strbuf, + bool crlf, unsigned int max_errors); + +/* Write errors to a logfile */ +struct sieve_error_handler * +sieve_logfile_ehandler_create(struct sieve_instance *svinst, + const char *logfile, unsigned int max_errors); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-execute.c b/pigeonhole/src/lib-sieve/sieve-execute.c new file mode 100644 index 0000000..a395cc6 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-execute.c @@ -0,0 +1,162 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-execute.h" + +struct sieve_execute_state { + void *dup_trans; +}; + +struct event_category event_category_sieve_execute = { + .parent = &event_category_sieve, + .name = "sieve-execute", +}; + +static struct sieve_execute_state * +sieve_execute_state_create(struct sieve_execute_env *eenv) +{ + return p_new(eenv->pool, struct sieve_execute_state, 1); +} + +static void +sieve_execute_state_free(struct sieve_execute_state **_estate, + struct sieve_execute_env *eenv) +{ + struct sieve_execute_state *estate = *_estate; + const struct sieve_script_env *senv = eenv->scriptenv; + + *_estate = NULL; + + if (senv->duplicate_transaction_rollback != NULL) + senv->duplicate_transaction_rollback(&estate->dup_trans); +} + +void sieve_execute_init(struct sieve_execute_env *eenv, + struct sieve_instance *svinst, pool_t pool, + const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv, + enum sieve_execute_flags flags) +{ + i_zero(eenv); + eenv->svinst = svinst; + eenv->pool = pool; + eenv->flags = flags; + eenv->msgdata = msgdata; + eenv->scriptenv = senv; + + pool_ref(pool); + eenv->event = event_create(svinst->event); + event_add_category(eenv->event, &event_category_sieve_execute); + event_add_str(eenv->event, "message_id", msgdata->id); + if ((flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0) { + /* Make sure important envelope fields are available */ + event_add_str(eenv->event, "mail_from", + smtp_address_encode(msgdata->envelope.mail_from)); + event_add_str(eenv->event, "rcpt_to", + smtp_address_encode(msgdata->envelope.rcpt_to)); + } + + eenv->state = sieve_execute_state_create(eenv); + + eenv->exec_status = senv->exec_status; + if (eenv->exec_status == NULL) + eenv->exec_status = p_new(pool, struct sieve_exec_status, 1); + else + i_zero(eenv->exec_status); +} + +void sieve_execute_finish(struct sieve_execute_env *eenv, int status) +{ + const struct sieve_script_env *senv = eenv->scriptenv; + + if (status == SIEVE_EXEC_OK) { + if (senv->duplicate_transaction_commit != NULL) { + senv->duplicate_transaction_commit( + &eenv->state->dup_trans); + } + } else { + if (senv->duplicate_transaction_rollback != NULL) { + senv->duplicate_transaction_rollback( + &eenv->state->dup_trans); + } + } +} + +void sieve_execute_deinit(struct sieve_execute_env *eenv) +{ + sieve_execute_state_free(&eenv->state, eenv); + event_unref(&eenv->event); + pool_unref(&eenv->pool); +} + +/* + * Checking for duplicates + */ + +static void * +sieve_execute_get_dup_transaction(const struct sieve_execute_env *eenv) +{ + const struct sieve_script_env *senv = eenv->scriptenv; + + if (senv->duplicate_transaction_begin == NULL) + return NULL; + if (eenv->state->dup_trans == NULL) { + eenv->state->dup_trans = + senv->duplicate_transaction_begin(senv); + } + return eenv->state->dup_trans; +} + +bool sieve_execute_duplicate_check_available( + const struct sieve_execute_env *eenv) +{ + const struct sieve_script_env *senv = eenv->scriptenv; + + return (senv->duplicate_transaction_begin != NULL); +} + +int sieve_execute_duplicate_check(const struct sieve_execute_env *eenv, + const void *id, size_t id_size, + bool *duplicate_r) +{ + const struct sieve_script_env *senv = eenv->scriptenv; + void *dup_trans = sieve_execute_get_dup_transaction(eenv); + int ret; + + *duplicate_r = FALSE; + + if (senv->duplicate_check == NULL) + return SIEVE_EXEC_OK; + + e_debug(eenv->svinst->event, "Check duplicate ID"); + + ret = senv->duplicate_check(dup_trans, senv, id, id_size); + switch (ret) { + case SIEVE_DUPLICATE_CHECK_RESULT_EXISTS: + *duplicate_r = TRUE; + break; + case SIEVE_DUPLICATE_CHECK_RESULT_NOT_FOUND: + break; + case SIEVE_DUPLICATE_CHECK_RESULT_FAILURE: + return SIEVE_EXEC_FAILURE; + case SIEVE_DUPLICATE_CHECK_RESULT_TEMP_FAILURE: + return SIEVE_EXEC_TEMP_FAILURE; + } + return SIEVE_EXEC_OK; +} + +void sieve_execute_duplicate_mark(const struct sieve_execute_env *eenv, + const void *id, size_t id_size, time_t time) +{ + const struct sieve_script_env *senv = eenv->scriptenv; + void *dup_trans = sieve_execute_get_dup_transaction(eenv); + + if (senv->duplicate_mark == NULL) + return; + + e_debug(eenv->svinst->event, "Mark ID as duplicate"); + + senv->duplicate_mark(dup_trans, senv, id, id_size, time); +} diff --git a/pigeonhole/src/lib-sieve/sieve-execute.h b/pigeonhole/src/lib-sieve/sieve-execute.h new file mode 100644 index 0000000..8af182b --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-execute.h @@ -0,0 +1,42 @@ +#ifndef SIEVE_EXECUTE_H +#define SIEVE_EXECUTE_H + +#include "sieve-common.h" + +struct sieve_execute_state; + +struct sieve_execute_env { + struct sieve_instance *svinst; + pool_t pool; + + enum sieve_execute_flags flags; + struct event *event; + + const struct sieve_message_data *msgdata; + const struct sieve_script_env *scriptenv; + + struct sieve_execute_state *state; + struct sieve_exec_status *exec_status; +}; + +void sieve_execute_init(struct sieve_execute_env *eenv, + struct sieve_instance *svinst, pool_t pool, + const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv, + enum sieve_execute_flags flags); +void sieve_execute_finish(struct sieve_execute_env *eenv, int status); +void sieve_execute_deinit(struct sieve_execute_env *eenv); + +/* + * Checking for duplicates + */ + +bool sieve_execute_duplicate_check_available( + const struct sieve_execute_env *eenv); +int sieve_execute_duplicate_check(const struct sieve_execute_env *eenv, + const void *id, size_t id_size, + bool *duplicate_r); +void sieve_execute_duplicate_mark(const struct sieve_execute_env *eenv, + const void *id, size_t id_size, time_t time); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-extensions.c b/pigeonhole/src/lib-sieve/sieve-extensions.c new file mode 100644 index 0000000..a1cb810 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-extensions.c @@ -0,0 +1,879 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "mempool.h" +#include "hash.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-settings.h" +#include "sieve-extensions.h" + +/* + * Forward declarations + */ + +static void sieve_extension_registry_init(struct sieve_instance *svinst); +static void sieve_extension_registry_deinit(struct sieve_instance *svinst); + +static void sieve_capability_registry_init(struct sieve_instance *svinst); +static void sieve_capability_registry_deinit(struct sieve_instance *svinst); + +static struct sieve_extension *_sieve_extension_register + (struct sieve_instance *svinst, const struct sieve_extension_def *extdef, + bool load, bool required); + +/* + * Instance global context + */ + +struct sieve_extension_registry { + ARRAY(struct sieve_extension *) extensions; + HASH_TABLE(const char *, struct sieve_extension *) extension_index; + HASH_TABLE(const char *, struct sieve_capability_registration *) capabilities_index; + + /* Core language 'extensions' */ + const struct sieve_extension *comparator_extension; + const struct sieve_extension *match_type_extension; + const struct sieve_extension *address_part_extension; + + /* Preloaded extensions */ + ARRAY(const struct sieve_extension *) preloaded_extensions; +}; + +/* + * Pre-loaded 'extensions' + */ + +extern const struct sieve_extension_def comparator_extension; +extern const struct sieve_extension_def match_type_extension; +extern const struct sieve_extension_def address_part_extension; + +/* + * Dummy extensions + */ + +/* FIXME: This is stupid. Define a comparator-* extension and be done with it */ + +const struct sieve_extension_def comparator_i_octet_extension = { + .name = "comparator-i;octet", +}; + +const struct sieve_extension_def comparator_i_ascii_casemap_extension = { + .name = "comparator-i;ascii-casemap", +}; + +/* + * List of native extensions + */ + +/* Dummy extensions */ + +extern const struct sieve_extension_def comparator_i_octet_extension; +extern const struct sieve_extension_def comparator_i_ascii_casemap_extension; + +const struct sieve_extension_def *sieve_dummy_extensions[] = { + &comparator_i_octet_extension, &comparator_i_ascii_casemap_extension +}; + +const unsigned int sieve_dummy_extensions_count = + N_ELEMENTS(sieve_dummy_extensions); + +/* Core */ + +extern const struct sieve_extension_def fileinto_extension; +extern const struct sieve_extension_def reject_extension; +extern const struct sieve_extension_def envelope_extension; +extern const struct sieve_extension_def encoded_character_extension; + +extern const struct sieve_extension_def vacation_extension; +extern const struct sieve_extension_def subaddress_extension; +extern const struct sieve_extension_def comparator_i_ascii_numeric_extension; +extern const struct sieve_extension_def relational_extension; +extern const struct sieve_extension_def regex_extension; +extern const struct sieve_extension_def imap4flags_extension; +extern const struct sieve_extension_def copy_extension; +extern const struct sieve_extension_def include_extension; +extern const struct sieve_extension_def body_extension; +extern const struct sieve_extension_def variables_extension; +extern const struct sieve_extension_def enotify_extension; +extern const struct sieve_extension_def environment_extension; +extern const struct sieve_extension_def mailbox_extension; +extern const struct sieve_extension_def date_extension; +extern const struct sieve_extension_def index_extension; +extern const struct sieve_extension_def ihave_extension; +extern const struct sieve_extension_def duplicate_extension; +extern const struct sieve_extension_def mime_extension; +extern const struct sieve_extension_def foreverypart_extension; +extern const struct sieve_extension_def extracttext_extension; +extern const struct sieve_extension_def mboxmetadata_extension; +extern const struct sieve_extension_def servermetadata_extension; + +const struct sieve_extension_def *sieve_core_extensions[] = { + /* Core extensions */ + &fileinto_extension, &reject_extension, &envelope_extension, + &encoded_character_extension, + + /* 'Plugins' */ + &vacation_extension, &subaddress_extension, + &comparator_i_ascii_numeric_extension, + &relational_extension, ®ex_extension, &imap4flags_extension, + ©_extension, &include_extension, &body_extension, + &variables_extension, &enotify_extension, &environment_extension, + &mailbox_extension, &date_extension, &index_extension, &ihave_extension, + &duplicate_extension, &mime_extension, &foreverypart_extension, + &extracttext_extension +}; + +const unsigned int sieve_core_extensions_count = + N_ELEMENTS(sieve_core_extensions); + +/* Extra; + * These are not enabled by default, e.g. because explicit configuration is + * necessary to make these useful. + */ + +extern const struct sieve_extension_def vacation_seconds_extension; +extern const struct sieve_extension_def spamtest_extension; +extern const struct sieve_extension_def spamtestplus_extension; +extern const struct sieve_extension_def virustest_extension; +extern const struct sieve_extension_def editheader_extension; +extern const struct sieve_extension_def special_use_extension; + +extern const struct sieve_extension_def vnd_debug_extension; +extern const struct sieve_extension_def vnd_environment_extension; +extern const struct sieve_extension_def vnd_report_extension; + +const struct sieve_extension_def *sieve_extra_extensions[] = { + &vacation_seconds_extension, &spamtest_extension, &spamtestplus_extension, + &virustest_extension, &editheader_extension, + &mboxmetadata_extension, &servermetadata_extension, + &special_use_extension, + + /* vnd.dovecot. */ + &vnd_debug_extension, &vnd_environment_extension, &vnd_report_extension +}; + +const unsigned int sieve_extra_extensions_count = + N_ELEMENTS(sieve_extra_extensions); + +/* + * Deprecated extensions + */ + +extern const struct sieve_extension_def imapflags_extension; +extern const struct sieve_extension_def notify_extension; +extern const struct sieve_extension_def vnd_duplicate_extension; + +const struct sieve_extension_def *sieve_deprecated_extensions[] = { + &imapflags_extension, + ¬ify_extension, + &vnd_duplicate_extension +}; + +const unsigned int sieve_deprecated_extensions_count = + N_ELEMENTS(sieve_deprecated_extensions); + +/* + * Unfinished extensions + */ + +#ifdef HAVE_SIEVE_UNFINISHED + +extern const struct sieve_extension_def ereject_extension; + +const struct sieve_extension_def *sieve_unfinished_extensions[] = { + &ereject_extension +}; + +const unsigned int sieve_unfinished_extensions_count = + N_ELEMENTS(sieve_unfinished_extensions); + +#endif /* HAVE_SIEVE_UNFINISHED */ + +/* + * Extensions init/deinit + */ + +bool sieve_extensions_init(struct sieve_instance *svinst) +{ + unsigned int i; + struct sieve_extension_registry *ext_reg = + p_new(svinst->pool, struct sieve_extension_registry, 1); + struct sieve_extension *ext; + + svinst->ext_reg = ext_reg; + + sieve_extension_registry_init(svinst); + sieve_capability_registry_init(svinst); + + /* Preloaded 'extensions' */ + ext_reg->comparator_extension = + sieve_extension_register(svinst, &comparator_extension, TRUE); + ext_reg->match_type_extension = + sieve_extension_register(svinst, &match_type_extension, TRUE); + ext_reg->address_part_extension = + sieve_extension_register(svinst, &address_part_extension, TRUE); + + p_array_init(&ext_reg->preloaded_extensions, svinst->pool, 5); + array_append(&ext_reg->preloaded_extensions, + &ext_reg->comparator_extension, 1); + array_append(&ext_reg->preloaded_extensions, + &ext_reg->match_type_extension, 1); + array_append(&ext_reg->preloaded_extensions, + &ext_reg->address_part_extension, 1); + + /* Pre-load dummy extensions */ + for ( i = 0; i < sieve_dummy_extensions_count; i++ ) { + if ( (ext=_sieve_extension_register + (svinst, sieve_dummy_extensions[i], TRUE, FALSE)) == NULL ) + return FALSE; + + ext->dummy = TRUE; + } + + /* Pre-load core extensions */ + for ( i = 0; i < sieve_core_extensions_count; i++ ) { + if ( sieve_extension_register + (svinst, sieve_core_extensions[i], TRUE) == NULL ) + return FALSE; + } + + /* Pre-load extra extensions */ + for ( i = 0; i < sieve_extra_extensions_count; i++ ) { + if ( sieve_extension_register + (svinst, sieve_extra_extensions[i], FALSE) == NULL ) + return FALSE; + } + + /* Register deprecated extensions */ + for ( i = 0; i < sieve_deprecated_extensions_count; i++ ) { + if ( sieve_extension_register + (svinst, sieve_deprecated_extensions[i], FALSE) == NULL ) + return FALSE; + } + +#ifdef HAVE_SIEVE_UNFINISHED + /* Register unfinished extensions */ + for ( i = 0; i < sieve_unfinished_extensions_count; i++ ) { + if ( sieve_extension_register + (svinst, sieve_unfinished_extensions[i], FALSE) == NULL ) + return FALSE; + } +#endif + + /* More extensions can be added through plugins */ + + return TRUE; +} + +void sieve_extensions_configure(struct sieve_instance *svinst) +{ + const char *extensions; + + /* Apply sieve_extensions configuration */ + + if ( (extensions=sieve_setting_get + (svinst, "sieve_extensions")) != NULL ) + sieve_extensions_set_string(svinst, extensions, FALSE, FALSE); + + /* Apply sieve_global_extensions configuration */ + + if ( (extensions=sieve_setting_get + (svinst, "sieve_global_extensions")) != NULL ) + sieve_extensions_set_string(svinst, extensions, TRUE, FALSE); + + /* Apply sieve_implicit_extensions configuration */ + + if ( (extensions=sieve_setting_get + (svinst, "sieve_implicit_extensions")) != NULL ) + sieve_extensions_set_string(svinst, extensions, FALSE, TRUE); +} + +void sieve_extensions_deinit(struct sieve_instance *svinst) +{ + sieve_extension_registry_deinit(svinst); + sieve_capability_registry_deinit(svinst); +} + +/* + * Pre-loaded extensions + */ + +const struct sieve_extension *const *sieve_extensions_get_preloaded +(struct sieve_instance *svinst, unsigned int *count_r) +{ + struct sieve_extension_registry *ext_reg = svinst->ext_reg; + + return array_get(&ext_reg->preloaded_extensions, count_r); +} + +/* + * Extension registry + */ + +static bool _sieve_extension_load(struct sieve_extension *ext) +{ + /* Call load handler */ + if ( ext->def != NULL && ext->def->load != NULL && + !ext->def->load(ext, &ext->context) ) { + e_error(ext->svinst->event, + "failed to load '%s' extension support.", + ext->def->name); + return FALSE; + } + + return TRUE; +} + +static void _sieve_extension_unload(struct sieve_extension *ext) +{ + /* Call unload handler */ + if ( ext->def != NULL && ext->def->unload != NULL ) + ext->def->unload(ext); + ext->context = NULL; +} + +static void sieve_extension_registry_init(struct sieve_instance *svinst) +{ + struct sieve_extension_registry *ext_reg = svinst->ext_reg; + + p_array_init(&ext_reg->extensions, svinst->pool, 50); + hash_table_create + (&ext_reg->extension_index, default_pool, 0, str_hash, strcmp); +} + +static void sieve_extension_registry_deinit(struct sieve_instance *svinst) +{ + struct sieve_extension_registry *ext_reg = svinst->ext_reg; + struct sieve_extension * const *exts; + unsigned int i, ext_count; + + if ( !hash_table_is_created(ext_reg->extension_index) ) return; + + exts = array_get_modifiable(&ext_reg->extensions, &ext_count); + for ( i = 0; i < ext_count; i++ ) { + _sieve_extension_unload(exts[i]); + } + + hash_table_destroy(&ext_reg->extension_index); +} + +bool sieve_extension_reload(const struct sieve_extension *ext) +{ + struct sieve_extension_registry *ext_reg = ext->svinst->ext_reg; + struct sieve_extension * const *mod_ext; + int ext_id = ext->id; + + /* Let's not just cast the 'const' away */ + if ( ext_id >= 0 && ext_id < (int) array_count(&ext_reg->extensions) ) { + mod_ext = array_idx(&ext_reg->extensions, ext_id); + + return _sieve_extension_load(*mod_ext); + } + + return FALSE; +} + +static struct sieve_extension *sieve_extension_lookup +(struct sieve_instance *svinst, const char *name) +{ + struct sieve_extension_registry *ext_reg = svinst->ext_reg; + + return hash_table_lookup(ext_reg->extension_index, name); +} + +static struct sieve_extension *sieve_extension_alloc +(struct sieve_instance *svinst, + const struct sieve_extension_def *extdef) +{ + struct sieve_extension_registry *ext_reg = svinst->ext_reg; + struct sieve_extension *ext, **extr; + int ext_id; + + ext_id = (int)array_count(&ext_reg->extensions); + + /* Add extension to the registry */ + extr = array_append_space(&ext_reg->extensions); + *extr = ext = p_new(svinst->pool, struct sieve_extension, 1); + ext->id = ext_id; + ext->def = extdef; + ext->svinst = svinst; + return ext; +} + +static struct sieve_extension *_sieve_extension_register +(struct sieve_instance *svinst, const struct sieve_extension_def *extdef, + bool load, bool required) +{ + struct sieve_extension *ext; + + ext = sieve_extension_lookup(svinst, extdef->name); + + /* Register extension if it is not registered already */ + if ( ext == NULL ) { + ext = sieve_extension_alloc(svinst, extdef); + hash_table_insert + (svinst->ext_reg->extension_index, extdef->name, ext); + + } else if ( ext->overridden ) { + /* Create a dummy */ + ext = sieve_extension_alloc(svinst, extdef); + + } else { + /* Re-register it if it were previously unregistered + * (not going to happen) + */ + i_assert( ext->def == NULL || ext->def == extdef ); + ext->def = extdef; + } + + /* Enable extension */ + if ( load || required ) { + ext->enabled = ( ext->enabled || load ); + + /* Call load handler if extension was not loaded already */ + if ( !ext->loaded ) { + if ( !_sieve_extension_load(ext) ) + return NULL; + } + + ext->loaded = TRUE; + } + + ext->required = ( ext->required || required ); + + return ext; +} + +const struct sieve_extension *sieve_extension_register +(struct sieve_instance *svinst, const struct sieve_extension_def *extdef, + bool load) +{ + return _sieve_extension_register(svinst, extdef, load, FALSE); +} + +void sieve_extension_unregister(const struct sieve_extension *ext) +{ + struct sieve_extension_registry *ext_reg = ext->svinst->ext_reg; + struct sieve_extension * const *mod_ext; + int ext_id = ext->id; + + if ( ext_id >= 0 && ext_id < (int) array_count(&ext_reg->extensions) ) { + mod_ext = array_idx(&ext_reg->extensions, ext_id); + + sieve_extension_capabilities_unregister(*mod_ext); + _sieve_extension_unload(*mod_ext); + (*mod_ext)->loaded = FALSE; + (*mod_ext)->enabled = FALSE; + (*mod_ext)->def = NULL; + } +} + +const struct sieve_extension *sieve_extension_replace +(struct sieve_instance *svinst, const struct sieve_extension_def *extdef, + bool load) +{ + struct sieve_extension *ext; + + ext = sieve_extension_lookup(svinst, extdef->name); + if (ext != NULL) + sieve_extension_unregister(ext); + return sieve_extension_register(svinst, extdef, load); +} + +const struct sieve_extension *sieve_extension_require +(struct sieve_instance *svinst, const struct sieve_extension_def *extdef, + bool load) +{ + return _sieve_extension_register(svinst, extdef, load, TRUE); +} + +void sieve_extension_override +(struct sieve_instance *svinst, const char *name, + const struct sieve_extension *ext) +{ + struct sieve_extension_registry *ext_reg = ext->svinst->ext_reg; + struct sieve_extension * const *mod_ext; + struct sieve_extension *old_ext; + + old_ext = sieve_extension_lookup(svinst, name); + if (old_ext == ext) + return; + i_assert( old_ext == NULL || !old_ext->overridden ); + + i_assert( ext->id >= 0 && + ext->id < (int) array_count(&ext_reg->extensions) ); + mod_ext = array_idx(&ext_reg->extensions, ext->id); + + hash_table_update + (ext_reg->extension_index, name, *mod_ext); + if ( old_ext != NULL ) + old_ext->overridden = TRUE; +} + +unsigned int sieve_extensions_get_count(struct sieve_instance *svinst) +{ + struct sieve_extension_registry *ext_reg = svinst->ext_reg; + + return array_count(&ext_reg->extensions); +} + +const struct sieve_extension *const * +sieve_extensions_get_all(struct sieve_instance *svinst, + unsigned int *count_r) +{ + struct sieve_extension_registry *ext_reg = svinst->ext_reg; + + return (const struct sieve_extension *const *) + array_get(&ext_reg->extensions, count_r); +} + +const struct sieve_extension *sieve_extension_get_by_id +(struct sieve_instance *svinst, unsigned int ext_id) +{ + struct sieve_extension_registry *ext_reg = svinst->ext_reg; + struct sieve_extension * const *ext; + + if ( ext_id < array_count(&ext_reg->extensions) ) { + ext = array_idx(&ext_reg->extensions, ext_id); + + if ( (*ext)->def != NULL && ((*ext)->enabled || (*ext)->required) ) + return *ext; + } + + return NULL; +} + +const struct sieve_extension *sieve_extension_get_by_name +(struct sieve_instance *svinst, const char *name) +{ + const struct sieve_extension *ext; + + if ( *name == '@' ) + return NULL; + + if ( strlen(name) > 128 ) + return NULL; + + ext = sieve_extension_lookup(svinst, name); + if ( ext == NULL || ext->def == NULL || (!ext->enabled && !ext->required)) + return NULL; + + return ext; +} + +static inline bool _sieve_extension_listable(const struct sieve_extension *ext) +{ + return ( ext->enabled && ext->def != NULL && *(ext->def->name) != '@' + && !ext->dummy && !ext->global && !ext->overridden); +} + +const char *sieve_extensions_get_string(struct sieve_instance *svinst) +{ + struct sieve_extension_registry *ext_reg = svinst->ext_reg; + string_t *extstr = t_str_new(256); + struct sieve_extension * const *exts; + unsigned int i, ext_count; + + exts = array_get(&ext_reg->extensions, &ext_count); + + if ( ext_count > 0 ) { + i = 0; + + /* Find first listable extension */ + while ( i < ext_count && !_sieve_extension_listable(exts[i]) ) + i++; + + if ( i < ext_count ) { + /* Add first to string */ + str_append(extstr, exts[i]->def->name); + i++; + + /* Add others */ + for ( ; i < ext_count; i++ ) { + if ( _sieve_extension_listable(exts[i]) ) { + str_append_c(extstr, ' '); + str_append(extstr, exts[i]->def->name); + } + } + } + } + + return str_c(extstr); +} + +static void sieve_extension_set_enabled +(struct sieve_extension *ext, bool enabled) +{ + if ( enabled ) { + ext->enabled = TRUE; + + if ( !ext->loaded ) { + (void)_sieve_extension_load(ext); + } + + ext->loaded = TRUE; + } else { + ext->enabled = FALSE; + } +} + +static void sieve_extension_set_global +(struct sieve_extension *ext, bool enabled) +{ + if ( enabled ) { + sieve_extension_set_enabled(ext, TRUE); + ext->global = TRUE; + } else { + ext->global = FALSE; + } +} + +static void sieve_extension_set_implicit +(struct sieve_extension *ext, bool enabled) +{ + if ( enabled ) { + sieve_extension_set_enabled(ext, TRUE); + ext->implicit = TRUE; + } else { + ext->implicit = FALSE; + } +} + +void sieve_extensions_set_string +(struct sieve_instance *svinst, const char *ext_string, + bool global, bool implicit) +{ + struct sieve_extension_registry *ext_reg = svinst->ext_reg; + ARRAY(const struct sieve_extension *) enabled_extensions; + ARRAY(const struct sieve_extension *) disabled_extensions; + const struct sieve_extension *const *ext_enabled; + const struct sieve_extension *const *ext_disabled; + struct sieve_extension **exts; + const char **ext_names; + unsigned int i, ext_count, ena_count, dis_count; + bool relative = FALSE; + + if ( ext_string == NULL ) { + if ( global || implicit ) return; + + /* Enable all */ + exts = array_get_modifiable(&ext_reg->extensions, &ext_count); + + for ( i = 0; i < ext_count; i++ ) + sieve_extension_set_enabled(exts[i], TRUE); + + return; + } + + T_BEGIN { + t_array_init(&enabled_extensions, array_count(&ext_reg->extensions)); + t_array_init(&disabled_extensions, array_count(&ext_reg->extensions)); + + ext_names = t_strsplit_spaces(ext_string, " \t"); + + while ( *ext_names != NULL ) { + const char *name = *ext_names; + + ext_names++; + + if ( *name != '\0' ) { + const struct sieve_extension *ext; + char op = '\0'; /* No add/remove operation */ + + if ( *name == '+' /* Add to existing config */ + || *name == '-' ) { /* Remove from existing config */ + op = *name++; + relative = TRUE; + } + + if ( *name == '@' ) + ext = NULL; + else + ext = hash_table_lookup(ext_reg->extension_index, name); + + if ( ext == NULL || ext->def == NULL ) { + e_warning(svinst->event, + "ignored unknown extension '%s' while configuring " + "available extensions", name); + continue; + } + + if ( op == '-' ) + array_append(&disabled_extensions, &ext, 1); + else + array_append(&enabled_extensions, &ext, 1); + } + } + + exts = array_get_modifiable(&ext_reg->extensions, &ext_count); + ext_enabled = array_get(&enabled_extensions, &ena_count); + ext_disabled = array_get(&disabled_extensions, &dis_count); + + /* Set new extension status */ + + for ( i = 0; i < ext_count; i++ ) { + unsigned int j; + bool enabled = FALSE; + + if ( exts[i]->id < 0 || exts[i]->def == NULL || + *(exts[i]->def->name) == '@' ) { + continue; + } + + /* If extensions are specified relative to the default set, + * we first need to check which ones are disabled + */ + + if ( relative ) { + if ( global ) + enabled = exts[i]->global; + else if ( implicit ) + enabled = exts[i]->implicit; + else + enabled = exts[i]->enabled; + + if ( enabled ) { + /* Disable if explicitly disabled */ + for ( j = 0; j < dis_count; j++ ) { + if ( ext_disabled[j]->def == exts[i]->def ) { + enabled = FALSE; + break; + } + } + } + } + + /* Enable if listed with '+' or no prefix */ + + for ( j = 0; j < ena_count; j++ ) { + if ( ext_enabled[j]->def == exts[i]->def ) { + enabled = TRUE; + break; + } + } + + /* Perform actual activation/deactivation */ + if ( global ) { + sieve_extension_set_global(exts[i], enabled); + } else if ( implicit ) { + sieve_extension_set_implicit(exts[i], enabled); + } else { + sieve_extension_set_enabled(exts[i], enabled); + } + } + } T_END; +} + +const struct sieve_extension *sieve_get_match_type_extension + (struct sieve_instance *svinst) +{ + return svinst->ext_reg->match_type_extension; +} + +const struct sieve_extension *sieve_get_comparator_extension + (struct sieve_instance *svinst) +{ + return svinst->ext_reg->comparator_extension; +} + +const struct sieve_extension *sieve_get_address_part_extension + (struct sieve_instance *svinst) +{ + return svinst->ext_reg->address_part_extension; +} + +void sieve_enable_debug_extension(struct sieve_instance *svinst) +{ + (void) sieve_extension_register(svinst, &vnd_debug_extension, TRUE); +} + +/* + * Extension capabilities + */ + +struct sieve_capability_registration { + const struct sieve_extension *ext; + const struct sieve_extension_capabilities *capabilities; +}; + +void sieve_capability_registry_init(struct sieve_instance *svinst) +{ + struct sieve_extension_registry *ext_reg = svinst->ext_reg; + + hash_table_create + (&ext_reg->capabilities_index, default_pool, 0, str_hash, strcmp); +} + +void sieve_capability_registry_deinit(struct sieve_instance *svinst) +{ + struct sieve_extension_registry *ext_reg = svinst->ext_reg; + + if ( !hash_table_is_created(ext_reg->capabilities_index) ) return; + + hash_table_destroy(&svinst->ext_reg->capabilities_index); +} + +void sieve_extension_capabilities_register +(const struct sieve_extension *ext, + const struct sieve_extension_capabilities *cap) +{ + struct sieve_instance *svinst = ext->svinst; + struct sieve_extension_registry *ext_reg = svinst->ext_reg; + struct sieve_capability_registration *reg; + + reg = hash_table_lookup(ext_reg->capabilities_index, cap->name); + if (reg != NULL) { + /* Already registered */ + return; + } + + reg = p_new(svinst->pool, struct sieve_capability_registration, 1); + reg->ext = ext; + reg->capabilities = cap; + + hash_table_insert(ext_reg->capabilities_index, cap->name, reg); +} + +void sieve_extension_capabilities_unregister +(const struct sieve_extension *ext) +{ + struct sieve_extension_registry *ext_reg = ext->svinst->ext_reg; + struct hash_iterate_context *hictx; + const char *name; + struct sieve_capability_registration *reg; + + hictx = hash_table_iterate_init(ext_reg->capabilities_index); + while ( hash_table_iterate(hictx, ext_reg->capabilities_index, &name, ®) ) { + if ( reg->ext == ext ) + hash_table_remove(ext_reg->capabilities_index, name); + } + hash_table_iterate_deinit(&hictx); +} + +const char *sieve_extension_capabilities_get_string +(struct sieve_instance *svinst, const char *cap_name) +{ + struct sieve_extension_registry *ext_reg = svinst->ext_reg; + const struct sieve_capability_registration *cap_reg = + hash_table_lookup(ext_reg->capabilities_index, cap_name); + const struct sieve_extension_capabilities *cap; + + if ( cap_reg == NULL || cap_reg->capabilities == NULL ) + return NULL; + + cap = cap_reg->capabilities; + + if ( cap->get_string == NULL || !cap_reg->ext->enabled ) + return NULL; + + return cap->get_string(cap_reg->ext); +} + + + + diff --git a/pigeonhole/src/lib-sieve/sieve-extensions.h b/pigeonhole/src/lib-sieve/sieve-extensions.h new file mode 100644 index 0000000..961cf41 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-extensions.h @@ -0,0 +1,191 @@ +#ifndef SIEVE_EXTENSIONS_H +#define SIEVE_EXTENSIONS_H + +#include "lib.h" +#include "sieve-common.h" + +/* + * Per-extension object registry + */ + +struct sieve_extension_objects { + const void *objects; + unsigned int count; +}; + +/* + * Extension definition + */ + +struct sieve_extension_def { + const char *name; + + /* Version */ + unsigned int version; + + /* Registration */ + bool (*load)(const struct sieve_extension *ext, void **context); + void (*unload)(const struct sieve_extension *ext); + + /* Compilation */ + bool (*validator_load) + (const struct sieve_extension *ext, struct sieve_validator *validator); + bool (*generator_load) + (const struct sieve_extension *ext, const struct sieve_codegen_env *cgenv); + bool (*interpreter_load) + (const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address); + bool (*binary_load) + (const struct sieve_extension *ext, struct sieve_binary *binary); + + /* Code dump */ + bool (*binary_dump) + (const struct sieve_extension *ext, struct sieve_dumptime_env *denv); + bool (*code_dump) + (const struct sieve_extension *ext, const struct sieve_dumptime_env *denv, + sieve_size_t *address); + + /* Objects */ + struct sieve_extension_objects operations; + struct sieve_extension_objects operands; +}; + +/* Defining opcodes and operands */ + +#define SIEVE_EXT_DEFINE_NO_OBJECTS \ + { NULL, 0 } +#define SIEVE_EXT_DEFINE_OBJECT(OBJ) \ + { &OBJ, 1 } +#define SIEVE_EXT_DEFINE_OBJECTS(OBJS) \ + { OBJS, N_ELEMENTS(OBJS) } + +#define SIEVE_EXT_GET_OBJECTS_COUNT(ext, field) \ + ext->field->count; + +#define SIEVE_EXT_DEFINE_NO_OPERATIONS \ + .operations = SIEVE_EXT_DEFINE_NO_OBJECTS +#define SIEVE_EXT_DEFINE_OPERATION(OP) \ + .operations = SIEVE_EXT_DEFINE_OBJECT(OP) +#define SIEVE_EXT_DEFINE_OPERATIONS(OPS) \ + .operations = SIEVE_EXT_DEFINE_OBJECTS(OPS) + +#define SIEVE_EXT_DEFINE_NO_OPERANDS \ + .operands = SIEVE_EXT_DEFINE_NO_OBJECTS +#define SIEVE_EXT_DEFINE_OPERAND(OP) \ + .operands = SIEVE_EXT_DEFINE_OBJECT(OP) +#define SIEVE_EXT_DEFINE_OPERANDS(OPS) \ + .operands = SIEVE_EXT_DEFINE_OBJECTS(OPS) + +/* + * Extension instance + */ + +struct sieve_extension { + const struct sieve_extension_def *def; + int id; + + struct sieve_instance *svinst; + void *context; + + bool required:1; + bool loaded:1; + bool enabled:1; + bool dummy:1; + bool global:1; + bool implicit:1; + bool overridden:1; +}; + +#define sieve_extension_is(ext, definition) \ + ( (ext)->def == &(definition) ) +#define sieve_extension_name(ext) \ + ((ext)->def->name) +#define sieve_extension_name_is(ext, _name) \ + ( strcmp((ext)->def->name, (_name)) == 0 ) +#define sieve_extension_version(ext) \ + ((ext)->def->version) +#define sieve_extension_version_is(ext, _version) \ + ((ext)->def->version == (_version)) + +/* + * Extensions init/deinit + */ + +bool sieve_extensions_init(struct sieve_instance *svinst); +void sieve_extensions_configure(struct sieve_instance *svinst); +void sieve_extensions_deinit(struct sieve_instance *svinst); + +/* + * Pre-loaded extensions + */ + +const struct sieve_extension *const *sieve_extensions_get_preloaded + (struct sieve_instance *svinst, unsigned int *count_r); + +/* + * Extension registry + */ + +const struct sieve_extension *sieve_extension_register + (struct sieve_instance *svinst, const struct sieve_extension_def *extension, + bool load); +const struct sieve_extension *sieve_extension_require + (struct sieve_instance *svinst, const struct sieve_extension_def *extension, + bool load); +bool sieve_extension_reload(const struct sieve_extension *ext); + +void sieve_extension_unregister(const struct sieve_extension *ext); + +const struct sieve_extension *sieve_extension_replace + (struct sieve_instance *svinst, + const struct sieve_extension_def *extdef, + bool load); +void sieve_extension_override + (struct sieve_instance *svinst, const char *name, + const struct sieve_extension *ext); + +unsigned int sieve_extensions_get_count(struct sieve_instance *svinst); +const struct sieve_extension *const * +sieve_extensions_get_all(struct sieve_instance *svinst, + unsigned int *count_r); + +const struct sieve_extension *sieve_extension_get_by_id + (struct sieve_instance *svinst, unsigned int ext_id); +const struct sieve_extension *sieve_extension_get_by_name + (struct sieve_instance *svinst, const char *name); + +const char *sieve_extensions_get_string + (struct sieve_instance *svinst); +void sieve_extensions_set_string + (struct sieve_instance *svinst, const char *ext_string, + bool global, bool implicit); + +const struct sieve_extension *sieve_get_match_type_extension + (struct sieve_instance *svinst); +const struct sieve_extension *sieve_get_comparator_extension + (struct sieve_instance *svinst); +const struct sieve_extension *sieve_get_address_part_extension + (struct sieve_instance *svinst); + +void sieve_enable_debug_extension(struct sieve_instance *svinst); + +/* + * Capability registries + */ + +struct sieve_extension_capabilities { + const char *name; + + const char *(*get_string)(const struct sieve_extension *ext); +}; + +void sieve_extension_capabilities_register + (const struct sieve_extension *ext, + const struct sieve_extension_capabilities *cap); +void sieve_extension_capabilities_unregister + (const struct sieve_extension *ext); + +const char *sieve_extension_capabilities_get_string + (struct sieve_instance *svinst, const char *cap_name); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-generator.c b/pigeonhole/src/lib-sieve/sieve-generator.c new file mode 100644 index 0000000..ebc06ed --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-generator.c @@ -0,0 +1,578 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "mempool.h" + +#include "sieve-common.h" +#include "sieve-script.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-binary.h" + +#include "sieve-generator.h" + +/* + * Jump list + */ + +struct sieve_jumplist * +sieve_jumplist_create(pool_t pool, struct sieve_binary_block *sblock) +{ + struct sieve_jumplist *jlist; + + jlist = p_new(pool, struct sieve_jumplist, 1); + jlist->block = sblock; + p_array_init(&jlist->jumps, pool, 4); + + return jlist; +} + +void sieve_jumplist_init_temp(struct sieve_jumplist *jlist, + struct sieve_binary_block *sblock) +{ + jlist->block = sblock; + t_array_init(&jlist->jumps, 4); +} + +void sieve_jumplist_reset(struct sieve_jumplist *jlist) +{ + array_clear(&jlist->jumps); +} + +void sieve_jumplist_add(struct sieve_jumplist *jlist, sieve_size_t jump) +{ + array_append(&jlist->jumps, &jump, 1); +} + +void sieve_jumplist_resolve(struct sieve_jumplist *jlist) +{ + unsigned int i; + + for (i = 0; i < array_count(&jlist->jumps); i++) { + const sieve_size_t *jump = array_idx(&jlist->jumps, i); + + sieve_binary_resolve_offset(jlist->block, *jump); + } +} + +/* + * Code Generator + */ + +struct sieve_generator { + pool_t pool; + + struct sieve_instance *instance; + + struct sieve_error_handler *ehandler; + + struct sieve_codegen_env genenv; + struct sieve_binary_debug_writer *dwriter; + + ARRAY(void *) ext_contexts; +}; + +struct sieve_generator * +sieve_generator_create(struct sieve_ast *ast, + struct sieve_error_handler *ehandler, + enum sieve_compile_flags flags) +{ + pool_t pool; + struct sieve_generator *gentr; + struct sieve_script *script; + struct sieve_instance *svinst; + + pool = pool_alloconly_create("sieve_generator", 4096); + gentr = p_new(pool, struct sieve_generator, 1); + gentr->pool = pool; + + gentr->ehandler = ehandler; + sieve_error_handler_ref(ehandler); + + gentr->genenv.gentr = gentr; + gentr->genenv.flags = flags; + gentr->genenv.ast = ast; + sieve_ast_ref(ast); + + script = sieve_ast_script(ast); + svinst = sieve_script_svinst(script); + + gentr->genenv.script = script; + gentr->genenv.svinst = svinst; + + /* Setup storage for extension contexts */ + p_array_init(&gentr->ext_contexts, pool, + sieve_extensions_get_count(svinst)); + + return gentr; +} + +void sieve_generator_free(struct sieve_generator **gentr) +{ + sieve_ast_unref(&(*gentr)->genenv.ast); + + sieve_error_handler_unref(&(*gentr)->ehandler); + sieve_binary_debug_writer_deinit(&(*gentr)->dwriter); + + sieve_binary_unref(&(*gentr)->genenv.sbin); + + pool_unref(&((*gentr)->pool)); + + *gentr = NULL; +} + +/* + * Accessors + */ + +struct sieve_error_handler * +sieve_generator_error_handler(struct sieve_generator *gentr) +{ + return gentr->ehandler; +} + +pool_t sieve_generator_pool(struct sieve_generator *gentr) +{ + return gentr->pool; +} + +struct sieve_script *sieve_generator_script(struct sieve_generator *gentr) +{ + return gentr->genenv.script; +} + +struct sieve_binary *sieve_generator_get_binary(struct sieve_generator *gentr) +{ + return gentr->genenv.sbin; +} + +struct sieve_binary_block * +sieve_generator_get_block(struct sieve_generator *gentr) +{ + return gentr->genenv.sblock; +} + +/* + * Extension support + */ + +void sieve_generator_extension_set_context(struct sieve_generator *gentr, + const struct sieve_extension *ext, + void *context) +{ + if (ext->id < 0) + return; + + array_idx_set(&gentr->ext_contexts, (unsigned int) ext->id, &context); +} + +const void * +sieve_generator_extension_get_context(struct sieve_generator *gentr, + const struct sieve_extension *ext) +{ + void * const *ctx; + + if (ext->id < 0 || ext->id >= (int) array_count(&gentr->ext_contexts)) + return NULL; + + ctx = array_idx(&gentr->ext_contexts, (unsigned int) ext->id); + + return *ctx; +} + +/* + * Code generation API + */ + +static void +sieve_generate_debug_from_ast_node(const struct sieve_codegen_env *cgenv, + struct sieve_ast_node *ast_node) +{ + sieve_size_t address = sieve_binary_block_get_size(cgenv->sblock); + unsigned int line = sieve_ast_node_line(ast_node); + + sieve_binary_debug_emit(cgenv->gentr->dwriter, address, line, 0); +} + +static void +sieve_generate_debug_from_ast_argument(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *ast_arg) +{ + sieve_size_t address = sieve_binary_block_get_size(cgenv->sblock); + unsigned int line = sieve_ast_argument_line(ast_arg); + + sieve_binary_debug_emit(cgenv->gentr->dwriter, address, line, 0); +} + +bool sieve_generate_argument(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, + struct sieve_command *cmd) +{ + const struct sieve_argument_def *arg_def; + + if (arg->argument == NULL || arg->argument->def == NULL) + return FALSE; + + arg_def = arg->argument->def; + + if (arg_def->generate == NULL) + return TRUE; + + sieve_generate_debug_from_ast_argument(cgenv, arg); + + return arg_def->generate(cgenv, arg, cmd); +} + +bool sieve_generate_arguments(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd, + struct sieve_ast_argument **last_arg_r) +{ + enum { ARG_START, ARG_OPTIONAL, ARG_POSITIONAL } state = ARG_START; + struct sieve_ast_argument *arg = + sieve_ast_argument_first(cmd->ast_node); + + /* Generate all arguments with assigned generator function */ + + while (arg != NULL) { + const struct sieve_argument *argument; + const struct sieve_argument_def *arg_def; + + if (arg->argument == NULL || arg->argument->def == NULL) + return FALSE; + + argument = arg->argument; + arg_def = argument->def; + + switch (state) { + case ARG_START: + if (argument->id_code == 0) + state = ARG_POSITIONAL; + else { + /* Mark start of optional operands with 0 + operand identifier */ + sieve_binary_emit_byte(cgenv->sblock, + SIEVE_OPERAND_OPTIONAL); + + /* Emit argument id for optional operand */ + sieve_binary_emit_byte( + cgenv->sblock, + (unsigned char)argument->id_code); + + state = ARG_OPTIONAL; + } + break; + case ARG_OPTIONAL: + if (argument->id_code == 0) + state = ARG_POSITIONAL; + + /* Emit argument id for optional operand (0 marks the + end of the optionals) */ + sieve_binary_emit_byte( + cgenv->sblock, + (unsigned char)argument->id_code); + break; + case ARG_POSITIONAL: + if (argument->id_code != 0) + return FALSE; + break; + } + + /* Call the generation function for the argument */ + if (arg_def->generate != NULL) { + sieve_generate_debug_from_ast_argument(cgenv, arg); + + if (!arg_def->generate(cgenv, arg, cmd)) + return FALSE; + } else if (state == ARG_POSITIONAL) { + break; + } + + arg = sieve_ast_argument_next(arg); + } + + /* Mark end of optional list if it is still open */ + if (state == ARG_OPTIONAL) + sieve_binary_emit_byte(cgenv->sblock, 0); + + if (last_arg_r != NULL) + *last_arg_r = arg; + + return TRUE; +} + +bool sieve_generate_argument_parameters(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd, + struct sieve_ast_argument *arg) +{ + struct sieve_ast_argument *param = arg->parameters; + + /* Generate all parameters with assigned generator function */ + + while (param != NULL) { + if (param->argument != NULL && param->argument->def != NULL) { + const struct sieve_argument_def *parameter = + param->argument->def; + + /* Call the generation function for the parameter */ + if (parameter->generate != NULL) { + sieve_generate_debug_from_ast_argument( + cgenv, param); + + if (!parameter->generate(cgenv, param, cmd)) + return FALSE; + } + } + + param = sieve_ast_argument_next(param); + } + + return TRUE; +} + +bool sieve_generate_test(const struct sieve_codegen_env *cgenv, + struct sieve_ast_node *tst_node, + struct sieve_jumplist *jlist, bool jump_true) +{ + struct sieve_command *test; + const struct sieve_command_def *tst_def; + + i_assert(tst_node->command != NULL && tst_node->command->def != NULL); + + test = tst_node->command; + tst_def = test->def; + + if (tst_def->control_generate != NULL) { + sieve_generate_debug_from_ast_node(cgenv, tst_node); + + if (tst_def->control_generate(cgenv, test, jlist, jump_true)) + return TRUE; + + return FALSE; + } + + if (tst_def->generate != NULL) { + sieve_generate_debug_from_ast_node(cgenv, tst_node); + + if (tst_def->generate(cgenv, test)) { + + if (jump_true) { + sieve_operation_emit(cgenv->sblock, NULL, + &sieve_jmptrue_operation); + } else { + sieve_operation_emit(cgenv->sblock, NULL, + &sieve_jmpfalse_operation); + } + sieve_jumplist_add( + jlist, + sieve_binary_emit_offset(cgenv->sblock, 0)); + return TRUE; + } + + return FALSE; + } + + return TRUE; +} + +static bool +sieve_generate_command(const struct sieve_codegen_env *cgenv, + struct sieve_ast_node *cmd_node) +{ + struct sieve_command *command; + const struct sieve_command_def *cmd_def; + + i_assert(cmd_node->command != NULL && cmd_node->command->def != NULL); + + command = cmd_node->command; + cmd_def = command->def; + + if (cmd_def->generate != NULL) { + sieve_generate_debug_from_ast_node(cgenv, cmd_node); + + return cmd_def->generate(cgenv, command); + } + + return TRUE; +} + +bool sieve_generate_block(const struct sieve_codegen_env *cgenv, + struct sieve_ast_node *block) +{ + bool result = TRUE; + struct sieve_ast_node *cmd_node; + + T_BEGIN { + cmd_node = sieve_ast_command_first(block); + while (result && cmd_node != NULL) { + result = sieve_generate_command(cgenv, cmd_node); + cmd_node = sieve_ast_command_next(cmd_node); + } + } T_END; + + return result; +} + +struct sieve_binary * +sieve_generator_run(struct sieve_generator *gentr, + struct sieve_binary_block **sblock_r) +{ + bool topmost = (sblock_r == NULL || *sblock_r == NULL); + struct sieve_binary *sbin; + struct sieve_binary_block *sblock, *debug_block; + const struct sieve_extension *const *extensions; + unsigned int i, ext_count; + bool result = TRUE; + + /* Initialize */ + + if (topmost) { + sbin = sieve_binary_create_new( + sieve_ast_script(gentr->genenv.ast)); + sblock = sieve_binary_block_get( + sbin, SBIN_SYSBLOCK_MAIN_PROGRAM); + } else { + sblock = *sblock_r; + sbin = sieve_binary_block_get_binary(sblock); + } + + i_assert(sbin != NULL); + + gentr->genenv.sbin = sbin; + gentr->genenv.sblock = sblock; + sieve_binary_ref(gentr->genenv.sbin); + + /* Create debug block */ + debug_block = sieve_binary_block_create(sbin); + gentr->dwriter = sieve_binary_debug_writer_init(debug_block); + (void)sieve_binary_emit_unsigned( + sblock, sieve_binary_block_get_id(debug_block)); + + /* Load extensions linked to the AST and emit a list in code */ + extensions = sieve_ast_extensions_get(gentr->genenv.ast, &ext_count); + (void) sieve_binary_emit_unsigned(sblock, ext_count); + for (i = 0; i < ext_count; i++) { + const struct sieve_extension *ext = extensions[i]; + bool deferred; + + /* Link to binary */ + (void)sieve_binary_extension_link(sbin, ext); + + /* Emit */ + sieve_binary_emit_extension(sblock, ext, 0); + + /* Emit deferred flag */ + deferred = !sieve_ast_extension_is_required( + gentr->genenv.ast, ext); + sieve_binary_emit_byte(sblock, (deferred ? 1 : 0)); + + /* Load */ + if (ext->def != NULL && ext->def->generator_load != NULL && + !ext->def->generator_load(ext, &gentr->genenv)) + result = FALSE; + } + + /* Generate code */ + + if (result) { + if (!sieve_generate_block(&gentr->genenv, + sieve_ast_root(gentr->genenv.ast))) { + result = FALSE; + } else if (topmost) { + sieve_binary_activate(sbin); + } + } + + /* Cleanup */ + + sieve_binary_unref(&gentr->genenv.sbin); + gentr->genenv.sblock = NULL; + + if (!result) { + if (topmost) { + sieve_binary_unref(&sbin); + if (sblock_r != NULL) + *sblock_r = NULL; + } + sbin = NULL; + } else { + if (sblock_r != NULL) + *sblock_r = sblock; + } + + return sbin; +} + +/* + * Error handling + */ + +#undef sieve_generator_error +void sieve_generator_error(struct sieve_generator *gentr, + const char *csrc_filename, unsigned int csrc_linenum, + unsigned int source_line, const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_ERROR, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + }; + va_list args; + + params.location = + sieve_error_script_location(gentr->genenv.script, source_line); + + va_start(args, fmt); + sieve_logv(gentr->ehandler, ¶ms, fmt, args); + va_end(args); +} + +#undef sieve_generator_warning +void sieve_generator_warning(struct sieve_generator *gentr, + const char *csrc_filename, + unsigned int csrc_linenum, + unsigned int source_line, const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_WARNING, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + }; + va_list args; + + params.location = + sieve_error_script_location(gentr->genenv.script, source_line); + + va_start(args, fmt); + sieve_logv(gentr->ehandler, ¶ms, fmt, args); + va_end(args); +} + +#undef sieve_generator_critical +void sieve_generator_critical(struct sieve_generator *gentr, + const char *csrc_filename, + unsigned int csrc_linenum, + unsigned int source_line, const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_ERROR, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + }; + va_list args; + + params.location = + sieve_error_script_location(gentr->genenv.script, source_line); + + va_start(args, fmt); + sieve_criticalv(gentr->genenv.svinst, gentr->ehandler, ¶ms, + "Code generation failed", fmt, args); + va_end(args); +} diff --git a/pigeonhole/src/lib-sieve/sieve-generator.h b/pigeonhole/src/lib-sieve/sieve-generator.h new file mode 100644 index 0000000..fab2023 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-generator.h @@ -0,0 +1,121 @@ +#ifndef SIEVE_GENERATOR_H +#define SIEVE_GENERATOR_H + +#include "sieve-common.h" + +/* + * Code generator + */ + +struct sieve_generator; + +struct sieve_codegen_env { + struct sieve_generator *gentr; + + struct sieve_instance *svinst; + enum sieve_compile_flags flags; + + struct sieve_script *script; + struct sieve_ast *ast; + + struct sieve_binary *sbin; + struct sieve_binary_block *sblock; +}; + +struct sieve_generator * +sieve_generator_create(struct sieve_ast *ast, + struct sieve_error_handler *ehandler, + enum sieve_compile_flags flags); +void sieve_generator_free(struct sieve_generator **generator); + +/* + * Accessors + */ + +struct sieve_error_handler * +sieve_generator_error_handler(struct sieve_generator *gentr); +pool_t sieve_generator_pool(struct sieve_generator *gentr); +struct sieve_script *sieve_generator_script(struct sieve_generator *gentr); +struct sieve_binary *sieve_generator_get_binary(struct sieve_generator *gentr); +struct sieve_binary_block * +sieve_generator_get_block(struct sieve_generator *gentr); + +/* + * Extension support + */ + +void sieve_generator_extension_set_context(struct sieve_generator *gentr, + const struct sieve_extension *ext, + void *context); +const void * +sieve_generator_extension_get_context(struct sieve_generator *gentr, + const struct sieve_extension *ext); + +/* + * Jump list + */ + +struct sieve_jumplist { + pool_t pool; + struct sieve_binary_block *block; + ARRAY(sieve_size_t) jumps; +}; + +struct sieve_jumplist * +sieve_jumplist_create(pool_t pool, struct sieve_binary_block *sblock); +void sieve_jumplist_init_temp(struct sieve_jumplist *jlist, + struct sieve_binary_block *sblock); +void sieve_jumplist_reset(struct sieve_jumplist *jlist); +void sieve_jumplist_add(struct sieve_jumplist *jlist, sieve_size_t jump); +void sieve_jumplist_resolve(struct sieve_jumplist *jlist); + +/* + * Code generation API + */ + +bool sieve_generate_argument(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, + struct sieve_command *cmd); +bool sieve_generate_arguments(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd, + struct sieve_ast_argument **last_arg_r); +bool sieve_generate_argument_parameters(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd, + struct sieve_ast_argument *arg); + +bool sieve_generate_block(const struct sieve_codegen_env *cgenv, + struct sieve_ast_node *block); +bool sieve_generate_test(const struct sieve_codegen_env *cgenv, + struct sieve_ast_node *tst_node, + struct sieve_jumplist *jlist, bool jump_true); +struct sieve_binary * +sieve_generator_run(struct sieve_generator *gentr, + struct sieve_binary_block **sblock_r); + +/* + * Error handling + */ + +void sieve_generator_error(struct sieve_generator *gentr, + const char *csrc_filename, unsigned int csrc_linenum, + unsigned int source_line, const char *fmt, ...) + ATTR_FORMAT(5, 6); +#define sieve_generator_error(gentr, ...) \ + sieve_generator_error(gentr, __FILE__, __LINE__, __VA_ARGS__) +void sieve_generator_warning(struct sieve_generator *gentr, + const char *csrc_filename, + unsigned int csrc_linenum, + unsigned int source_line, const char *fmt, ...) + ATTR_FORMAT(5, 6); +#define sieve_generator_warning(gentr, ...) \ + sieve_generator_warning(gentr, __FILE__, __LINE__, __VA_ARGS__) +void sieve_generator_critical(struct sieve_generator *gentr, + const char *csrc_filename, + unsigned int csrc_linenum, + unsigned int source_line, const char *fmt, ...) + ATTR_FORMAT(5, 6); +#define sieve_generator_critical(gentr, ...) \ + sieve_generator_critical(gentr, __FILE__, __LINE__, __VA_ARGS__) + +#endif + diff --git a/pigeonhole/src/lib-sieve/sieve-interpreter.c b/pigeonhole/src/lib-sieve/sieve-interpreter.c new file mode 100644 index 0000000..274e142 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-interpreter.c @@ -0,0 +1,1196 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "ostream.h" +#include "mempool.h" +#include "array.h" +#include "hash.h" +#include "cpu-limit.h" +#include "mail-storage.h" + +#include "sieve-common.h" +#include "sieve-limits.h" +#include "sieve-script.h" +#include "sieve-error.h" +#include "sieve-extensions.h" +#include "sieve-message.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-actions.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-result.h" +#include "sieve-comparators.h" +#include "sieve-runtime-trace.h" + +#include "sieve-interpreter.h" + +#include <string.h> + +static struct event_category event_category_sieve_runtime = { + .parent = &event_category_sieve, + .name = "sieve-runtime", +}; + +/* + * Interpreter extension + */ + +struct sieve_interpreter_extension_reg { + const struct sieve_interpreter_extension *intext; + const struct sieve_extension *ext; + + void *context; + + bool deferred:1; + bool started:1; +}; + +/* + * Code loop + */ + +struct sieve_interpreter_loop { + unsigned int level; + sieve_size_t begin, end; + const struct sieve_extension_def *ext_def; + pool_t pool; + void *context; +}; + +/* + * Interpreter + */ + +struct sieve_interpreter { + pool_t pool; + struct sieve_interpreter *parent; + + /* Runtime data for extensions */ + ARRAY(struct sieve_interpreter_extension_reg) extensions; + + sieve_size_t reset_vector; + + /* Execution status */ + sieve_size_t pc; /* Program counter */ + + /* Loop stack */ + ARRAY(struct sieve_interpreter_loop) loop_stack; + sieve_size_t loop_limit; + unsigned int parent_loop_level; + + /* Runtime environment */ + struct sieve_runtime_env runenv; + struct sieve_runtime_trace trace; + struct sieve_resource_usage rusage; + + /* Current operation */ + struct sieve_operation oprtn; + + /* Location information */ + struct sieve_binary_debug_reader *dreader; + unsigned int command_line; + + bool running:1; /* Interpreter is running + (may be interrupted) */ + bool interrupted:1; /* Interpreter interrupt requested */ + bool test_result:1; /* Result of previous test command */ +}; + +static struct sieve_interpreter * +_sieve_interpreter_create(struct sieve_binary *sbin, + struct sieve_binary_block *sblock, + struct sieve_script *script, + struct sieve_interpreter *parent, + const struct sieve_execute_env *eenv, + struct sieve_error_handler *ehandler) ATTR_NULL(3, 4) +{ + const struct sieve_script_env *senv = eenv->scriptenv; + unsigned int i, ext_count; + struct sieve_interpreter *interp; + pool_t pool; + struct sieve_instance *svinst; + const struct sieve_extension *const *ext_preloaded; + unsigned int debug_block_id; + sieve_size_t *address; + bool success = TRUE; + + pool = pool_alloconly_create("sieve_interpreter", 4096); + interp = p_new(pool, struct sieve_interpreter, 1); + interp->parent = parent; + interp->pool = pool; + + interp->runenv.ehandler = ehandler; + sieve_error_handler_ref(ehandler); + + interp->runenv.exec_env = eenv; + interp->runenv.interp = interp; + interp->runenv.oprtn = &interp->oprtn; + interp->runenv.sbin = sbin; + interp->runenv.sblock = sblock; + sieve_binary_ref(sbin); + + interp->runenv.event = event_create(eenv->event); + event_add_category(interp->runenv.event, &event_category_sieve_runtime); + event_add_str(interp->runenv.event, "script_name", + sieve_binary_script_name(sbin)); + event_add_str(interp->runenv.event, "script_location", + sieve_binary_script_location(sbin)); + event_add_str(interp->runenv.event, "binary_path", + sieve_binary_path(sbin)); + + svinst = sieve_binary_svinst(sbin); + + if (senv->trace_log != NULL) { + interp->trace.log = senv->trace_log; + interp->trace.config = senv->trace_config; + interp->trace.indent = 0; + interp->runenv.trace = &interp->trace; + } + + if (script == NULL) + interp->runenv.script = sieve_binary_script(sbin); + else + interp->runenv.script = script; + + interp->runenv.pc = 0; + address = &(interp->runenv.pc); + + sieve_runtime_trace_begin(&(interp->runenv)); + + p_array_init(&interp->extensions, pool, + sieve_extensions_get_count(svinst)); + + interp->parent_loop_level = 0; + if (parent != NULL && array_is_created(&parent->loop_stack)) { + interp->parent_loop_level = parent->parent_loop_level + + array_count(&parent->loop_stack); + } + + /* Pre-load core language features implemented as 'extensions' */ + ext_preloaded = sieve_extensions_get_preloaded(svinst, &ext_count); + for (i = 0; i < ext_count; i++) { + const struct sieve_extension_def *ext_def = + ext_preloaded[i]->def; + + if (ext_def != NULL && ext_def->interpreter_load != NULL) { + (void)ext_def->interpreter_load(ext_preloaded[i], + &interp->runenv, + address); + } + } + + /* Load debug block */ + if (sieve_binary_read_unsigned(sblock, address, &debug_block_id)) { + struct sieve_binary_block *debug_block = + sieve_binary_block_get(sbin, debug_block_id); + + if (debug_block == NULL) { + sieve_runtime_trace_error(&interp->runenv, + "invalid id for debug block"); + success = FALSE; + } else { + /* Initialize debug reader */ + interp->dreader = + sieve_binary_debug_reader_init(debug_block); + } + } + + /* Load other extensions listed in code */ + if (success && sieve_binary_read_unsigned(sblock, address, + &ext_count)) { + + for (i = 0; i < ext_count; i++) { + unsigned int code = 0, deferred; + struct sieve_interpreter_extension_reg *reg; + const struct sieve_extension *ext; + + if (!sieve_binary_read_extension(sblock, address, + &code, &ext) || + !sieve_binary_read_byte(sblock, address, + &deferred)) { + success = FALSE; + break; + } + + if (deferred > 0 && ext->id >= 0) { + reg = array_idx_get_space( + &interp->extensions, + (unsigned int)ext->id); + reg->deferred = TRUE; + } + + if (ext->def != NULL) { + if (ext->global && + (eenv->flags & SIEVE_EXECUTE_FLAG_NOGLOBAL) != 0) { + sieve_runtime_error(&interp->runenv, NULL, + "failed to enable extension `%s': " + "its use is restricted to global scripts", + sieve_extension_name(ext)); + success = FALSE; + break; + } + + if (ext->def->interpreter_load != NULL && + !ext->def->interpreter_load(ext, &interp->runenv, + address)) { + success = FALSE; + break; + } + } + } + } else { + success = FALSE; + } + + if (!success) { + sieve_interpreter_free(&interp); + interp = NULL; + } else { + interp->reset_vector = *address; + } + + return interp; +} + +struct sieve_interpreter * +sieve_interpreter_create(struct sieve_binary *sbin, + struct sieve_interpreter *parent, + const struct sieve_execute_env *eenv, + struct sieve_error_handler *ehandler) +{ + struct sieve_binary_block *sblock; + + if ((sblock = sieve_binary_block_get( + sbin, SBIN_SYSBLOCK_MAIN_PROGRAM)) == NULL) + return NULL; + + return _sieve_interpreter_create(sbin, sblock, NULL, parent, eenv, + ehandler); +} + +struct sieve_interpreter * +sieve_interpreter_create_for_block(struct sieve_binary_block *sblock, + struct sieve_script *script, + struct sieve_interpreter *parent, + const struct sieve_execute_env *eenv, + struct sieve_error_handler *ehandler) +{ + if (sblock == NULL) return NULL; + + return _sieve_interpreter_create(sieve_binary_block_get_binary(sblock), + sblock, script, parent, eenv, + ehandler); +} + +void sieve_interpreter_free(struct sieve_interpreter **_interp) +{ + struct sieve_interpreter *interp = *_interp; + struct sieve_runtime_env *renv = &interp->runenv; + const struct sieve_interpreter_extension_reg *eregs; + struct sieve_interpreter_loop *loops; + unsigned int count, i; + + if (interp->running) { + struct event_passthrough *e = + event_create_passthrough(interp->runenv.event)-> + set_name("sieve_runtime_script_finished")-> + add_str("error", "Aborted"); + e_debug(e->event(), "Aborted running script `%s'", + sieve_binary_source(interp->runenv.sbin)); + + interp->running = FALSE; + } + + if (array_is_created(&interp->loop_stack)) { + loops = array_get_modifiable(&interp->loop_stack, &count); + for (i = 0; i < count; i++) + pool_unref(&loops[i].pool); + } + + interp->trace.indent = 0; + sieve_runtime_trace_end(renv); + + /* Signal registered extensions that the interpreter is being destroyed */ + eregs = array_get(&interp->extensions, &count); + for (i = 0; i < count; i++) { + if (eregs[i].intext != NULL && eregs[i].intext->free != NULL) { + eregs[i].intext->free(eregs[i].ext, interp, + eregs[i].context); + } + } + + sieve_binary_debug_reader_deinit(&interp->dreader); + sieve_binary_unref(&renv->sbin); + sieve_error_handler_unref(&renv->ehandler); + event_unref(&renv->event); + + pool_unref(&interp->pool); + *_interp = NULL; +} + +/* + * Accessors + */ + +pool_t sieve_interpreter_pool(struct sieve_interpreter *interp) +{ + return interp->pool; +} + +struct sieve_interpreter * +sieve_interpreter_get_parent(struct sieve_interpreter *interp) +{ + return interp->parent; +} + +struct sieve_script *sieve_interpreter_script(struct sieve_interpreter *interp) +{ + return interp->runenv.script; +} + +struct sieve_error_handler * +sieve_interpreter_get_error_handler(struct sieve_interpreter *interp) +{ + return interp->runenv.ehandler; +} + +struct sieve_instance * +sieve_interpreter_svinst(struct sieve_interpreter *interp) +{ + return interp->runenv.exec_env->svinst; +} + +/* Do not use this function for normal sieve extensions. This is intended for + * the testsuite only. + */ +void sieve_interpreter_set_result(struct sieve_interpreter *interp, + struct sieve_result *result) +{ + sieve_result_unref(&interp->runenv.result); + interp->runenv.result = result; + interp->runenv.msgctx = sieve_result_get_message_context(result); + sieve_result_ref(result); +} + +/* + * Source location + */ + +unsigned int +sieve_runtime_get_source_location(const struct sieve_runtime_env *renv, + sieve_size_t code_address) +{ + struct sieve_interpreter *interp = renv->interp; + + if (interp->dreader == NULL) + return 0; + + if (interp->command_line == 0) { + interp->command_line = + sieve_binary_debug_read_line(interp->dreader, + renv->oprtn->address); + } + + return sieve_binary_debug_read_line(interp->dreader, code_address); +} + +unsigned int +sieve_runtime_get_command_location(const struct sieve_runtime_env *renv) +{ + struct sieve_interpreter *interp = renv->interp; + + if (interp->dreader == NULL) + return 0; + + if (interp->command_line == 0) { + interp->command_line = + sieve_binary_debug_read_line(interp->dreader, + renv->oprtn->address); + } + + return interp->command_line; +} + +const char * +sieve_runtime_get_full_command_location(const struct sieve_runtime_env *renv) +{ + return sieve_error_script_location( + renv->script, sieve_runtime_get_command_location(renv)); +} + +/* + * Extension support + */ + +void sieve_interpreter_extension_register( + struct sieve_interpreter *interp, const struct sieve_extension *ext, + const struct sieve_interpreter_extension *intext, void *context) +{ + struct sieve_interpreter_extension_reg *reg; + + if (ext->id < 0) + return; + + reg = array_idx_get_space(&interp->extensions, (unsigned int) ext->id); + reg->intext = intext; + reg->ext = ext; + reg->context = context; +} + +void sieve_interpreter_extension_set_context(struct sieve_interpreter *interp, + const struct sieve_extension *ext, + void *context) +{ + struct sieve_interpreter_extension_reg *reg; + + if (ext->id < 0) + return; + + reg = array_idx_get_space(&interp->extensions, (unsigned int) ext->id); + reg->context = context; +} + +void *sieve_interpreter_extension_get_context(struct sieve_interpreter *interp, + const struct sieve_extension *ext) +{ + const struct sieve_interpreter_extension_reg *reg; + + if (ext->id < 0 || ext->id >= (int) array_count(&interp->extensions)) + return NULL; + + reg = array_idx(&interp->extensions, (unsigned int) ext->id); + + return reg->context; +} + +int sieve_interpreter_extension_start(struct sieve_interpreter *interp, + const struct sieve_extension *ext) +{ + struct sieve_interpreter_extension_reg *reg; + int ret; + + i_assert(ext->id >= 0); + + if (ext->id >= (int) array_count(&interp->extensions)) + return SIEVE_EXEC_OK; + + reg = array_idx_modifiable(&interp->extensions, (unsigned int)ext->id); + + if (!reg->deferred) + return SIEVE_EXEC_OK; + reg->deferred = FALSE; + reg->started = TRUE; + + if (reg->intext != NULL && reg->intext->run != NULL && + (ret = reg->intext->run(ext, &interp->runenv, + reg->context, TRUE)) <= 0) + return ret; + return SIEVE_EXEC_OK; +} + +/* + * Loop handling + */ + +int sieve_interpreter_loop_start(struct sieve_interpreter *interp, + sieve_size_t loop_end, + const struct sieve_extension_def *ext_def, + struct sieve_interpreter_loop **loop_r) +{ + const struct sieve_runtime_env *renv = &interp->runenv; + struct sieve_interpreter_loop *loop; + + i_assert(loop_end > interp->runenv.pc); + + /* Check supplied end offset */ + if (loop_end > sieve_binary_block_get_size(renv->sblock)) { + sieve_runtime_trace_error(renv, "loop end offset out of range"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + /* Trace */ + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) { + unsigned int line = + sieve_runtime_get_source_location(renv, loop_end); + + if (sieve_runtime_trace_hasflag(renv, SIEVE_TRFLG_ADDRESSES)) { + sieve_runtime_trace(renv, 0, + "loop ends at line %d [%08llx]", + line, + (long long unsigned int) loop_end); + } else { + sieve_runtime_trace(renv, 0, + "loop ends at line %d", line); + } + } + + /* Check loop nesting limit */ + if (!array_is_created(&interp->loop_stack)) + p_array_init(&interp->loop_stack, interp->pool, 8); + if ((interp->parent_loop_level + + array_count(&interp->loop_stack)) >= SIEVE_MAX_LOOP_DEPTH) { + /* Should normally be caught at compile time */ + sieve_runtime_error(renv, NULL, + "new program loop exceeds " + "the nesting limit (<= %u levels)", + SIEVE_MAX_LOOP_DEPTH); + return SIEVE_EXEC_FAILURE; + } + + /* Create new loop */ + loop = array_append_space(&interp->loop_stack); + loop->level = array_count(&interp->loop_stack)-1; + loop->ext_def = ext_def; + loop->begin = interp->runenv.pc; + loop->end = loop_end; + loop->pool = pool_alloconly_create("sieve_interpreter", 128); + + /* Set new loop limit */ + interp->loop_limit = loop_end; + + *loop_r = loop; + return SIEVE_EXEC_OK; +} + +struct sieve_interpreter_loop * +sieve_interpreter_loop_get(struct sieve_interpreter *interp, + sieve_size_t loop_end, + const struct sieve_extension_def *ext_def) +{ + struct sieve_interpreter_loop *loops; + unsigned int count, i; + + if (!array_is_created(&interp->loop_stack)) + return NULL; + + loops = array_get_modifiable(&interp->loop_stack, &count); + for (i = count; i > 0; i--) { + /* We're really making sure our loop matches */ + if (loops[i-1].end == loop_end && + loops[i-1].ext_def == ext_def) + return &loops[i-1]; + } + return NULL; +} + +int sieve_interpreter_loop_next(struct sieve_interpreter *interp, + struct sieve_interpreter_loop *loop, + sieve_size_t loop_begin) +{ + const struct sieve_runtime_env *renv = &interp->runenv; + struct sieve_interpreter_loop *loops; + unsigned int count; + + /* Trace */ + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) { + unsigned int line = + sieve_runtime_get_source_location(renv, loop_begin); + + if (sieve_runtime_trace_hasflag(renv, SIEVE_TRFLG_ADDRESSES)) { + sieve_runtime_trace(renv, 0, + "looping back to line %d [%08llx]", + line, + (long long unsigned int) loop_begin); + } else { + sieve_runtime_trace(renv, 0, + "looping back to line %d", line); + } + } + + /* Check the code for corruption */ + if (loop->begin != loop_begin) { + sieve_runtime_trace_error(renv, "loop begin offset invalid"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + /* Check invariants */ + i_assert(array_is_created(&interp->loop_stack)); + loops = array_get_modifiable(&interp->loop_stack, &count); + i_assert(&loops[count-1] == loop); + + /* Return to beginning */ + interp->runenv.pc = loop_begin; + return SIEVE_EXEC_OK; +} + +int sieve_interpreter_loop_break(struct sieve_interpreter *interp, + struct sieve_interpreter_loop *loop) +{ + const struct sieve_runtime_env *renv = &interp->runenv; + struct sieve_interpreter_loop *loops; + sieve_size_t loop_end = loop->end; + unsigned int count, i; + + /* Find the loop */ + i_assert(array_is_created(&interp->loop_stack)); + loops = array_get_modifiable(&interp->loop_stack, &count); + i_assert(count > 0); + + i = count; + do { + pool_unref(&loops[i-1].pool); + i--; + } while (i > 0 && &loops[i] != loop); + i_assert(&loops[i] == loop); + + /* Set new loop limit */ + if (i > 0) + interp->loop_limit = loops[i].end; + else + interp->loop_limit = 0; + + /* Delete it and all deeper loops */ + array_delete(&interp->loop_stack, i, count - i); + + /* Trace */ + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) { + unsigned int jmp_line = + sieve_runtime_get_source_location(renv, loop_end); + + if (sieve_runtime_trace_hasflag(renv, SIEVE_TRFLG_ADDRESSES)) { + sieve_runtime_trace(renv, 0, + "exiting loops at line %d [%08llx]", + jmp_line, + (long long unsigned int) loop_end); + } else { + sieve_runtime_trace(renv, 0, + "exiting loops at line %d", + jmp_line); + } + } + + /* Exit loop */ + interp->runenv.pc = loop->end; + return SIEVE_EXEC_OK; +} + +static int +sieve_interpreter_loop_break_out(struct sieve_interpreter *interp, + sieve_size_t target) +{ + struct sieve_interpreter_loop *loops; + unsigned int count, i; + + if (!array_is_created(&interp->loop_stack)) + return SIEVE_EXEC_OK; + + loops = array_get_modifiable(&interp->loop_stack, &count); + for (i = count; i > 0; i--) { + /* We're really making sure our loop matches */ + if (loops[i-1].end > target) + break; + } + if (i == count) + return SIEVE_EXEC_OK; + + return sieve_interpreter_loop_break(interp, &loops[i]); +} + +struct sieve_interpreter_loop * +sieve_interpreter_loop_get_local(struct sieve_interpreter *interp, + struct sieve_interpreter_loop *loop, + const struct sieve_extension_def *ext_def) +{ + struct sieve_interpreter_loop *loops; + unsigned int count, i; + + if (!array_is_created(&interp->loop_stack)) + return NULL; + + loops = array_get_modifiable(&interp->loop_stack, &count); + i_assert(loop == NULL || loop->level < count); + + for (i = (loop == NULL ? count : loop->level); i > 0; i--) { + if (ext_def == NULL || loops[i-1].ext_def == ext_def) + return &loops[i-1]; + } + return NULL; +} + +struct sieve_interpreter_loop * +sieve_interpreter_loop_get_global(struct sieve_interpreter *interp, + struct sieve_interpreter_loop *loop, + const struct sieve_extension_def *ext_def) +{ + struct sieve_interpreter_loop *result; + + while (interp != NULL) { + result = sieve_interpreter_loop_get_local(interp, loop, + ext_def); + if (result != NULL) + return result; + interp = interp->parent; + } + return NULL; +} + +pool_t sieve_interpreter_loop_get_pool(struct sieve_interpreter_loop *loop) +{ + return loop->pool; +} + +void *sieve_interpreter_loop_get_context(struct sieve_interpreter_loop *loop) +{ + return loop->context; +} + +void sieve_interpreter_loop_set_context(struct sieve_interpreter_loop *loop, + void *context) +{ + loop->context = context; +} + +/* + * Program flow + */ + +void sieve_interpreter_reset(struct sieve_interpreter *interp) +{ + interp->runenv.pc = interp->reset_vector; + interp->interrupted = FALSE; + interp->test_result = FALSE; + interp->runenv.result = NULL; +} + +void sieve_interpreter_interrupt(struct sieve_interpreter *interp) +{ + interp->interrupted = TRUE; +} + +sieve_size_t sieve_interpreter_program_counter(struct sieve_interpreter *interp) +{ + return interp->runenv.pc; +} + +static int +sieve_interpreter_check_program_jump(struct sieve_interpreter *interp, + sieve_size_t jmp_target, bool break_loops) +{ + const struct sieve_runtime_env *renv = &interp->runenv; + sieve_size_t loop_limit = (break_loops ? 0 : interp->loop_limit); + + if (jmp_target == 0 || + jmp_target > sieve_binary_block_get_size(renv->sblock) || + (loop_limit > 0 && jmp_target >= loop_limit)) { + if (interp->loop_limit != 0) { + sieve_runtime_trace_error( + renv, "jump target crosses loop boundary"); + } else { + sieve_runtime_trace_error( + renv, "jump target out of range"); + } + return SIEVE_EXEC_BIN_CORRUPT; + } + return SIEVE_EXEC_OK; +} + +static int +sieve_interpreter_do_program_jump(struct sieve_interpreter *interp, + sieve_size_t jmp_target, bool break_loops) +{ + const struct sieve_runtime_env *renv = &interp->runenv; + sieve_size_t *address = &(interp->runenv.pc); + int ret; + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) { + unsigned int jmp_line = + sieve_runtime_get_source_location(renv, jmp_target); + + if (sieve_runtime_trace_hasflag(renv, SIEVE_TRFLG_ADDRESSES)) { + sieve_runtime_trace(renv, 0, "jumping to line %d [%08llx]", + jmp_line, + (long long unsigned int)jmp_target); + } else { + sieve_runtime_trace(renv, 0, "jumping to line %d", + jmp_line); + } + } + + if (break_loops && + (ret = sieve_interpreter_loop_break_out(interp, + jmp_target)) <= 0) + return ret; + + *address = jmp_target; + return SIEVE_EXEC_OK; +} + +int sieve_interpreter_program_jump_to(struct sieve_interpreter *interp, + sieve_size_t jmp_target, + bool break_loops) +{ + int ret; + + ret = sieve_interpreter_check_program_jump(interp, jmp_target, + break_loops); + if (ret <= 0) + return ret; + + return sieve_interpreter_do_program_jump( + interp, jmp_target, break_loops); +} + +int sieve_interpreter_program_jump(struct sieve_interpreter *interp, + bool jump, bool break_loops) +{ + const struct sieve_runtime_env *renv = &interp->runenv; + sieve_size_t *address = &(interp->runenv.pc); + sieve_size_t jmp_start = *address, jmp_target; + sieve_offset_t jmp_offset; + int ret; + + if (!sieve_binary_read_offset(renv->sblock, address, &jmp_offset)) { + sieve_runtime_trace_error(renv, "invalid jump offset"); + return SIEVE_EXEC_BIN_CORRUPT; + } + jmp_target = jmp_start + jmp_offset; + + ret = sieve_interpreter_check_program_jump(interp, jmp_target, + break_loops); + if (ret <= 0) + return ret; + + if (!jump) { + sieve_runtime_trace(renv, 0, "not jumping"); + return SIEVE_EXEC_OK; + } + + return sieve_interpreter_do_program_jump( + interp, jmp_target, break_loops); +} + +/* + * Test results + */ + +void sieve_interpreter_set_test_result(struct sieve_interpreter *interp, + bool result) +{ + interp->test_result = result; +} + +bool sieve_interpreter_get_test_result(struct sieve_interpreter *interp) +{ + return interp->test_result; +} + +/* + * Code execute + */ + +static int sieve_interpreter_operation_execute(struct sieve_interpreter *interp) +{ + struct sieve_operation *oprtn = &(interp->oprtn); + sieve_size_t *address = &(interp->runenv.pc); + + sieve_runtime_trace_toplevel(&interp->runenv); + + /* Read the operation */ + if (sieve_operation_read(interp->runenv.sblock, address, oprtn)) { + const struct sieve_operation_def *op = oprtn->def; + int result = SIEVE_EXEC_OK; + + /* Reset cached command location */ + interp->command_line = 0; + + /* Execute the operation */ + if (op->execute != NULL) { /* Noop ? */ + T_BEGIN { + result = op->execute(&(interp->runenv), + address); + } T_END; + } else { + sieve_runtime_trace(&interp->runenv, + SIEVE_TRLVL_COMMANDS, + "OP: %s (NOOP)", + sieve_operation_mnemonic(oprtn)); + } + + return result; + } + + /* Binary corrupt */ + sieve_runtime_trace_error(&interp->runenv, + "Encountered invalid operation"); + return SIEVE_EXEC_BIN_CORRUPT; +} + +int sieve_interpreter_continue(struct sieve_interpreter *interp, + bool *interrupted) +{ + const struct sieve_runtime_env *renv = &interp->runenv; + const struct sieve_execute_env *eenv = renv->exec_env; + struct cpu_limit *climit = NULL; + sieve_size_t *address = &(interp->runenv.pc); + struct sieve_instance *svinst = eenv->svinst; + struct sieve_exec_status *exec_status = eenv->exec_status; + struct sieve_resource_usage rusage; + int ret = SIEVE_EXEC_OK; + + sieve_result_ref(renv->result); + interp->interrupted = FALSE; + + if (interrupted != NULL) + *interrupted = FALSE; + + if (svinst->max_cpu_time_secs > 0) { + climit = cpu_limit_init(svinst->max_cpu_time_secs, + CPU_LIMIT_TYPE_USER); + } + + while (ret == SIEVE_EXEC_OK && !interp->interrupted && + *address < sieve_binary_block_get_size(renv->sblock)) { + if (climit != NULL && cpu_limit_exceeded(climit)) { + sieve_runtime_error( + renv, NULL, + "execution exceeded CPU time limit"); + ret = SIEVE_EXEC_RESOURCE_LIMIT; + break; + } + if (interp->loop_limit != 0 && *address > interp->loop_limit) { + sieve_runtime_trace_error( + renv, "program crossed loop boundary"); + ret = SIEVE_EXEC_BIN_CORRUPT; + break; + } + + ret = sieve_interpreter_operation_execute(interp); + } + + if (climit != NULL) { + sieve_resource_usage_init(&rusage); + rusage.cpu_time_msecs = + cpu_limit_get_usage_msecs(climit, CPU_LIMIT_TYPE_USER); + sieve_resource_usage_add(&interp->rusage, &rusage); + + cpu_limit_deinit(&climit); + } + + if (ret != SIEVE_EXEC_OK) { + sieve_runtime_trace(&interp->runenv, SIEVE_TRLVL_NONE, + "[[EXECUTION ABORTED]]"); + } + + if (interrupted != NULL) + *interrupted = interp->interrupted; + + if (!interp->interrupted) { + exec_status->resource_usage = interp->rusage; + + struct event_passthrough *e = + event_create_passthrough(interp->runenv.event)-> + set_name("sieve_runtime_script_finished"); + switch (ret) { + case SIEVE_EXEC_OK: + break; + case SIEVE_EXEC_FAILURE: + e->add_str("error", "Failed"); + break; + case SIEVE_EXEC_TEMP_FAILURE: + e->add_str("error", "Failed temporarily"); + break; + case SIEVE_EXEC_BIN_CORRUPT: + e->add_str("error", "Binary corrupt"); + break; + case SIEVE_EXEC_RESOURCE_LIMIT: + e->add_str("error", "Resource limit exceeded"); + break; + case SIEVE_EXEC_KEEP_FAILED: + /* Not supposed to occur at runtime */ + i_unreached(); + } + e_debug(e->event(), "Finished running script `%s' " + "(status=%s, resource usage: %s)", + sieve_binary_source(interp->runenv.sbin), + sieve_execution_exitcode_to_str(ret), + sieve_resource_usage_get_summary(&interp->rusage)); + interp->running = FALSE; + } + + sieve_result_unref(&interp->runenv.result); + return ret; +} + +int sieve_interpreter_start(struct sieve_interpreter *interp, + struct sieve_result *result, bool *interrupted) +{ + struct sieve_interpreter_extension_reg *eregs; + unsigned int ext_count, i; + int ret; + + struct event_passthrough *e = + event_create_passthrough(interp->runenv.event)-> + set_name("sieve_runtime_script_started"); + e_debug(e->event(), "Started running script `%s'", + sieve_binary_source(interp->runenv.sbin)); + + interp->running = TRUE; + interp->runenv.result = result; + interp->runenv.msgctx = sieve_result_get_message_context(result); + + sieve_resource_usage_init(&interp->rusage); + + /* Signal registered extensions that the interpreter is being run */ + eregs = array_get_modifiable(&interp->extensions, &ext_count); + for (i = 0; i < ext_count; i++) { + if (!eregs[i].deferred) { + eregs[i].started = TRUE; + if (eregs[i].intext != NULL && + eregs[i].intext->run != NULL && + (ret = eregs[i].intext->run( + eregs[i].ext, &interp->runenv, + eregs[i].context, FALSE)) <= 0) + return ret; + } + } + + return sieve_interpreter_continue(interp, interrupted); +} + +int sieve_interpreter_run(struct sieve_interpreter *interp, + struct sieve_result *result) +{ + sieve_interpreter_reset(interp); + + return sieve_interpreter_start(interp, result, NULL); +} + +/* + * Error handling + */ + +static inline void ATTR_FORMAT(3, 0) +sieve_runtime_logv(const struct sieve_runtime_env *renv, + const struct sieve_error_params *params, + const char *fmt, va_list args) +{ + struct sieve_error_params new_params = *params; + + new_params.event = renv->event; + T_BEGIN { + if (new_params.location == NULL) { + new_params.location = + sieve_runtime_get_full_command_location(renv); + } + + sieve_logv(renv->ehandler, params, fmt, args); + } T_END; +} + +#undef sieve_runtime_error +void sieve_runtime_error(const struct sieve_runtime_env *renv, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_ERROR, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + .location = location, + }; + va_list args; + + va_start(args, fmt); + sieve_runtime_logv(renv, ¶ms, fmt, args); + va_end(args); +} + +#undef sieve_runtime_warning +void sieve_runtime_warning(const struct sieve_runtime_env *renv, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_WARNING, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + .location = location, + }; + va_list args; + + va_start(args, fmt); + sieve_runtime_logv(renv, ¶ms, fmt, args); + va_end(args); +} + +#undef sieve_runtime_log +void sieve_runtime_log(const struct sieve_runtime_env *renv, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_INFO, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + .location = location, + }; + va_list args; + + va_start(args, fmt); + sieve_runtime_logv(renv, ¶ms, fmt, args); + va_end(args); +} + +#undef sieve_runtime_critical +void sieve_runtime_critical(const struct sieve_runtime_env *renv, + const char *csrc_filename, + unsigned int csrc_linenum, + const char *location, const char *user_prefix, + const char *fmt, ...) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct sieve_error_params params = { + .log_type = LOG_TYPE_ERROR, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + .location = location, + }; + va_list args; + + va_start(args, fmt); + + params.event = renv->event; + T_BEGIN { + if (params.location == NULL) { + params.location = + sieve_runtime_get_full_command_location(renv); + } + + sieve_criticalv(eenv->svinst, renv->ehandler, ¶ms, + user_prefix, fmt, args); + } T_END; + + va_end(args); +} + +#undef sieve_runtime_mail_error +int sieve_runtime_mail_error(const struct sieve_runtime_env *renv, + struct mail *mail, + const char *csrc_filename, + unsigned int csrc_linenum, + const char *fmt, ...) +{ + const char *error_msg, *user_prefix; + va_list args; + + error_msg = mailbox_get_last_internal_error(mail->box, NULL); + + va_start(args, fmt); + user_prefix = t_strdup_vprintf(fmt, args); + sieve_runtime_critical(renv, csrc_filename, csrc_linenum, + NULL, user_prefix, "%s: %s", + user_prefix, error_msg); + va_end(args); + + return SIEVE_EXEC_TEMP_FAILURE; +} diff --git a/pigeonhole/src/lib-sieve/sieve-interpreter.h b/pigeonhole/src/lib-sieve/sieve-interpreter.h new file mode 100644 index 0000000..ec38029 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-interpreter.h @@ -0,0 +1,204 @@ +#ifndef SIEVE_INTERPRETER_H +#define SIEVE_INTERPRETER_H + +#include "lib.h" +#include "array.h" +#include "buffer.h" + +#include "sieve-common.h" +#include "sieve-runtime.h" + +/* + * Interpreter + */ + +struct sieve_interpreter * +sieve_interpreter_create(struct sieve_binary *sbin, + struct sieve_interpreter *parent, + const struct sieve_execute_env *eenv, + struct sieve_error_handler *ehandler) ATTR_NULL(2); +struct sieve_interpreter * +sieve_interpreter_create_for_block(struct sieve_binary_block *sblock, + struct sieve_script *script, + struct sieve_interpreter *parent, + const struct sieve_execute_env *eenv, + struct sieve_error_handler *ehandler) + ATTR_NULL(3); +void sieve_interpreter_free(struct sieve_interpreter **_interp); + +/* + * Accessors + */ + +pool_t sieve_interpreter_pool(struct sieve_interpreter *interp); +struct sieve_interpreter * +sieve_interpreter_get_parent(struct sieve_interpreter *interp); +struct sieve_script *sieve_interpreter_script(struct sieve_interpreter *interp); +struct sieve_error_handler * +sieve_interpreter_get_error_handler(struct sieve_interpreter *interp); +struct sieve_instance * +sieve_interpreter_svinst(struct sieve_interpreter *interp); + +/* Do not use this function for normal sieve extensions. This is intended for + * the testsuite only. + */ +void sieve_interpreter_set_result(struct sieve_interpreter *interp, + struct sieve_result *result); + +/* + * Loop handling + */ + +struct sieve_interpreter_loop; + +int sieve_interpreter_loop_start(struct sieve_interpreter *interp, + sieve_size_t loop_end, + const struct sieve_extension_def *ext_def, + struct sieve_interpreter_loop **loop_r); +struct sieve_interpreter_loop * +sieve_interpreter_loop_get(struct sieve_interpreter *interp, + sieve_size_t loop_end, + const struct sieve_extension_def *ext_def); +int sieve_interpreter_loop_next(struct sieve_interpreter *interp, + struct sieve_interpreter_loop *loop, + sieve_size_t loop_begin); +int sieve_interpreter_loop_break(struct sieve_interpreter *interp, + struct sieve_interpreter_loop *loop); + +struct sieve_interpreter_loop * +sieve_interpreter_loop_get_local(struct sieve_interpreter *interp, + struct sieve_interpreter_loop *loop, + const struct sieve_extension_def *ext_def) + ATTR_NULL(2, 3); +struct sieve_interpreter_loop * +sieve_interpreter_loop_get_global(struct sieve_interpreter *interp, + struct sieve_interpreter_loop *loop, + const struct sieve_extension_def *ext_def) + ATTR_NULL(2, 3); + +pool_t sieve_interpreter_loop_get_pool(struct sieve_interpreter_loop *loop) + ATTR_PURE; +void *sieve_interpreter_loop_get_context(struct sieve_interpreter_loop *loop) + ATTR_PURE; +void sieve_interpreter_loop_set_context(struct sieve_interpreter_loop *loop, + void *context); + +/* + * Program flow + */ + +void sieve_interpreter_reset(struct sieve_interpreter *interp); +void sieve_interpreter_interrupt(struct sieve_interpreter *interp); +sieve_size_t +sieve_interpreter_program_counter(struct sieve_interpreter *interp); + +int sieve_interpreter_program_jump_to(struct sieve_interpreter *interp, + sieve_size_t jmp_target, + bool break_loops); +int sieve_interpreter_program_jump(struct sieve_interpreter *interp, bool jump, + bool break_loops); + +/* + * Test results + */ + +void sieve_interpreter_set_test_result(struct sieve_interpreter *interp, + bool result); +bool sieve_interpreter_get_test_result(struct sieve_interpreter *interp); + +/* + * Source location + */ + +unsigned int +sieve_runtime_get_source_location(const struct sieve_runtime_env *renv, + sieve_size_t code_address); + +unsigned int +sieve_runtime_get_command_location(const struct sieve_runtime_env *renv); +const char * +sieve_runtime_get_full_command_location(const struct sieve_runtime_env *renv); + +/* + * Extension support + */ + +struct sieve_interpreter_extension { + const struct sieve_extension_def *ext_def; + + int (*run)(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + void *context, bool deferred); + void (*free)(const struct sieve_extension *ext, + struct sieve_interpreter *interp, void *context); +}; + +void sieve_interpreter_extension_register( + struct sieve_interpreter *interp, const struct sieve_extension *ext, + const struct sieve_interpreter_extension *intext, void *context); +void sieve_interpreter_extension_set_context( + struct sieve_interpreter *interp, const struct sieve_extension *ext, + void *context); +void *sieve_interpreter_extension_get_context( + struct sieve_interpreter *interp, const struct sieve_extension *ext); + +int sieve_interpreter_extension_start(struct sieve_interpreter *interp, + const struct sieve_extension *ext); + +/* + * Opcodes and operands + */ + +int sieve_interpreter_handle_optional_operands( + const struct sieve_runtime_env *renv, sieve_size_t *address, + struct sieve_side_effects_list **list); + +/* + * Code execute + */ + +int sieve_interpreter_continue(struct sieve_interpreter *interp, + bool *interrupted); +int sieve_interpreter_start(struct sieve_interpreter *interp, + struct sieve_result *result, bool *interrupted); +int sieve_interpreter_run(struct sieve_interpreter *interp, + struct sieve_result *result); + +/* + * Error handling + */ + +void sieve_runtime_error(const struct sieve_runtime_env *renv, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *fmt, ...) + ATTR_FORMAT(5, 6); +#define sieve_runtime_error(renv, ...) \ + sieve_runtime_error(renv, __FILE__, __LINE__, __VA_ARGS__) +void sieve_runtime_warning(const struct sieve_runtime_env *renv, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *fmt, ...) + ATTR_FORMAT(5, 6); +#define sieve_runtime_warning(renv, ...) \ + sieve_runtime_warning(renv, __FILE__, __LINE__, __VA_ARGS__) +void sieve_runtime_log(const struct sieve_runtime_env *renv, + const char *csrc_filename, unsigned int csrc_linenum, + const char *location, const char *fmt, ...) + ATTR_FORMAT(5, 6); +#define sieve_runtime_log(renv, ...) \ + sieve_runtime_log(renv, __FILE__, __LINE__, __VA_ARGS__) +void sieve_runtime_critical(const struct sieve_runtime_env *renv, + const char *csrc_filename, + unsigned int csrc_linenum, + const char *location, const char *user_prefix, + const char *fmt, ...) ATTR_FORMAT(6, 7); +#define sieve_runtime_critical(renv, ...) \ + sieve_runtime_critical(renv, __FILE__, __LINE__, __VA_ARGS__) +int sieve_runtime_mail_error(const struct sieve_runtime_env *renv, + struct mail *mail, + const char *csrc_filename, + unsigned int csrc_linenum, + const char *fmt, ...) ATTR_FORMAT(5, 6); +#define sieve_runtime_mail_error(renv, mail, ...) \ + sieve_runtime_mail_error(renv, mail, __FILE__, __LINE__, __VA_ARGS__) + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-lexer.c b/pigeonhole/src/lib-sieve/sieve-lexer.c new file mode 100644 index 0000000..a6968a9 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-lexer.c @@ -0,0 +1,930 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "compat.h" +#include "str.h" +#include "str-sanitize.h" +#include "istream.h" + +#include "sieve-common.h" +#include "sieve-limits.h" +#include "sieve-error.h" +#include "sieve-script.h" + +#include "sieve-lexer.h" + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <ctype.h> + +/* + * Useful macros + */ + +#define DIGIT_VAL(c) (c - '0') + +/* + * Lexer object + */ + +struct sieve_lexical_scanner { + pool_t pool; + struct sieve_instance *svinst; + + struct sieve_script *script; + struct istream *input; + + struct sieve_error_handler *ehandler; + + /* Currently scanned data */ + const unsigned char *buffer; + size_t buffer_size; + size_t buffer_pos; + + struct sieve_lexer lexer; + + int current_line; +}; + +const struct sieve_lexer * +sieve_lexer_create(struct sieve_script *script, + struct sieve_error_handler *ehandler, + enum sieve_error *error_r) +{ + struct sieve_lexical_scanner *scanner; + struct sieve_instance *svinst = sieve_script_svinst(script); + struct istream *stream; + const struct stat *st; + + /* Open script as stream */ + if (sieve_script_get_stream(script, &stream, error_r) < 0) + return NULL; + + /* Check script size */ + if (i_stream_stat(stream, TRUE, &st) >= 0 && st->st_size > 0 && + svinst->max_script_size > 0 && + (uoff_t)st->st_size > svinst->max_script_size) { + sieve_error(ehandler, sieve_script_name(script), + "sieve script is too large (max %zu bytes)", + svinst->max_script_size); + if (error_r != NULL) + *error_r = SIEVE_ERROR_NOT_POSSIBLE; + return NULL; + } + + scanner = i_new(struct sieve_lexical_scanner, 1); + scanner->lexer.scanner = scanner; + + scanner->ehandler = ehandler; + sieve_error_handler_ref(ehandler); + + scanner->input = stream; + i_stream_ref(scanner->input); + + scanner->script = script; + sieve_script_ref(script); + + scanner->buffer = NULL; + scanner->buffer_size = 0; + scanner->buffer_pos = 0; + + scanner->lexer.token_type = STT_NONE; + scanner->lexer.token_str_value = str_new(default_pool, 256); + scanner->lexer.token_int_value = 0; + scanner->lexer.token_line = 1; + + scanner->current_line = 1; + + return &scanner->lexer; +} + +void sieve_lexer_free(const struct sieve_lexer **_lexer) +{ + const struct sieve_lexer *lexer = *_lexer; + struct sieve_lexical_scanner *scanner = lexer->scanner; + + i_stream_unref(&scanner->input); + sieve_script_unref(&scanner->script); + sieve_error_handler_unref(&scanner->ehandler); + str_free(&scanner->lexer.token_str_value); + + i_free(scanner); + *_lexer = NULL; +} + +/* + * Internal error handling + */ + +inline static void ATTR_FORMAT(4, 5) +sieve_lexer_error(const struct sieve_lexer *lexer, + const char *csrc_filename, unsigned int csrc_linenum, + const char *fmt, ...) +{ + struct sieve_lexical_scanner *scanner = lexer->scanner; + struct sieve_error_params params = { + .log_type = LOG_TYPE_ERROR, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + }; + va_list args; + + va_start(args, fmt); + + T_BEGIN { + params.location = + sieve_error_script_location(scanner->script, + scanner->current_line); + sieve_logv(scanner->ehandler, ¶ms, fmt, args); + } T_END; + + va_end(args); +} +#define sieve_lexer_error(lexer, ...) \ + sieve_lexer_error(lexer, __FILE__, __LINE__, __VA_ARGS__) + +inline static void ATTR_FORMAT(4, 5) +sieve_lexer_warning(const struct sieve_lexer *lexer, + const char *csrc_filename, unsigned int csrc_linenum, + const char *fmt, ...) +{ + struct sieve_lexical_scanner *scanner = lexer->scanner; + struct sieve_error_params params = { + .log_type = LOG_TYPE_WARNING, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + }; + va_list args; + + va_start(args, fmt); + + T_BEGIN { + params.location = + sieve_error_script_location(scanner->script, + scanner->current_line); + sieve_logv(scanner->ehandler, ¶ms, fmt, args); + } T_END; + + va_end(args); +} +#define sieve_lexer_warning(lexer, ...) \ + sieve_lexer_warning(lexer, __FILE__, __LINE__, __VA_ARGS__) + +const char *sieve_lexer_token_description(const struct sieve_lexer *lexer) +{ + switch (lexer->token_type) { + case STT_NONE: + return "no token (bug)"; + case STT_WHITESPACE: + return "whitespace (bug)"; + case STT_EOF: + return "end of file"; + + case STT_NUMBER: + return "number"; + case STT_IDENTIFIER: + return "identifier"; + case STT_TAG: + return "tag"; + case STT_STRING: + return "string"; + + case STT_RBRACKET: + return "')'"; + case STT_LBRACKET: + return "'('"; + case STT_RCURLY: + return "'}'"; + case STT_LCURLY: + return "'{'"; + case STT_RSQUARE: + return "']'"; + case STT_LSQUARE: + return "'['"; + case STT_SEMICOLON: + return "';'"; + case STT_COMMA: + return "','"; + + case STT_SLASH: + return "'/'"; + case STT_COLON: + return "':'"; + + case STT_GARBAGE: + return "unknown characters"; + case STT_ERROR: + return "error token (bug)"; + } + + return "unknown token (bug)"; +} + +/* + * Debug + */ + +void sieve_lexer_token_print(const struct sieve_lexer *lexer) +{ + switch (lexer->token_type) { + case STT_NONE: + printf("??NONE?? "); + break; + case STT_WHITESPACE: + printf("??WHITESPACE?? "); + break; + case STT_EOF: + printf("EOF\n"); + break; + + case STT_NUMBER: + printf("NUMBER "); + break; + case STT_IDENTIFIER: + printf("IDENTIFIER "); + break; + case STT_TAG: + printf("TAG "); + break; + case STT_STRING: + printf("STRING "); + break; + + case STT_RBRACKET: + printf(") "); + break; + case STT_LBRACKET: + printf("( "); + break; + case STT_RCURLY: + printf("}\n"); + break; + case STT_LCURLY: + printf("{\n"); + break; + case STT_RSQUARE: + printf("] "); + break; + case STT_LSQUARE: + printf("[ "); + break; + case STT_SEMICOLON: + printf(";\n"); + break; + case STT_COMMA: + printf(", "); + break; + + case STT_SLASH: + printf("/ "); + break; + case STT_COLON: + printf(": "); + break; + + case STT_GARBAGE: + printf(">>GARBAGE<<"); + break; + case STT_ERROR: + printf(">>ERROR<<"); + break; + default: + printf("UNKNOWN "); + break; + } +} + +/* + * Lexical scanning + */ + +static void sieve_lexer_shift(struct sieve_lexical_scanner *scanner) +{ + if (scanner->buffer_size > 0 && + scanner->buffer[scanner->buffer_pos] == '\n') + scanner->current_line++; + + if (scanner->buffer_size > 0 && + scanner->buffer_pos + 1 < scanner->buffer_size) + scanner->buffer_pos++; + else { + if (scanner->buffer_size > 0) + i_stream_skip(scanner->input, scanner->buffer_size); + + scanner->buffer = i_stream_get_data(scanner->input, + &scanner->buffer_size); + + if (scanner->buffer_size == 0 && + i_stream_read(scanner->input) > 0) { + scanner->buffer = i_stream_get_data( + scanner->input, &scanner->buffer_size); + } + + scanner->buffer_pos = 0; + } +} + +static inline int sieve_lexer_curchar(struct sieve_lexical_scanner *scanner) +{ + if (scanner->buffer_size == 0) + return -1; + + return scanner->buffer[scanner->buffer_pos]; +} + +static inline const char *_char_sanitize(int ch) +{ + if (ch > 31 && ch < 127) + return t_strdup_printf("'%c'", ch); + + return t_strdup_printf("0x%02x", ch); +} + +static bool sieve_lexer_scan_number(struct sieve_lexical_scanner *scanner) +{ + struct sieve_lexer *lexer = &scanner->lexer; + uintmax_t value; + string_t *str; + bool overflow = FALSE; + + str_truncate(lexer->token_str_value,0); + str = lexer->token_str_value; + + while (i_isdigit(sieve_lexer_curchar(scanner))) { + str_append_c(str, sieve_lexer_curchar(scanner)); + sieve_lexer_shift(scanner); + } + + if (str_to_uintmax(str_c(str), &value) < 0 || + value > (sieve_number_t)-1) { + overflow = TRUE; + } else { + switch (sieve_lexer_curchar(scanner)) { + case 'k': + case 'K': /* Kilo */ + if (value > (SIEVE_MAX_NUMBER >> 10)) + overflow = TRUE; + else + value = value << 10; + sieve_lexer_shift(scanner); + break; + case 'm': + case 'M': /* Mega */ + if (value > (SIEVE_MAX_NUMBER >> 20)) + overflow = TRUE; + else + value = value << 20; + sieve_lexer_shift(scanner); + break; + case 'g': + case 'G': /* Giga */ + if (value > (SIEVE_MAX_NUMBER >> 30)) + overflow = TRUE; + else + value = value << 30; + sieve_lexer_shift(scanner); + break; + default: + /* Next token */ + break; + } + } + + /* Check for integer overflow */ + if (overflow) { + sieve_lexer_error(lexer, + "number exceeds integer limits (max %llu)", + (long long) SIEVE_MAX_NUMBER); + lexer->token_type = STT_ERROR; + return FALSE; + } + + lexer->token_type = STT_NUMBER; + lexer->token_int_value = (sieve_number_t)value; + return TRUE; + +} + +static bool +sieve_lexer_scan_hash_comment(struct sieve_lexical_scanner *scanner) +{ + struct sieve_lexer *lexer = &scanner->lexer; + + while (sieve_lexer_curchar(scanner) != '\n') { + switch(sieve_lexer_curchar(scanner)) { + case -1: + if (!scanner->input->eof) { + lexer->token_type = STT_ERROR; + return FALSE; + } + sieve_lexer_warning(lexer, + "no newline (CRLF) at end of hash comment at end of file"); + lexer->token_type = STT_WHITESPACE; + return TRUE; + case '\0': + sieve_lexer_error(lexer, + "encountered NUL character in hash comment"); + lexer->token_type = STT_ERROR; + return FALSE; + default: + break; + } + + /* Stray CR is ignored */ + sieve_lexer_shift(scanner); + } + + sieve_lexer_shift(scanner); + + lexer->token_type = STT_WHITESPACE; + return TRUE; +} + +/* sieve_lexer_scan_raw_token: + * Scans valid tokens and whitespace + */ +static bool +sieve_lexer_scan_raw_token(struct sieve_lexical_scanner *scanner) +{ + struct sieve_lexer *lexer = &scanner->lexer; + string_t *str; + int ret; + + /* Read first character */ + if (lexer->token_type == STT_NONE) { + if ((ret = i_stream_read(scanner->input)) < 0) { + i_assert(ret != -2); + if (!scanner->input->eof) { + lexer->token_type = STT_ERROR; + return FALSE; + } + } + sieve_lexer_shift(scanner); + } + + lexer->token_line = scanner->current_line; + + switch (sieve_lexer_curchar(scanner)) { + + /* whitespace */ + + // hash-comment = ( "#" *CHAR-NOT-CRLF CRLF ) + case '#': + sieve_lexer_shift(scanner); + return sieve_lexer_scan_hash_comment(scanner); + + // bracket-comment = "/*" *(CHAR-NOT-STAR / ("*" CHAR-NOT-SLASH)) "*/" + // ;; No */ allowed inside a comment. + // ;; (No * is allowed unless it is the last character, + // ;; or unless it is followed by a character that isn't a + // ;; slash.) + case '/': + sieve_lexer_shift(scanner); + + if (sieve_lexer_curchar(scanner) == '*') { + sieve_lexer_shift(scanner); + + while (TRUE) { + switch (sieve_lexer_curchar(scanner)) { + case -1: + if (scanner->input->eof) { + sieve_lexer_error(lexer, + "end of file before end of bracket comment " + "('/* ... */') " + "started at line %d", + lexer->token_line); + } + lexer->token_type = STT_ERROR; + return FALSE; + case '*': + sieve_lexer_shift(scanner); + + if (sieve_lexer_curchar(scanner) == '/') { + sieve_lexer_shift(scanner); + + lexer->token_type = STT_WHITESPACE; + return TRUE; + + } else if (sieve_lexer_curchar(scanner) == -1) { + sieve_lexer_error(lexer, + "end of file before end of bracket comment " + "('/* ... */') " + "started at line %d", + lexer->token_line); + lexer->token_type = STT_ERROR; + return FALSE; + } + break; + case '\0': + sieve_lexer_error(lexer, + "encountered NUL character in bracket comment"); + lexer->token_type = STT_ERROR; + return FALSE; + default: + sieve_lexer_shift(scanner); + } + } + + i_unreached(); + return FALSE; + } + + lexer->token_type = STT_SLASH; + return TRUE; + + // comment = bracket-comment / hash-comment + // white-space = 1*(SP / CRLF / HTAB) / comment + case '\t': + case '\r': + case '\n': + case ' ': + sieve_lexer_shift(scanner); + + while (sieve_lexer_curchar(scanner) == '\t' || + sieve_lexer_curchar(scanner) == '\r' || + sieve_lexer_curchar(scanner) == '\n' || + sieve_lexer_curchar(scanner) == ' ') { + + sieve_lexer_shift(scanner); + } + + lexer->token_type = STT_WHITESPACE; + return TRUE; + + /* quoted-string */ + case '"': + sieve_lexer_shift(scanner); + + str_truncate(lexer->token_str_value, 0); + str = lexer->token_str_value; + + while (sieve_lexer_curchar(scanner) != '"') { + if (sieve_lexer_curchar(scanner) == '\\') + sieve_lexer_shift(scanner); + + switch (sieve_lexer_curchar(scanner)) { + + /* End of file */ + case -1: + if (scanner->input->eof) { + sieve_lexer_error(lexer, + "end of file before end of quoted string " + "started at line %d", lexer->token_line); + } + lexer->token_type = STT_ERROR; + return FALSE; + + /* NUL character */ + case '\0': + sieve_lexer_error(lexer, + "encountered NUL character in quoted string " + "started at line %d", lexer->token_line); + lexer->token_type = STT_ERROR; + return FALSE; + + /* CR .. check for LF */ + case '\r': + sieve_lexer_shift(scanner); + + if (sieve_lexer_curchar(scanner) != '\n') { + sieve_lexer_error(lexer, + "found stray carriage-return (CR) character " + "in quoted string started at line %d", + lexer->token_line); + lexer->token_type = STT_ERROR; + return FALSE; + } + + if (str_len(str) <= SIEVE_MAX_STRING_LEN) + str_append(str, "\r\n"); + break; + + /* Loose LF is allowed (non-standard) and converted to CRLF */ + case '\n': + if (str_len(str) <= SIEVE_MAX_STRING_LEN) + str_append(str, "\r\n"); + break; + + /* Other characters */ + default: + if (str_len(str) <= SIEVE_MAX_STRING_LEN) + str_append_c(str, sieve_lexer_curchar(scanner)); + } + + sieve_lexer_shift(scanner); + } + + sieve_lexer_shift(scanner); + + if (str_len(str) > SIEVE_MAX_STRING_LEN) { + sieve_lexer_error(lexer, + "quoted string started at line %d is too long " + "(longer than %llu bytes)", lexer->token_line, + (long long) SIEVE_MAX_STRING_LEN); + lexer->token_type = STT_ERROR; + return FALSE; + } + + lexer->token_type = STT_STRING; + return TRUE; + + /* single character tokens */ + case ']': + sieve_lexer_shift(scanner); + lexer->token_type = STT_RSQUARE; + return TRUE; + case '[': + sieve_lexer_shift(scanner); + lexer->token_type = STT_LSQUARE; + return TRUE; + case '}': + sieve_lexer_shift(scanner); + lexer->token_type = STT_RCURLY; + return TRUE; + case '{': + sieve_lexer_shift(scanner); + lexer->token_type = STT_LCURLY; + return TRUE; + case ')': + sieve_lexer_shift(scanner); + lexer->token_type = STT_RBRACKET; + return TRUE; + case '(': + sieve_lexer_shift(scanner); + lexer->token_type = STT_LBRACKET; + return TRUE; + case ';': + sieve_lexer_shift(scanner); + lexer->token_type = STT_SEMICOLON; + return TRUE; + case ',': + sieve_lexer_shift(scanner); + lexer->token_type = STT_COMMA; + return TRUE; + + /* EOF */ + case -1: + if (!scanner->input->eof) { + lexer->token_type = STT_ERROR; + return FALSE; + } + lexer->token_type = STT_EOF; + return TRUE; + + default: + /* number */ + if (i_isdigit(sieve_lexer_curchar(scanner))) { + return sieve_lexer_scan_number(scanner); + + /* identifier / tag */ + } else if (i_isalpha(sieve_lexer_curchar(scanner)) || + sieve_lexer_curchar(scanner) == '_' || + sieve_lexer_curchar(scanner) == ':') { + + enum sieve_token_type type = STT_IDENTIFIER; + str_truncate(lexer->token_str_value,0); + str = lexer->token_str_value; + + /* If it starts with a ':' it is a tag and not an + identifier */ + if (sieve_lexer_curchar(scanner) == ':') { + sieve_lexer_shift(scanner); // discard colon + type = STT_TAG; + + /* First character still can't be a DIGIT */ + if (i_isalpha(sieve_lexer_curchar(scanner)) || + sieve_lexer_curchar(scanner) == '_') { + str_append_c(str, sieve_lexer_curchar(scanner)); + sieve_lexer_shift(scanner); + } else { + /* Hmm, otherwise it is just a spurious + colon */ + lexer->token_type = STT_COLON; + return TRUE; + } + } else { + str_append_c(str, sieve_lexer_curchar(scanner)); + sieve_lexer_shift(scanner); + } + + /* Scan the rest of the identifier */ + while (i_isalnum(sieve_lexer_curchar(scanner)) || + sieve_lexer_curchar(scanner) == '_') { + + if (str_len(str) <= SIEVE_MAX_IDENTIFIER_LEN) { + str_append_c(str, sieve_lexer_curchar(scanner)); + } + sieve_lexer_shift(scanner); + } + + /* Is this in fact a multiline text string ? */ + if (sieve_lexer_curchar(scanner) == ':' && + type == STT_IDENTIFIER && str_len(str) == 4 && + strncasecmp(str_c(str), "text", 4) == 0) { + sieve_lexer_shift(scanner); // discard colon + + /* Discard SP and HTAB whitespace */ + while (sieve_lexer_curchar(scanner) == ' ' || + sieve_lexer_curchar(scanner) == '\t') + sieve_lexer_shift(scanner); + + /* Discard hash comment or handle single CRLF */ + if (sieve_lexer_curchar(scanner) == '\r') + sieve_lexer_shift(scanner); + switch (sieve_lexer_curchar(scanner)) { + case '#': + if (!sieve_lexer_scan_hash_comment(scanner)) + return FALSE; + if (scanner->input->eof) { + sieve_lexer_error(lexer, + "end of file before end of multi-line string"); + lexer->token_type = STT_ERROR; + return FALSE; + } else if (scanner->input->stream_errno != 0) { + lexer->token_type = STT_ERROR; + return FALSE; + } + break; + case '\n': + sieve_lexer_shift(scanner); + break; + case -1: + if (scanner->input->eof) { + sieve_lexer_error(lexer, + "end of file before end of multi-line string"); + } + lexer->token_type = STT_ERROR; + return FALSE; + default: + sieve_lexer_error(lexer, + "invalid character %s after 'text:' in multiline string", + _char_sanitize(sieve_lexer_curchar(scanner))); + lexer->token_type = STT_ERROR; + return FALSE; + } + + /* Start over */ + str_truncate(str, 0); + + /* Parse literal lines */ + while (TRUE) { + bool cr_shifted = FALSE; + + /* Remove dot-stuffing or detect end of text */ + if (sieve_lexer_curchar(scanner) == '.') { + sieve_lexer_shift(scanner); + + /* Check for CR.. */ + if (sieve_lexer_curchar(scanner) == '\r') { + sieve_lexer_shift(scanner); + cr_shifted = TRUE; + } + + /* ..LF */ + if (sieve_lexer_curchar(scanner) == '\n') { + sieve_lexer_shift(scanner); + + /* End of multi-line string */ + + /* Check whether length limit was violated */ + if (str_len(str) > SIEVE_MAX_STRING_LEN) { + sieve_lexer_error(lexer, + "multi-line string started at line %d is too long " + "(longer than %llu bytes)", lexer->token_line, + (long long) SIEVE_MAX_STRING_LEN); + lexer->token_type = STT_ERROR; + return FALSE; + } + + lexer->token_type = STT_STRING; + return TRUE; + } else if (cr_shifted) { + /* Seen CR, but no LF */ + if (sieve_lexer_curchar(scanner) != -1 || + !scanner->input->eof) { + sieve_lexer_error(lexer, + "found stray carriage-return (CR) character " + "in multi-line string started at line %d", + lexer->token_line); + } + lexer->token_type = STT_ERROR; + return FALSE; + } + + /* Handle dot-stuffing */ + if (str_len(str) <= SIEVE_MAX_STRING_LEN) + str_append_c(str, '.'); + if (sieve_lexer_curchar(scanner) == '.') + sieve_lexer_shift(scanner); + } + + /* Scan the rest of the line */ + while (sieve_lexer_curchar(scanner) != '\n' && + sieve_lexer_curchar(scanner) != '\r') { + + switch (sieve_lexer_curchar(scanner)) { + case -1: + if (scanner->input->eof) { + sieve_lexer_error(lexer, + "end of file before end of multi-line string"); + } + lexer->token_type = STT_ERROR; + return FALSE; + case '\0': + sieve_lexer_error(lexer, + "encountered NUL character in quoted string " + "started at line %d", lexer->token_line); + lexer->token_type = STT_ERROR; + return FALSE; + default: + if (str_len(str) <= SIEVE_MAX_STRING_LEN) + str_append_c(str, sieve_lexer_curchar(scanner)); + } + + sieve_lexer_shift(scanner); + } + + /* If exited loop due to CR, skip it */ + if (sieve_lexer_curchar(scanner) == '\r') + sieve_lexer_shift(scanner); + + /* Now we must see an LF */ + if (sieve_lexer_curchar(scanner) != '\n') { + if (sieve_lexer_curchar(scanner) != -1 || + !scanner->input->eof) { + sieve_lexer_error(lexer, + "found stray carriage-return (CR) character " + "in multi-line string started at line %d", + lexer->token_line); + } + lexer->token_type = STT_ERROR; + return FALSE; + } + + if (str_len(str) <= SIEVE_MAX_STRING_LEN) + str_append(str, "\r\n"); + + sieve_lexer_shift(scanner); + } + + i_unreached(); + lexer->token_type = STT_ERROR; + return FALSE; + } + + if (str_len(str) > SIEVE_MAX_IDENTIFIER_LEN) { + sieve_lexer_error(lexer, + "encountered impossibly long %s%s'", + (type == STT_TAG ? "tag identifier ':" : + "identifier '"), + str_sanitize(str_c(str), + SIEVE_MAX_IDENTIFIER_LEN)); + lexer->token_type = STT_ERROR; + return FALSE; + } + + lexer->token_type = type; + return TRUE; + } + + /* Error (unknown character and EOF handled already) */ + if (lexer->token_type != STT_GARBAGE) { + sieve_lexer_error(lexer, + "unexpected character(s) starting with %s", + _char_sanitize(sieve_lexer_curchar(scanner))); + } + sieve_lexer_shift(scanner); + lexer->token_type = STT_GARBAGE; + return FALSE; + } +} + +void sieve_lexer_skip_token(const struct sieve_lexer *lexer) +{ + /* Scan token while skipping whitespace */ + do { + struct sieve_lexical_scanner *scanner = lexer->scanner; + + if (!sieve_lexer_scan_raw_token(scanner)) { + if (!scanner->input->eof && + scanner->input->stream_errno != 0) { + sieve_critical(scanner->svinst, scanner->ehandler, + sieve_error_script_location(scanner->script, + scanner->current_line), + "error reading script", + "error reading script during lexical analysis: %s", + i_stream_get_error(scanner->input)); + } + return; + } + } while (lexer->token_type == STT_WHITESPACE); +} + diff --git a/pigeonhole/src/lib-sieve/sieve-lexer.h b/pigeonhole/src/lib-sieve/sieve-lexer.h new file mode 100644 index 0000000..95451cc --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-lexer.h @@ -0,0 +1,119 @@ +#ifndef SIEVE_LEXER_H +#define SIEVE_LEXER_H + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" + +enum sieve_token_type { + STT_NONE, + STT_WHITESPACE, + STT_EOF, + + STT_NUMBER, + STT_IDENTIFIER, + STT_TAG, + STT_STRING, + + STT_RBRACKET, + STT_LBRACKET, + STT_RCURLY, + STT_LCURLY, + STT_RSQUARE, + STT_LSQUARE, + STT_SEMICOLON, + STT_COMMA, + + /* These are currently not used in the lexical specification, but a + token is assigned to these to generate proper error messages (these + are technically not garbage and possibly part of mistyped but + otherwise valid tokens). + */ + STT_SLASH, + STT_COLON, + + /* Error tokens */ + STT_GARBAGE, /* Error reporting deferred to parser */ + STT_ERROR /* Lexer is responsible for error, parser won't report + additional errors */ +}; + +/* + * Lexer object + */ + +struct sieve_lexical_scanner; + +struct sieve_lexer { + struct sieve_lexical_scanner *scanner; + + enum sieve_token_type token_type; + string_t *token_str_value; + sieve_number_t token_int_value; + + int token_line; +}; + +const struct sieve_lexer * +sieve_lexer_create(struct sieve_script *script, + struct sieve_error_handler *ehandler, + enum sieve_error *error_r); +void sieve_lexer_free(const struct sieve_lexer **lexer); + +/* + * Scanning + */ + +void sieve_lexer_skip_token(const struct sieve_lexer *lexer); + +/* + * Token access + */ + +static inline enum sieve_token_type +sieve_lexer_token_type(const struct sieve_lexer *lexer) +{ + return lexer->token_type; +} + +static inline const string_t * +sieve_lexer_token_str(const struct sieve_lexer *lexer) +{ + i_assert(lexer->token_type == STT_STRING); + + return lexer->token_str_value; +} + +static inline const char * +sieve_lexer_token_ident(const struct sieve_lexer *lexer) +{ + i_assert(lexer->token_type == STT_TAG || + lexer->token_type == STT_IDENTIFIER); + + return str_c(lexer->token_str_value); +} + +static inline sieve_number_t +sieve_lexer_token_int(const struct sieve_lexer *lexer) +{ + i_assert(lexer->token_type == STT_NUMBER); + + return lexer->token_int_value; +} + +static inline bool sieve_lexer_eof(const struct sieve_lexer *lexer) +{ + return lexer->token_type == STT_EOF; +} + +static inline int sieve_lexer_token_line(const struct sieve_lexer *lexer) +{ + return lexer->token_line; +} + +const char *sieve_lexer_token_description(const struct sieve_lexer *lexer); + +void sieve_lexer_token_print(const struct sieve_lexer *lexer); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-limits.h b/pigeonhole/src/lib-sieve/sieve-limits.h new file mode 100644 index 0000000..1adbaa6 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-limits.h @@ -0,0 +1,45 @@ +#ifndef SIEVE_LIMITS_H +#define SIEVE_LIMITS_H + +/* + * Scripts + */ + +#define SIEVE_MAX_SCRIPT_NAME_LEN 256 + +#define SIEVE_DEFAULT_MAX_SCRIPT_SIZE (1 << 20) + +#define SIEVE_MAX_LOOP_DEPTH 4 + +/* + * Lexer + */ + +#define SIEVE_MAX_STRING_LEN (1 << 20) +#define SIEVE_MAX_IDENTIFIER_LEN 32 + +/* + * AST + */ + +#define SIEVE_MAX_COMMAND_ARGUMENTS 32 +#define SIEVE_MAX_BLOCK_NESTING 32 +#define SIEVE_MAX_TEST_NESTING 32 + +/* + * Runtime + */ + +#define SIEVE_MAX_MATCH_VALUES 32 +#define SIEVE_HIGH_CPU_TIME_MSECS 1500 +#define SIEVE_DEFAULT_MAX_CPU_TIME_SECS 30 +#define SIEVE_DEFAULT_RESOURCE_USAGE_TIMEOUT_SECS (60 * 60) + +/* + * Actions + */ + +#define SIEVE_DEFAULT_MAX_ACTIONS 32 +#define SIEVE_DEFAULT_MAX_REDIRECTS 4 + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-match-types.c b/pigeonhole/src/lib-sieve/sieve-match-types.c new file mode 100644 index 0000000..a61737e --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-match-types.c @@ -0,0 +1,569 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "compat.h" +#include "mempool.h" +#include "hash.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-limits.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-comparators.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "sieve-match-types.h" + +#include <string.h> + +/* + * Types + */ + +struct sieve_match_values { + pool_t pool; + ARRAY(string_t *) values; + unsigned count; +}; + +/* + * Default match types + */ + +const struct sieve_match_type_def *sieve_core_match_types[] = { + &is_match_type, &contains_match_type, &matches_match_type +}; + +const unsigned int sieve_core_match_types_count = + N_ELEMENTS(sieve_core_match_types); + +/* + * Match-type 'extension' + */ + +static bool mtch_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def match_type_extension = { + .name = "@match-types", + .validator_load = mtch_validator_load +}; + +/* + * Validator context: + * name-based match-type registry. + */ + +static struct sieve_validator_object_registry *_get_object_registry +(struct sieve_validator *valdtr) +{ + struct sieve_instance *svinst; + const struct sieve_extension *mcht_ext; + + svinst = sieve_validator_svinst(valdtr); + mcht_ext = sieve_get_match_type_extension(svinst); + return sieve_validator_object_registry_get(valdtr, mcht_ext); +} + +void sieve_match_type_register +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + const struct sieve_match_type_def *mcht_def) +{ + struct sieve_validator_object_registry *regs = _get_object_registry(valdtr); + + sieve_validator_object_registry_add(regs, ext, &mcht_def->obj_def); +} + +static bool sieve_match_type_exists +(struct sieve_validator *valdtr, const char *identifier) +{ + struct sieve_validator_object_registry *regs = _get_object_registry(valdtr); + + return sieve_validator_object_registry_find(regs, identifier, NULL); +} + +static const struct sieve_match_type *sieve_match_type_create_instance +(struct sieve_validator *valdtr, struct sieve_command *cmd, + const char *identifier) +{ + struct sieve_validator_object_registry *regs = _get_object_registry(valdtr); + struct sieve_object object; + struct sieve_match_type *mcht; + + if ( !sieve_validator_object_registry_find(regs, identifier, &object) ) + return NULL; + + mcht = p_new(sieve_command_pool(cmd), struct sieve_match_type, 1); + mcht->object = object; + mcht->def = (const struct sieve_match_type_def *) object.def; + + return mcht; +} + +bool mtch_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + struct sieve_validator_object_registry *regs = + sieve_validator_object_registry_init(valdtr, ext); + unsigned int i; + + /* Register core match-types */ + for ( i = 0; i < sieve_core_match_types_count; i++ ) { + sieve_validator_object_registry_add + (regs, NULL, &(sieve_core_match_types[i]->obj_def)); + } + + return TRUE; +} + +/* + * Interpreter context + */ + +struct mtch_interpreter_context { + struct sieve_match_values *match_values; + bool match_values_enabled; +}; + +static void mtch_interpreter_free +(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_interpreter *interp ATTR_UNUSED, void *context) +{ + struct mtch_interpreter_context *mctx = + (struct mtch_interpreter_context *) context; + + if ( mctx->match_values != NULL ) { + pool_unref(&mctx->match_values->pool); + } +} + +struct sieve_interpreter_extension +mtch_interpreter_extension = { + .ext_def = &match_type_extension, + .free = mtch_interpreter_free +}; + +static inline struct mtch_interpreter_context *get_interpreter_context +(struct sieve_interpreter *interp, bool create) +{ + struct sieve_instance *svinst; + const struct sieve_extension *mcht_ext; + struct mtch_interpreter_context *ctx; + + svinst = sieve_interpreter_svinst(interp); + mcht_ext = sieve_get_match_type_extension(svinst); + + ctx = (struct mtch_interpreter_context *) + sieve_interpreter_extension_get_context(interp, mcht_ext); + + if ( ctx == NULL && create ) { + pool_t pool = sieve_interpreter_pool(interp); + ctx = p_new(pool, struct mtch_interpreter_context, 1); + + sieve_interpreter_extension_register + (interp, mcht_ext, &mtch_interpreter_extension, (void *) ctx); + } + + return ctx; +} + +/* + * Match values + */ + +bool sieve_match_values_set_enabled +(const struct sieve_runtime_env *renv, bool enable) +{ + struct mtch_interpreter_context *ctx = + get_interpreter_context(renv->interp, enable); + + if ( ctx != NULL ) { + bool previous = ctx->match_values_enabled; + + ctx->match_values_enabled = enable; + return previous; + } + + return FALSE; +} + +bool sieve_match_values_are_enabled +(const struct sieve_runtime_env *renv) +{ + struct mtch_interpreter_context *ctx = + get_interpreter_context(renv->interp, FALSE); + + return ( ctx == NULL ? FALSE : ctx->match_values_enabled ); +} + +struct sieve_match_values *sieve_match_values_start +(const struct sieve_runtime_env *renv) +{ + struct mtch_interpreter_context *ctx = + get_interpreter_context(renv->interp, FALSE); + struct sieve_match_values *match_values; + + if ( ctx == NULL || !ctx->match_values_enabled ) + return NULL; + + pool_t pool = pool_alloconly_create("sieve_match_values", 1024); + + match_values = p_new(pool, struct sieve_match_values, 1); + match_values->pool = pool; + match_values->count = 0; + + p_array_init(&match_values->values, pool, 4); + + return match_values; +} + +static string_t *sieve_match_values_add_entry +(struct sieve_match_values *mvalues) +{ + string_t *entry; + + if ( mvalues == NULL ) return NULL; + + if ( mvalues->count >= SIEVE_MAX_MATCH_VALUES ) return NULL; + + if ( mvalues->count >= array_count(&mvalues->values) ) { + entry = str_new(mvalues->pool, 64); + array_append(&mvalues->values, &entry, 1); } else { + string_t * const *ep = array_idx(&mvalues->values, mvalues->count); + entry = *ep; + str_truncate(entry, 0); + } + + mvalues->count++; + + return entry; +} + +void sieve_match_values_set +(struct sieve_match_values *mvalues, unsigned int index, string_t *value) +{ + if ( mvalues != NULL && index < array_count(&mvalues->values) ) { + string_t * const *ep = array_idx(&mvalues->values, index); + string_t *entry = *ep; + + if ( entry != NULL && value != NULL ) { + str_truncate(entry, 0); + str_append_str(entry, value); + } + } +} + +void sieve_match_values_add +(struct sieve_match_values *mvalues, string_t *value) +{ + string_t *entry = sieve_match_values_add_entry(mvalues); + + if ( entry != NULL && value != NULL ) + str_append_str(entry, value); +} + +void sieve_match_values_add_char +(struct sieve_match_values *mvalues, char c) +{ + string_t *entry = sieve_match_values_add_entry(mvalues); + + if ( entry != NULL ) + str_append_c(entry, c); +} + +void sieve_match_values_skip +(struct sieve_match_values *mvalues, int num) +{ + int i; + + for ( i = 0; i < num; i++ ) + (void) sieve_match_values_add_entry(mvalues); +} + +void sieve_match_values_commit +(const struct sieve_runtime_env *renv, struct sieve_match_values **mvalues) +{ + struct mtch_interpreter_context *ctx; + + if ( (*mvalues) == NULL ) return; + + ctx = get_interpreter_context(renv->interp, FALSE); + if ( ctx == NULL || !ctx->match_values_enabled ) + return; + + if ( ctx->match_values != NULL ) { + pool_unref(&ctx->match_values->pool); + ctx->match_values = NULL; + } + + ctx->match_values = *mvalues; + *mvalues = NULL; +} + +void sieve_match_values_abort +(struct sieve_match_values **mvalues) +{ + if ( (*mvalues) == NULL ) return; + + pool_unref(&(*mvalues)->pool); + *mvalues = NULL; +} + +void sieve_match_values_get +(const struct sieve_runtime_env *renv, unsigned int index, string_t **value_r) +{ + struct mtch_interpreter_context *ctx = + get_interpreter_context(renv->interp, FALSE); + struct sieve_match_values *mvalues; + + if ( ctx == NULL || ctx->match_values == NULL ) { + *value_r = NULL; + return; + } + + mvalues = ctx->match_values; + if ( index < array_count(&mvalues->values) && index < mvalues->count ) { + string_t * const *entry = array_idx(&mvalues->values, index); + + *value_r = *entry; + return; + } + + *value_r = NULL; +} + +/* + * Match-type tagged argument + */ + +/* Forward declarations */ + +static bool tag_match_type_is_instance_of + (struct sieve_validator *valdtr, struct sieve_command *cmd, + const struct sieve_extension *ext, const char *identifier, void **data); +static bool tag_match_type_validate + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool tag_match_type_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd); + +/* Argument object */ + +const struct sieve_argument_def match_type_tag = { + .identifier = "MATCH-TYPE", + .is_instance_of = tag_match_type_is_instance_of, + .validate = tag_match_type_validate, + .generate = tag_match_type_generate +}; + +/* Argument implementation */ + +static bool tag_match_type_is_instance_of +(struct sieve_validator *valdtr, struct sieve_command *cmd, + const struct sieve_extension *ext ATTR_UNUSED, const char *identifier, + void **data) +{ + const struct sieve_match_type *mcht; + + if ( data == NULL ) + return sieve_match_type_exists(valdtr, identifier); + + if ( (mcht=sieve_match_type_create_instance + (valdtr, cmd, identifier)) == NULL ) + return FALSE; + + *data = (void *) mcht; + return TRUE; +} + +static bool tag_match_type_validate +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + const struct sieve_match_type *mcht = + (const struct sieve_match_type *) (*arg)->argument->data; + struct sieve_match_type_context *mtctx; + + mtctx = p_new(sieve_command_pool(cmd), struct sieve_match_type_context, 1); + mtctx->match_type = mcht; + mtctx->argument = *arg; + mtctx->comparator = NULL; /* Can be filled in later */ + + (*arg)->argument->data = mtctx; + + /* Syntax: + * ":is" / ":contains" / ":matches" (subject to extension) + */ + + /* Skip tag */ + *arg = sieve_ast_argument_next(*arg); + + /* Check whether this match type requires additional validation. + * Additional validation can override the match type recorded in the context + * for later code generation. + */ + if ( mcht->def != NULL && mcht->def->validate != NULL ) { + return mcht->def->validate(valdtr, arg, mtctx); + } + + return TRUE; +} + +static bool tag_match_type_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + struct sieve_match_type_context *mtctx = + (struct sieve_match_type_context *) arg->argument->data; + + (void) sieve_opr_match_type_emit(cgenv->sblock, mtctx->match_type); + + return TRUE; +} + +void sieve_match_types_link_tags +(struct sieve_validator *valdtr, + struct sieve_command_registration *cmd_reg, int id_code) +{ + struct sieve_instance *svinst; + const struct sieve_extension *mcht_ext; + + svinst = sieve_validator_svinst(valdtr); + mcht_ext = sieve_get_comparator_extension(svinst); + + sieve_validator_register_tag + (valdtr, cmd_reg, mcht_ext, &match_type_tag, id_code); +} + +/* + * Validation + */ + +bool sieve_match_type_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd, + struct sieve_ast_argument *key_arg, + const struct sieve_match_type *mcht_default, + const struct sieve_comparator *cmp_default) +{ + struct sieve_ast_argument *arg = sieve_command_first_argument(cmd); + struct sieve_ast_argument *mt_arg = NULL; + struct sieve_match_type_context *mtctx; + const struct sieve_match_type *mcht = NULL; + const struct sieve_comparator *cmp = NULL; + + /* Find match type and comparator among the arguments */ + while ( arg != NULL && arg != cmd->first_positional ) { + if ( sieve_argument_is_comparator(arg) ) { + cmp = sieve_comparator_tag_get(arg); + if ( mt_arg != NULL ) break; + } + + if ( sieve_argument_is_match_type(arg) ) { + mt_arg = arg; + if ( cmp != NULL ) break; + } + arg = sieve_ast_argument_next(arg); + } + + /* Verify using the default comparator if none is specified explicitly */ + if ( cmp == NULL ) { + cmp = sieve_comparator_copy(sieve_command_pool(cmd), cmp_default); + } + + /* Verify the default match type if none is specified explicitly */ + if ( mt_arg == NULL || mt_arg->argument == NULL || + mt_arg->argument->data == NULL ) { + mcht = sieve_match_type_copy(sieve_command_pool(cmd), mcht_default); + mtctx = t_new(struct sieve_match_type_context, 1); + mtctx->command = cmd; + mtctx->match_type = mcht; + } else { + mtctx = (struct sieve_match_type_context *) mt_arg->argument->data; + mcht = mtctx->match_type; + } + mtctx->comparator = cmp; + + /* Check whether this match type requires additional validation. + * Additional validation can override the match type recorded in the context + * for later code generation. + */ + if ( mcht != NULL && mcht->def != NULL && + mcht->def->validate_context != NULL ) { + return mcht->def->validate_context(valdtr, mt_arg, mtctx, key_arg); + } + + return TRUE; +} + +void sieve_match_type_arguments_remove +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = sieve_command_first_argument(cmd); + + /* Remove any comparator and match type arguments */ + while ( arg != NULL && arg != cmd->first_positional ) { + if ( sieve_argument_is_comparator(arg) ) { + arg = sieve_ast_arguments_detach(arg, 1); + continue; + } + + if ( sieve_argument_is_match_type(arg) ) { + arg = sieve_ast_arguments_detach(arg, 1); + continue; + } + + arg = sieve_ast_argument_next(arg); + } +} + + +/* + * Match-type operand + */ + +const struct sieve_operand_class sieve_match_type_operand_class = + { "match type" }; + +static const struct sieve_extension_objects core_match_types = + SIEVE_EXT_DEFINE_MATCH_TYPES(sieve_core_match_types); + +const struct sieve_operand_def match_type_operand = { + .name = "match-type", + .code = SIEVE_OPERAND_MATCH_TYPE, + .class = &sieve_match_type_operand_class, + .interface = &core_match_types +}; + +/* + * Common validation implementation + */ + +bool sieve_match_substring_validate_context +(struct sieve_validator *valdtr, struct sieve_ast_argument *arg, + struct sieve_match_type_context *ctx, + struct sieve_ast_argument *key_arg ATTR_UNUSED) +{ + const struct sieve_comparator *cmp = ctx->comparator; + + if ( cmp == NULL || cmp->def == NULL ) + return TRUE; + + if ( (cmp->def->flags & SIEVE_COMPARATOR_FLAG_SUBSTRING_MATCH) == 0 ) { + sieve_argument_validate_error(valdtr, arg, + "the specified %s comparator does not support " + "sub-string matching as required by the :%s match type", + cmp->object.def->identifier, ctx->match_type->object.def->identifier ); + + return FALSE; + } + + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/sieve-match-types.h b/pigeonhole/src/lib-sieve/sieve-match-types.h new file mode 100644 index 0000000..0417e2c --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-match-types.h @@ -0,0 +1,233 @@ +#ifndef SIEVE_MATCH_TYPES_H +#define SIEVE_MATCH_TYPES_H + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-objects.h" + +/* + * Types + */ + +struct sieve_match_type_context; + +/* + * Core match types + */ + +enum sieve_match_type_code { + SIEVE_MATCH_TYPE_IS, + SIEVE_MATCH_TYPE_CONTAINS, + SIEVE_MATCH_TYPE_MATCHES, + SIEVE_MATCH_TYPE_CUSTOM +}; + +extern const struct sieve_match_type_def is_match_type; +extern const struct sieve_match_type_def contains_match_type; +extern const struct sieve_match_type_def matches_match_type; + +/* + * Match type definition + */ + +struct sieve_match_type_def { + struct sieve_object_def obj_def; + + bool (*validate) + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_match_type_context *ctx); + bool (*validate_context) + (struct sieve_validator *valdtr, struct sieve_ast_argument *arg, + struct sieve_match_type_context *ctx, struct sieve_ast_argument *key_arg); + + /* + * Matching + */ + + /* Custom implementation */ + + int (*match) + (struct sieve_match_context *mctx, struct sieve_stringlist *value_list, + struct sieve_stringlist *key_list); + + /* Default match loop */ + + void (*match_init)(struct sieve_match_context *mctx); + + int (*match_keys) + (struct sieve_match_context *mctx, const char *val, size_t val_size, + struct sieve_stringlist *key_list); + int (*match_key) + (struct sieve_match_context *mctx, const char *val, size_t val_size, + const char *key, size_t key_size); + + void (*match_deinit)(struct sieve_match_context *mctx); +}; + +/* + * Match type instance + */ + +struct sieve_match_type { + struct sieve_object object; + + const struct sieve_match_type_def *def; +}; + +#define SIEVE_MATCH_TYPE_DEFAULT(definition) \ + { SIEVE_OBJECT_DEFAULT(definition), &(definition) } + +#define sieve_match_type_name(mcht) \ + ( (mcht)->object.def->identifier ) +#define sieve_match_type_is(mcht, definition) \ + ( (mcht)->def == &(definition) ) + +static inline const struct sieve_match_type *sieve_match_type_copy +(pool_t pool, const struct sieve_match_type *cmp_orig) +{ + struct sieve_match_type *cmp = p_new(pool, struct sieve_match_type, 1); + + *cmp = *cmp_orig; + + return cmp; +} + +/* + * Match type context + */ + +struct sieve_match_type_context { + struct sieve_command *command; + struct sieve_ast_argument *argument; + + const struct sieve_match_type *match_type; + + /* Only filled in when match_type->validate_context() is called */ + const struct sieve_comparator *comparator; + + /* Context data could be used in the future to pass data between validator and + * generator in match types that use extra parameters. Currently not + * necessary, not even for the relational extension. + */ + void *ctx_data; +}; + +/* + * Match type registration + */ + +void sieve_match_type_register + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + const struct sieve_match_type_def *mcht); + +/* + * Match values + */ + +struct sieve_match_values; + +bool sieve_match_values_set_enabled + (const struct sieve_runtime_env *renv, bool enable); +bool sieve_match_values_are_enabled + (const struct sieve_runtime_env *renv); + +struct sieve_match_values *sieve_match_values_start + (const struct sieve_runtime_env *renv); +void sieve_match_values_set + (struct sieve_match_values *mvalues, unsigned int index, string_t *value); +void sieve_match_values_add + (struct sieve_match_values *mvalues, string_t *value); +void sieve_match_values_add_char + (struct sieve_match_values *mvalues, char c); +void sieve_match_values_skip + (struct sieve_match_values *mvalues, int num); + +void sieve_match_values_commit + (const struct sieve_runtime_env *renv, struct sieve_match_values **mvalues); +void sieve_match_values_abort + (struct sieve_match_values **mvalues); + +void sieve_match_values_get + (const struct sieve_runtime_env *renv, unsigned int index, string_t **value_r); + +/* + * Match type tagged argument + */ + +extern const struct sieve_argument_def match_type_tag; + +static inline bool sieve_argument_is_match_type + (struct sieve_ast_argument *arg) +{ + return ( arg->argument->def == &match_type_tag ); +} + +void sieve_match_types_link_tags + (struct sieve_validator *valdtr, + struct sieve_command_registration *cmd_reg, int id_code); + +/* + * Validation + */ + +bool sieve_match_type_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd, + struct sieve_ast_argument *key_arg, + const struct sieve_match_type *mcht_default, + const struct sieve_comparator *cmp_default); + +void sieve_match_type_arguments_remove + (struct sieve_validator *valdtr, struct sieve_command *cmd); + +/* + * Match type operand + */ + +extern const struct sieve_operand_def match_type_operand; +extern const struct sieve_operand_class sieve_match_type_operand_class; + +#define SIEVE_EXT_DEFINE_MATCH_TYPE(OP) SIEVE_EXT_DEFINE_OBJECT(OP) +#define SIEVE_EXT_DEFINE_MATCH_TYPES(OPS) SIEVE_EXT_DEFINE_OBJECTS(OPS) + +static inline bool sieve_operand_is_match_type +(const struct sieve_operand *operand) +{ + return ( operand != NULL && operand->def != NULL && + operand->def->class == &sieve_match_type_operand_class ); +} + +static inline void sieve_opr_match_type_emit +(struct sieve_binary_block *sblock, const struct sieve_match_type *mcht) +{ + sieve_opr_object_emit(sblock, mcht->object.ext, mcht->object.def); +} + +static inline bool sieve_opr_match_type_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + return sieve_opr_object_dump + (denv, &sieve_match_type_operand_class, address, NULL); +} + +static inline int sieve_opr_match_type_read +(const struct sieve_runtime_env *renv, sieve_size_t *address, + struct sieve_match_type *mcht) +{ + if ( !sieve_opr_object_read + (renv, &sieve_match_type_operand_class, address, &mcht->object) ) + return SIEVE_EXEC_BIN_CORRUPT; + + mcht->def = (const struct sieve_match_type_def *) mcht->object.def; + return SIEVE_EXEC_OK; +} + +/* Common validation implementation */ + +bool sieve_match_substring_validate_context + (struct sieve_validator *valdtr, struct sieve_ast_argument *arg, + struct sieve_match_type_context *ctx, + struct sieve_ast_argument *key_arg); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-match.c b/pigeonhole/src/lib-sieve/sieve-match.c new file mode 100644 index 0000000..37d37fe --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-match.c @@ -0,0 +1,293 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "mempool.h" +#include "hash.h" +#include "array.h" +#include "str-sanitize.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-runtime-trace.h" + +#include "sieve-match.h" + +/* + * Matching implementation + */ + +struct sieve_match_context *sieve_match_begin +(const struct sieve_runtime_env *renv, + const struct sieve_match_type *mcht, + const struct sieve_comparator *cmp) +{ + struct sieve_match_context *mctx; + pool_t pool; + + /* Reject unimplemented match-type */ + if ( mcht->def == NULL || (mcht->def->match == NULL && + mcht->def->match_keys == NULL && mcht->def->match_key == NULL) ) + return NULL; + + /* Create match context */ + pool = pool_alloconly_create("sieve_match_context", 1024); + mctx = p_new(pool, struct sieve_match_context, 1); + mctx->pool = pool; + mctx->runenv = renv; + mctx->match_type = mcht; + mctx->comparator = cmp; + mctx->exec_status = SIEVE_EXEC_OK; + mctx->trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); + + /* Trace */ + if ( mctx->trace ) { + sieve_runtime_trace_descend(renv); + sieve_runtime_trace(renv, 0, + "starting `:%s' match with `%s' comparator:", + sieve_match_type_name(mcht), sieve_comparator_name(cmp)); + } + + /* Initialize match type */ + if ( mcht->def != NULL && mcht->def->match_init != NULL ) { + mcht->def->match_init(mctx); + } + + return mctx; +} + +int sieve_match_value +(struct sieve_match_context *mctx, const char *value, size_t value_size, + struct sieve_stringlist *key_list) +{ + const struct sieve_match_type *mcht = mctx->match_type; + const struct sieve_runtime_env *renv = mctx->runenv; + int match, ret; + + if ( mctx->trace ) { + sieve_runtime_trace(renv, 0, + "matching value `%s'", str_sanitize(value, 80)); + } + + /* Match to key values */ + + sieve_stringlist_reset(key_list); + + if ( mctx->trace ) + sieve_stringlist_set_trace(key_list, TRUE); + + sieve_runtime_trace_descend(renv); + + if ( mcht->def->match_keys != NULL ) { + /* Call match-type's own key match handler */ + match = mcht->def->match_keys(mctx, value, value_size, key_list); + } else { + string_t *key_item = NULL; + + /* Default key match loop */ + match = 0; + while ( match == 0 && + (ret=sieve_stringlist_next_item(key_list, &key_item)) > 0 ) { + T_BEGIN { + match = mcht->def->match_key + (mctx, value, value_size, str_c(key_item), str_len(key_item)); + + if ( mctx->trace ) { + sieve_runtime_trace(renv, 0, + "with key `%s' => %d", str_sanitize(str_c(key_item), 80), + match); + } + } T_END; + } + + if ( ret < 0 ) { + mctx->exec_status = key_list->exec_status; + match = -1; + } + } + + sieve_runtime_trace_ascend(renv); + + if ( mctx->match_status < 0 || match < 0 ) + mctx->match_status = -1; + else + mctx->match_status = + ( mctx->match_status > match ? mctx->match_status : match ); + return match; +} + +int sieve_match_end(struct sieve_match_context **mctx, int *exec_status) +{ + const struct sieve_match_type *mcht = (*mctx)->match_type; + const struct sieve_runtime_env *renv = (*mctx)->runenv; + int match = (*mctx)->match_status; + + if ( mcht->def != NULL && mcht->def->match_deinit != NULL ) + mcht->def->match_deinit(*mctx); + + if ( exec_status != NULL ) + *exec_status = (*mctx)->exec_status; + + pool_unref(&(*mctx)->pool); + + sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, + "finishing match with result: %s", + ( match > 0 ? "matched" : ( match < 0 ? "error" : "not matched" ) )); + sieve_runtime_trace_ascend(renv); + + return match; +} + +int sieve_match +(const struct sieve_runtime_env *renv, + const struct sieve_match_type *mcht, + const struct sieve_comparator *cmp, + struct sieve_stringlist *value_list, + struct sieve_stringlist *key_list, + int *exec_status) +{ + struct sieve_match_context *mctx; + string_t *value_item = NULL; + int match, ret; + + if ( (mctx=sieve_match_begin(renv, mcht, cmp)) == NULL ) + return 0; + + /* Match value to keys */ + + sieve_stringlist_reset(value_list); + + if ( mctx->trace ) + sieve_stringlist_set_trace(value_list, TRUE); + + if ( mcht->def->match != NULL ) { + /* Call match-type's match handler */ + match = mctx->match_status = + mcht->def->match(mctx, value_list, key_list); + + } else { + /* Default value match loop */ + + match = 0; + while ( match == 0 && + (ret=sieve_stringlist_next_item(value_list, &value_item)) > 0 ) { + + match = sieve_match_value + (mctx, str_c(value_item), str_len(value_item), key_list); + } + + if ( ret < 0 ) { + mctx->exec_status = value_list->exec_status; + match = -1; + } + } + + (void)sieve_match_end(&mctx, exec_status); + return match; +} + +/* + * Reading match operands + */ + +int sieve_match_opr_optional_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address, int *opt_code) +{ + int _opt_code = 0; + bool final = FALSE, opok = TRUE; + + if ( opt_code == NULL ) { + opt_code = &_opt_code; + final = TRUE; + } + + while ( opok ) { + int opt; + + if ( (opt=sieve_opr_optional_dump(denv, address, opt_code)) <= 0 ) + return opt; + + switch ( *opt_code ) { + case SIEVE_MATCH_OPT_COMPARATOR: + opok = sieve_opr_comparator_dump(denv, address); + break; + case SIEVE_MATCH_OPT_MATCH_TYPE: + opok = sieve_opr_match_type_dump(denv, address); + break; + default: + return ( final ? -1 : 1 ); + } + } + + return -1; +} + +int sieve_match_opr_optional_read +(const struct sieve_runtime_env *renv, sieve_size_t *address, int *opt_code, + int *exec_status, struct sieve_comparator *cmp, struct sieve_match_type *mcht) +{ + int _opt_code = 0; + bool final = FALSE; + int status = SIEVE_EXEC_OK; + + if ( opt_code == NULL ) { + opt_code = &_opt_code; + final = TRUE; + } + + if ( exec_status != NULL ) + *exec_status = SIEVE_EXEC_OK; + + while ( status == SIEVE_EXEC_OK ) { + int opt; + + if ( (opt=sieve_opr_optional_read(renv, address, opt_code)) <= 0 ){ + if ( opt < 0 && exec_status != NULL ) + *exec_status = SIEVE_EXEC_BIN_CORRUPT; + return opt; + } + + switch ( *opt_code ) { + case SIEVE_MATCH_OPT_COMPARATOR: + if (cmp == NULL) { + sieve_runtime_trace_error(renv, "unexpected comparator operand"); + if ( exec_status != NULL ) + *exec_status = SIEVE_EXEC_BIN_CORRUPT; + return -1; + } + status = sieve_opr_comparator_read(renv, address, cmp); + break; + case SIEVE_MATCH_OPT_MATCH_TYPE: + if (mcht == NULL) { + sieve_runtime_trace_error(renv, "unexpected match-type operand"); + if ( exec_status != NULL ) + *exec_status = SIEVE_EXEC_BIN_CORRUPT; + return -1; + } + status = sieve_opr_match_type_read(renv, address, mcht); + break; + default: + if ( final ) { + sieve_runtime_trace_error(renv, "invalid optional operand"); + if ( exec_status != NULL ) + *exec_status = SIEVE_EXEC_BIN_CORRUPT; + return -1; + } + return 1; + } + } + + if ( exec_status != NULL ) + *exec_status = status; + return -1; +} + diff --git a/pigeonhole/src/lib-sieve/sieve-match.h b/pigeonhole/src/lib-sieve/sieve-match.h new file mode 100644 index 0000000..d4d726f --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-match.h @@ -0,0 +1,68 @@ +#ifndef SIEVE_MATCH_H +#define SIEVE_MATCH_H + +#include "sieve-common.h" + +/* + * Matching context + */ + +struct sieve_match_context { + pool_t pool; + + const struct sieve_runtime_env *runenv; + + const struct sieve_match_type *match_type; + const struct sieve_comparator *comparator; + + void *data; + + int match_status; + int exec_status; + + bool trace:1; +}; + +/* + * Matching implementation + */ + +/* Manual value iteration (for when multiple matches are allowed) */ +struct sieve_match_context *sieve_match_begin + (const struct sieve_runtime_env *renv, + const struct sieve_match_type *mcht, + const struct sieve_comparator *cmp); +int sieve_match_value + (struct sieve_match_context *mctx, const char *value, size_t value_size, + struct sieve_stringlist *key_list); +int sieve_match_end(struct sieve_match_context **mctx, int *exec_status); + +/* Default matching operation */ +int sieve_match + (const struct sieve_runtime_env *renv, + const struct sieve_match_type *mcht, + const struct sieve_comparator *cmp, + struct sieve_stringlist *value_list, + struct sieve_stringlist *key_list, + int *exec_status); + +/* + * Read matching operands + */ + +enum sieve_match_opt_operand { + SIEVE_MATCH_OPT_END, + SIEVE_MATCH_OPT_COMPARATOR, + SIEVE_MATCH_OPT_MATCH_TYPE, + SIEVE_MATCH_OPT_LAST +}; + +int sieve_match_opr_optional_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address, int *opt_code); + +int sieve_match_opr_optional_read + (const struct sieve_runtime_env *renv, sieve_size_t *address, int *opt_code, + int *exec_status, struct sieve_comparator *cmp, + struct sieve_match_type *mcht); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-message.c b/pigeonhole/src/lib-sieve/sieve-message.c new file mode 100644 index 0000000..d086883 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-message.c @@ -0,0 +1,1845 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "ioloop.h" +#include "mempool.h" +#include "array.h" +#include "str.h" +#include "str-sanitize.h" +#include "istream.h" +#include "time-util.h" +#include "rfc822-parser.h" +#include "message-date.h" +#include "message-parser.h" +#include "message-decoder.h" +#include "message-header-decode.h" +#include "mail-html2text.h" +#include "mail-storage.h" +#include "mail-user.h" +#include "smtp-params.h" +#include "master-service.h" +#include "master-service-settings.h" +#include "raw-storage.h" + +#include "edit-mail.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-error.h" +#include "sieve-extensions.h" +#include "sieve-code.h" +#include "sieve-address.h" +#include "sieve-address-parts.h" +#include "sieve-runtime.h" +#include "sieve-runtime-trace.h" +#include "sieve-match.h" +#include "sieve-interpreter.h" + +#include "sieve-message.h" + +/* + * Message transmission + */ + +const char *sieve_message_get_new_id(const struct sieve_instance *svinst) +{ + static int count = 0; + + return t_strdup_printf("<dovecot-sieve-%s-%s-%d@%s>", + dec2str(ioloop_timeval.tv_sec), dec2str(ioloop_timeval.tv_usec), + count++, svinst->hostname); +} + +/* + * Message context + */ + +struct sieve_message_header { + const char *name; + + const unsigned char *value, *utf8_value; + size_t value_len, utf8_value_len; +}; + +struct sieve_message_part { + struct sieve_message_part *parent, *next, *children; + + ARRAY(struct sieve_message_header) headers; + + const char *content_type; + const char *content_disposition; + + const char *decoded_body; + const char *text_body; + size_t decoded_body_size; + size_t text_body_size; + + bool have_body:1; /* there's the empty end-of-headers line */ + bool epilogue:1; /* this is a multipart epilogue */ +}; + +struct sieve_message_version { + struct mail *mail; + struct mailbox *box; + struct mailbox_transaction_context *trans; + struct edit_mail *edit_mail; +}; + +struct sieve_message_context { + pool_t pool; + pool_t context_pool; + int refcount; + + struct sieve_instance *svinst; + struct timeval time; + + struct mail_user *mail_user; + const struct sieve_message_data *msgdata; + + /* Message versioning */ + + struct mail_user *raw_mail_user; + ARRAY(struct sieve_message_version) versions; + + /* Context data for extensions */ + + ARRAY(void *) ext_contexts; + + /* Body */ + + ARRAY(struct sieve_message_part *) cached_body_parts; + ARRAY(struct sieve_message_part_data) return_body_parts; + buffer_t *raw_body; + + bool edit_snapshot:1; + bool substitute_snapshot:1; +}; + +/* + * Message versions + */ + +static inline struct sieve_message_version *sieve_message_version_new +(struct sieve_message_context *msgctx) +{ + return array_append_space(&msgctx->versions); +} + +static inline struct sieve_message_version *sieve_message_version_get +(struct sieve_message_context *msgctx) +{ + struct sieve_message_version *versions; + unsigned int count; + + versions = array_get_modifiable(&msgctx->versions, &count); + if ( count == 0 ) + return array_append_space(&msgctx->versions); + + return &versions[count-1]; +} + +static inline void sieve_message_version_free +(struct sieve_message_version *version) +{ + if ( version->edit_mail != NULL ) { + edit_mail_unwrap(&version->edit_mail); + version->edit_mail = NULL; + } + + if ( version->mail != NULL ) { + mail_free(&version->mail); + mailbox_transaction_rollback(&version->trans); + mailbox_free(&version->box); + version->mail = NULL; + } +} + +/* + * Message context object + */ + +struct sieve_message_context *sieve_message_context_create +(struct sieve_instance *svinst, struct mail_user *mail_user, + const struct sieve_message_data *msgdata) +{ + struct sieve_message_context *msgctx; + + msgctx = i_new(struct sieve_message_context, 1); + msgctx->refcount = 1; + msgctx->svinst = svinst; + + msgctx->mail_user = mail_user; + msgctx->msgdata = msgdata; + + i_gettimeofday(&msgctx->time); + + sieve_message_context_reset(msgctx); + + return msgctx; +} + +void sieve_message_context_ref(struct sieve_message_context *msgctx) +{ + msgctx->refcount++; +} + +static void sieve_message_context_clear(struct sieve_message_context *msgctx) +{ + struct sieve_message_version *versions; + unsigned int count, i; + + if ( msgctx->pool != NULL ) { + versions = array_get_modifiable(&msgctx->versions, &count); + + for ( i = 0; i < count; i++ ) { + sieve_message_version_free(&versions[i]); + } + + pool_unref(&(msgctx->pool)); + } +} + +void sieve_message_context_unref(struct sieve_message_context **msgctx) +{ + i_assert((*msgctx)->refcount > 0); + + if (--(*msgctx)->refcount != 0) + return; + + if ( (*msgctx)->raw_mail_user != NULL ) + mail_user_unref(&(*msgctx)->raw_mail_user); + + sieve_message_context_clear(*msgctx); + + if ( (*msgctx)->context_pool != NULL ) + pool_unref(&((*msgctx)->context_pool)); + + i_free(*msgctx); + *msgctx = NULL; +} + +static void sieve_message_context_flush(struct sieve_message_context *msgctx) +{ + pool_t pool; + + if ( msgctx->context_pool != NULL ) + pool_unref(&(msgctx->context_pool)); + + msgctx->context_pool = pool = + pool_alloconly_create("sieve_message_context_data", 2048); + + p_array_init(&msgctx->ext_contexts, pool, + sieve_extensions_get_count(msgctx->svinst)); + + p_array_init(&msgctx->cached_body_parts, pool, 8); + p_array_init(&msgctx->return_body_parts, pool, 8); + msgctx->raw_body = NULL; +} + +void sieve_message_context_reset(struct sieve_message_context *msgctx) +{ + sieve_message_context_clear(msgctx); + + msgctx->pool = pool_alloconly_create("sieve_message_context", 1024); + + p_array_init(&msgctx->versions, msgctx->pool, 4); + + sieve_message_context_flush(msgctx); +} + +pool_t sieve_message_context_pool(struct sieve_message_context *msgctx) +{ + return msgctx->context_pool; +} + +void sieve_message_context_time(struct sieve_message_context *msgctx, + struct timeval *time) +{ + *time = msgctx->time; +} + +/* Extension support */ + +void sieve_message_context_extension_set +(struct sieve_message_context *msgctx, const struct sieve_extension *ext, + void *context) +{ + if ( ext->id < 0 ) return; + + array_idx_set(&msgctx->ext_contexts, (unsigned int) ext->id, &context); +} + +const void *sieve_message_context_extension_get +(struct sieve_message_context *msgctx, const struct sieve_extension *ext) +{ + void * const *ctx; + + if ( ext->id < 0 || ext->id >= (int) array_count(&msgctx->ext_contexts) ) + return NULL; + + ctx = array_idx(&msgctx->ext_contexts, (unsigned int) ext->id); + + return *ctx; +} + +/* Envelope */ + +const struct smtp_address *sieve_message_get_orig_recipient +(struct sieve_message_context *msgctx) +{ + const struct sieve_message_data *msgdata = msgctx->msgdata; + const struct smtp_address *orcpt_to = NULL; + + if ( msgdata->envelope.rcpt_params != NULL ) { + orcpt_to = msgdata->envelope.rcpt_params->orcpt.addr; + if ( !smtp_address_isnull(orcpt_to) ) + return orcpt_to; + } + + orcpt_to = msgdata->envelope.rcpt_to; + return ( !smtp_address_isnull(orcpt_to) ? orcpt_to : NULL ); +} + +const struct smtp_address *sieve_message_get_final_recipient +(struct sieve_message_context *msgctx) +{ + const struct sieve_message_data *msgdata = msgctx->msgdata; + const struct smtp_address *rcpt_to = msgdata->envelope.rcpt_to; + + return ( !smtp_address_isnull(rcpt_to) ? rcpt_to : NULL); +} + +const struct smtp_address *sieve_message_get_sender +(struct sieve_message_context *msgctx) +{ + const struct sieve_message_data *msgdata = msgctx->msgdata; + const struct smtp_address *mail_from = msgdata->envelope.mail_from; + + return ( !smtp_address_isnull(mail_from) ? mail_from : NULL); +} + +/* + * Mail + */ + +int sieve_message_substitute +(struct sieve_message_context *msgctx, struct istream *input) +{ + static const char *wanted_headers[] = { + "From", "Message-ID", "Subject", "Return-Path", NULL + }; + static const struct smtp_address default_sender = { + .localpart = DEFAULT_ENVELOPE_SENDER, + .domain = NULL, + }; + struct mail_user *mail_user = msgctx->mail_user; + struct sieve_message_version *version; + struct mailbox_header_lookup_ctx *headers_ctx; + struct mailbox *box = NULL; + const struct smtp_address *sender; + int ret; + + i_assert(input->blocking); + + if ( msgctx->raw_mail_user == NULL ) { + void **sets = master_service_settings_get_others(master_service); + + msgctx->raw_mail_user = + raw_storage_create_from_set(mail_user->set_info, sets[0]); + } + + i_stream_seek(input, 0); + sender = sieve_message_get_sender(msgctx); + sender = (sender == NULL ? &default_sender : sender); + ret = raw_mailbox_alloc_stream(msgctx->raw_mail_user, input, (time_t)-1, + smtp_address_encode(sender), &box); + + if ( ret < 0 ) { + e_error(msgctx->svinst->event, + "can't open substituted mail as raw: %s", + mailbox_get_last_internal_error(box, NULL)); + return -1; + } + + if ( msgctx->substitute_snapshot ) { + version = sieve_message_version_new(msgctx); + } else { + version = sieve_message_version_get(msgctx); + sieve_message_version_free(version); + } + + version->box = box; + version->trans = mailbox_transaction_begin(box, 0, __func__); + headers_ctx = mailbox_header_lookup_init(box, wanted_headers); + version->mail = mail_alloc(version->trans, 0, headers_ctx); + mailbox_header_lookup_unref(&headers_ctx); + mail_set_seq(version->mail, 1); + + sieve_message_context_flush(msgctx); + + msgctx->substitute_snapshot = FALSE; + msgctx->edit_snapshot = FALSE; + + return 1; +} + +struct mail *sieve_message_get_mail +(struct sieve_message_context *msgctx) +{ + const struct sieve_message_version *versions; + unsigned int count; + + versions = array_get(&msgctx->versions, &count); + if ( count == 0 ) + return msgctx->msgdata->mail; + + if ( versions[count-1].edit_mail != NULL ) + return edit_mail_get_mail(versions[count-1].edit_mail); + + return versions[count-1].mail; +} + +struct edit_mail *sieve_message_edit +(struct sieve_message_context *msgctx) +{ + struct sieve_message_version *version; + + version = sieve_message_version_get(msgctx); + + if ( version->edit_mail == NULL ) { + version->edit_mail = edit_mail_wrap + (( version->mail == NULL ? msgctx->msgdata->mail : version->mail )); + } else if ( msgctx->edit_snapshot ) { + version->edit_mail = edit_mail_snapshot(version->edit_mail); + } + + msgctx->edit_snapshot = FALSE; + + return version->edit_mail; +} + +void sieve_message_snapshot +(struct sieve_message_context *msgctx) +{ + msgctx->edit_snapshot = TRUE; + msgctx->substitute_snapshot = TRUE; +} + +/* + * Message header list + */ + +/* Forward declarations */ + +static int sieve_message_header_list_next_item + (struct sieve_header_list *_hdrlist, const char **name_r, + string_t **value_r); +static int sieve_message_header_list_next_value + (struct sieve_stringlist *_strlist, string_t **value_r); +static void sieve_message_header_list_reset + (struct sieve_stringlist *_strlist); + +/* String list object */ + +struct sieve_message_header_list { + struct sieve_header_list hdrlist; + + struct sieve_stringlist *field_names; + + const char *header_name; + const char *const *headers; + int headers_index; + + bool mime_decode:1; +}; + +struct sieve_header_list *sieve_message_header_list_create +(const struct sieve_runtime_env *renv, + struct sieve_stringlist *field_names, + bool mime_decode) +{ + struct sieve_message_header_list *hdrlist; + + hdrlist = t_new(struct sieve_message_header_list, 1); + hdrlist->hdrlist.strlist.runenv = renv; + hdrlist->hdrlist.strlist.exec_status = SIEVE_EXEC_OK; + hdrlist->hdrlist.strlist.next_item = sieve_message_header_list_next_value; + hdrlist->hdrlist.strlist.reset = sieve_message_header_list_reset; + hdrlist->hdrlist.next_item = sieve_message_header_list_next_item; + hdrlist->field_names = field_names; + hdrlist->mime_decode = mime_decode; + + return &hdrlist->hdrlist; +} + +// NOTE: get rid of this once we have a proper Sieve string type +static inline string_t *_header_right_trim(const char *raw) +{ + string_t *result; + const char *p, *pend; + + pend = raw + strlen(raw); + if (raw == pend) { + result = t_str_new(1); + } else { + for ( p = pend-1; p >= raw; p-- ) { + if ( *p != ' ' && *p != '\t' ) break; + } + result = t_str_new(p - raw + 1); + str_append_data(result, raw, p - raw + 1); + } + return result; +} + +/* String list implementation */ + +static int sieve_message_header_list_next_item +(struct sieve_header_list *_hdrlist, const char **name_r, + string_t **value_r) +{ + struct sieve_message_header_list *hdrlist = + (struct sieve_message_header_list *) _hdrlist; + const struct sieve_runtime_env *renv = _hdrlist->strlist.runenv; + struct mail *mail = sieve_message_get_mail(renv->msgctx); + + if ( name_r != NULL ) + *name_r = NULL; + *value_r = NULL; + + /* Check for end of current header list */ + if ( hdrlist->headers == NULL ) { + hdrlist->headers_index = 0; + } else if ( hdrlist->headers[hdrlist->headers_index] == NULL ) { + hdrlist->headers = NULL; + hdrlist->headers_index = 0; + } + + /* Fetch next header */ + while ( hdrlist->headers == NULL ) { + string_t *hdr_item = NULL; + int ret; + + /* Read next header name from source list */ + if ( (ret=sieve_stringlist_next_item + (hdrlist->field_names, &hdr_item)) <= 0 ) + return ret; + + hdrlist->header_name = str_c(hdr_item); + + if ( _hdrlist->strlist.trace ) { + sieve_runtime_trace(renv, 0, + "extracting `%s' headers from message", + str_sanitize(str_c(hdr_item), 80)); + } + + /* Fetch all matching headers from the e-mail */ + if ( hdrlist->mime_decode ) { + ret = mail_get_headers_utf8(mail, + str_c(hdr_item), &hdrlist->headers); + } else { + ret = mail_get_headers(mail, + str_c(hdr_item), &hdrlist->headers); + } + + if (ret < 0) { + _hdrlist->strlist.exec_status = + sieve_runtime_mail_error(renv, mail, + "failed to read header field `%s'", str_c(hdr_item)); + return -1; + } + + if ( ret == 0 || hdrlist->headers[0] == NULL ) { + /* Try next item when no headers found */ + hdrlist->headers = NULL; + } + } + + /* Return next item */ + if ( name_r != NULL ) + *name_r = hdrlist->header_name; + *value_r = _header_right_trim(hdrlist->headers[hdrlist->headers_index++]); + return 1; +} + +static int sieve_message_header_list_next_value +(struct sieve_stringlist *_strlist, string_t **value_r) +{ + struct sieve_header_list *hdrlist = + (struct sieve_header_list *) _strlist; + + return sieve_message_header_list_next_item + (hdrlist, NULL, value_r); +} + +static void sieve_message_header_list_reset +(struct sieve_stringlist *strlist) +{ + struct sieve_message_header_list *hdrlist = + (struct sieve_message_header_list *) strlist; + + hdrlist->headers = NULL; + hdrlist->headers_index = 0; + sieve_stringlist_reset(hdrlist->field_names); +} + +/* + * Header override operand + */ + +const struct sieve_operand_class sieve_message_override_operand_class = + { "header-override" }; + +bool sieve_opr_message_override_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + struct sieve_message_override svmo; + const struct sieve_message_override_def *hodef; + + if ( !sieve_opr_object_dump + (denv, &sieve_message_override_operand_class, address, &svmo.object) ) + return FALSE; + + hodef = svmo.def = + (const struct sieve_message_override_def *) svmo.object.def; + + if ( hodef->dump_context != NULL ) { + sieve_code_descend(denv); + if ( !hodef->dump_context(&svmo, denv, address) ) { + return FALSE; + } + sieve_code_ascend(denv); + } + + return TRUE; +} + +int sieve_opr_message_override_read +(const struct sieve_runtime_env *renv, sieve_size_t *address, + struct sieve_message_override *svmo) +{ + const struct sieve_message_override_def *hodef; + int ret; + + svmo->context = NULL; + + if ( !sieve_opr_object_read + (renv, &sieve_message_override_operand_class, address, &svmo->object) ) + return SIEVE_EXEC_BIN_CORRUPT; + + hodef = svmo->def = + (const struct sieve_message_override_def *) svmo->object.def; + + if ( hodef->read_context != NULL && + (ret=hodef->read_context(svmo, renv, address, &svmo->context)) <= 0 ) + return ret; + + return SIEVE_EXEC_OK; +} + +/* + * Optional operands + */ + +int sieve_message_opr_optional_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address, + signed int *opt_code) +{ + signed int _opt_code = 0; + bool final = FALSE, opok = TRUE; + + if ( opt_code == NULL ) { + opt_code = &_opt_code; + final = TRUE; + } + + while ( opok ) { + int opt; + + if ( (opt=sieve_addrmatch_opr_optional_dump + (denv, address, opt_code)) <= 0 ) + return opt; + + if ( *opt_code == SIEVE_OPT_MESSAGE_OVERRIDE ) { + opok = sieve_opr_message_override_dump(denv, address); + } else { + return ( final ? -1 : 1 ); + } + } + + return -1; +} + +int sieve_message_opr_optional_read +(const struct sieve_runtime_env *renv, sieve_size_t *address, + signed int *opt_code, int *exec_status, + struct sieve_address_part *addrp, struct sieve_match_type *mcht, + struct sieve_comparator *cmp, + ARRAY_TYPE(sieve_message_override) *svmos) +{ + signed int _opt_code = 0; + bool final = FALSE; + int ret; + + if ( opt_code == NULL ) { + opt_code = &_opt_code; + final = TRUE; + } + + if ( exec_status != NULL ) + *exec_status = SIEVE_EXEC_OK; + + for ( ;; ) { + int opt; + + if ( (opt=sieve_addrmatch_opr_optional_read + (renv, address, opt_code, exec_status, addrp, mcht, cmp)) <= 0 ) + return opt; + + if ( *opt_code == SIEVE_OPT_MESSAGE_OVERRIDE ) { + struct sieve_message_override svmo; + const struct sieve_message_override *svmo_idx; + unsigned int count, i; + + if ( (ret=sieve_opr_message_override_read + (renv, address, &svmo)) <= 0 ) { + if ( exec_status != NULL ) + *exec_status = ret; + return -1; + } + + if ( !array_is_created(svmos) ) + t_array_init(svmos, 8); + /* insert in sorted sequence */ + svmo_idx = array_get(svmos, &count); + for (i = 0; i < count; i++) { + if (svmo.def->sequence < svmo_idx[i].def->sequence) { + array_insert(svmos, i, &svmo, 1); + break; + } + } + if (count == i) + array_append(svmos, &svmo, 1); + } else { + if ( final ) { + sieve_runtime_trace_error(renv, "invalid optional operand"); + if ( exec_status != NULL ) + *exec_status = SIEVE_EXEC_BIN_CORRUPT; + return -1; + } + return 1; + } + } + + i_unreached(); + return -1; +} + +/* + * Message header + */ + +int sieve_message_get_header_fields +(const struct sieve_runtime_env *renv, + struct sieve_stringlist *field_names, + ARRAY_TYPE(sieve_message_override) *svmos, + bool mime_decode, struct sieve_stringlist **fields_r) +{ + const struct sieve_message_override *svmo; + unsigned int count, i; + int ret; + + if ( svmos == NULL || !array_is_created(svmos) || + array_count(svmos) == 0 ) { + struct sieve_header_list *headers; + headers = sieve_message_header_list_create + (renv, field_names, mime_decode); + *fields_r = &headers->strlist; + return SIEVE_EXEC_OK; + } + + svmo = array_get(svmos, &count); + if ( svmo[0].def->sequence == 0 && + svmo[0].def->header_override != NULL ) { + *fields_r = field_names; + } else { + struct sieve_header_list *headers; + headers = sieve_message_header_list_create + (renv, field_names, mime_decode); + *fields_r = &headers->strlist; + } + + for ( i = 0; i < count; i++ ) { + if ( svmo[i].def->header_override != NULL && + (ret=svmo[i].def->header_override + (&svmo[i], renv, mime_decode, fields_r)) <= 0 ) + return ret; + } + return SIEVE_EXEC_OK; +} + +/* + * Message part + */ + +struct sieve_message_part *sieve_message_part_parent +(struct sieve_message_part *mpart) +{ + return mpart->parent; +} + +struct sieve_message_part *sieve_message_part_next +(struct sieve_message_part *mpart) +{ + return mpart->next; +} + +struct sieve_message_part *sieve_message_part_children +(struct sieve_message_part *mpart) +{ + return mpart->children; +} + +const char *sieve_message_part_content_type +(struct sieve_message_part *mpart) +{ + return mpart->content_type; +} + +const char *sieve_message_part_content_disposition +(struct sieve_message_part *mpart) +{ + return mpart->content_disposition; +} + +int sieve_message_part_get_first_header +(struct sieve_message_part *mpart, const char *field, + const char **value_r) +{ + const struct sieve_message_header *headers; + unsigned int i, count; + + headers = array_get(&mpart->headers, &count); + for ( i = 0; i < count; i++ ) { + if ( strcasecmp( headers[i].name, field) == 0 ) { + i_assert( headers[i].value[headers[i].value_len] == '\0' ); + *value_r = (const char *)headers[i].value; + return 1; + } + } + + *value_r = NULL; + return 0; +} + +void sieve_message_part_get_data +(struct sieve_message_part *mpart, + struct sieve_message_part_data *data, bool text) +{ + i_zero(data); + data->content_type = mpart->content_type; + data->content_disposition = mpart->content_disposition; + + if ( !text ) { + data->content = mpart->decoded_body; + data->size = mpart->decoded_body_size; + } else if ( mpart->children != NULL ) { + data->content = ""; + data->size = 0; + } else { + data->content = mpart->text_body; + data->size = mpart->text_body_size; + } +} + +/* + * Message body + */ + +static void str_replace_nuls(string_t *str) +{ + char *data = str_c_modifiable(str); + unsigned int i, len = str_len(str); + + for (i = 0; i < len; i++) { + if (data[i] == '\0') + data[i] = ' '; + } +} + +static bool _is_wanted_content_type +(const char * const *wanted_types, const char *content_type) +ATTR_NULL(1) +{ + const char *subtype; + size_t type_len; + + if ( wanted_types == NULL ) + return TRUE; + + subtype = strchr(content_type, '/'); + type_len = ( subtype == NULL ? strlen(content_type) : + (size_t)(subtype - content_type) ); + + i_assert( wanted_types != NULL ); + + for (; *wanted_types != NULL; wanted_types++) { + const char *wanted_subtype; + + if (**wanted_types == '\0') { + /* empty string matches everything */ + return TRUE; + } + + wanted_subtype = strchr(*wanted_types, '/'); + if (wanted_subtype == NULL) { + /* match only main type */ + if (strlen(*wanted_types) == type_len && + strncasecmp(*wanted_types, content_type, type_len) == 0) + return TRUE; + } else { + /* match whole type/subtype */ + if (strcasecmp(*wanted_types, content_type) == 0) + return TRUE; + } + } + return FALSE; +} + +static bool sieve_message_body_get_return_parts +(const struct sieve_runtime_env *renv, + const char * const *wanted_types, + bool extract_text) +{ + struct sieve_message_context *msgctx = renv->msgctx; + struct sieve_message_part *const *body_parts; + unsigned int i, count; + struct sieve_message_part_data *return_part; + + /* Check whether any body parts are cached already */ + body_parts = array_get(&msgctx->cached_body_parts, &count); + if ( count == 0 ) + return FALSE; + + /* Clear result array */ + array_clear(&msgctx->return_body_parts); + + /* Fill result array with requested content_types */ + for (i = 0; i < count; i++) { + if (!body_parts[i]->have_body) { + /* Part has no body; according to RFC this MUST not match to anything and + * therefore it is not included in the result. + */ + continue; + } + + /* Skip content types that are not requested */ + if (!_is_wanted_content_type + (wanted_types, body_parts[i]->content_type)) + continue; + + /* Add new item to the result */ + return_part = array_append_space(&msgctx->return_body_parts); + return_part->content_type = body_parts[i]->content_type; + return_part->content_disposition = body_parts[i]->content_disposition; + + /* Depending on whether a decoded body part is requested, the appropriate + * cache item is read. If it is missing, this function fails and the cache + * needs to be completed by sieve_message_parts_add_missing(). + */ + if (extract_text) { + if (body_parts[i]->text_body == NULL) + return FALSE; + return_part->content = body_parts[i]->text_body; + return_part->size = body_parts[i]->text_body_size; + } else { + if (body_parts[i]->decoded_body == NULL) + return FALSE; + return_part->content = body_parts[i]->decoded_body; + return_part->size = body_parts[i]->decoded_body_size; + } + } + + return TRUE; +} + +static void sieve_message_part_save +(const struct sieve_runtime_env *renv, buffer_t *buf, + struct sieve_message_part *body_part, + bool extract_text) +{ + struct sieve_message_context *msgctx = renv->msgctx; + pool_t pool = msgctx->context_pool; + buffer_t *result_buf, *text_buf = NULL; + char *part_data; + size_t part_size; + + /* Extract text if requested */ + result_buf = buf; + if ( extract_text && body_part->children == NULL && + !body_part->epilogue ) { + + if ( buf->used > 0 && mail_html2text_content_type_match + (body_part->content_type) ) { + struct mail_html2text *html2text; + + text_buf = buffer_create_dynamic(default_pool, 4096); + + /* Remove HTML markup */ + html2text = mail_html2text_init(0); + mail_html2text_more(html2text, buf->data, buf->used, text_buf); + mail_html2text_deinit(&html2text); + + result_buf = text_buf; + } + } + + /* Add terminating NUL to the body part buffer */ + buffer_append_c(result_buf, '\0'); + + /* Make copy of the buffer */ + part_data = p_malloc(pool, result_buf->used); + memcpy(part_data, result_buf->data, result_buf->used); + part_size = result_buf->used - 1; + + /* Free text buffer if used */ + if ( text_buf != NULL) + buffer_free(&text_buf); + + /* Depending on whether the part is processed into text, store message + * body in the appropriate cache location. + */ + if ( !extract_text ) { + body_part->decoded_body = part_data; + body_part->decoded_body_size = part_size; + } else { + body_part->text_body = part_data; + body_part->text_body_size = part_size; + } + + /* Clear buffer */ + buffer_set_used_size(buf, 0); +} + +static const char * +_parse_content_type(const struct message_header_line *hdr) +{ + struct rfc822_parser_context parser; + string_t *content_type; + + /* Initialize parsing */ + rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL); + (void)rfc822_skip_lwsp(&parser); + + /* Parse content type */ + content_type = t_str_new(64); + if (rfc822_parse_content_type(&parser, content_type) < 0) + return ""; + + /* Content-type value must end here, otherwise it is invalid after all */ + (void)rfc822_skip_lwsp(&parser); + if ( parser.data != parser.end && *parser.data != ';' ) + return ""; + + /* Success */ + return str_c(content_type); +} + +static const char * +_parse_content_disposition(const struct message_header_line *hdr) +{ + struct rfc822_parser_context parser; + string_t *content_disp; + + /* Initialize parsing */ + rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL); + (void)rfc822_skip_lwsp(&parser); + + /* Parse content type */ + content_disp = t_str_new(64); + if (rfc822_parse_mime_token(&parser, content_disp) < 0) + return ""; + + /* Content-type value must end here, otherwise it is invalid after all */ + (void)rfc822_skip_lwsp(&parser); + if ( parser.data != parser.end && *parser.data != ';' ) + return ""; + + /* Success */ + return str_c(content_disp); +} + +/* sieve_message_parts_add_missing(): + * Add requested message body parts to the cache that are missing. + */ +static int sieve_message_parts_add_missing +(const struct sieve_runtime_env *renv, + const char *const *content_types, + bool extract_text, bool iter_all) + ATTR_NULL(2) +{ + struct sieve_message_context *msgctx = renv->msgctx; + pool_t pool = msgctx->context_pool; + struct mail *mail = sieve_message_get_mail(renv->msgctx); + struct message_parser_settings mparser_set = { + .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP, + .flags = MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS, + }; + ARRAY(struct sieve_message_header) headers; + struct sieve_message_part *body_part, *header_part, *last_part; + struct message_parser_ctx *parser; + struct message_decoder_context *decoder; + struct message_block block, decoded; + struct message_part *mparts, *prev_mpart = NULL; + buffer_t *buf; + struct istream *input; + unsigned int idx = 0; + bool save_body = FALSE, have_all; + string_t *hdr_content = NULL; + + /* First check whether any are missing */ + if ( !iter_all && sieve_message_body_get_return_parts + (renv, content_types, extract_text) ) { + /* Cache hit; all are present */ + return SIEVE_EXEC_OK; + } + + /* Get the message stream */ + if ( mail_get_stream(mail, NULL, NULL, &input) < 0 ) { + return sieve_runtime_mail_error(renv, mail, + "failed to open input message"); + } + if (mail_get_parts(mail, &mparts) < 0) { + return sieve_runtime_mail_error(renv, mail, + "failed to parse input message parts"); + } + + buf = buffer_create_dynamic(default_pool, 4096); + body_part = header_part = last_part = NULL; + + if (iter_all) { + t_array_init(&headers, 64); + hdr_content = t_str_new(512); + mparser_set.hdr_flags |= MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE; + } else { + i_zero(&headers); + } + + /* Initialize body decoder */ + decoder = message_decoder_init(NULL, 0); + + // FIXME: currently not tested with edit-mail. + //parser = message_parser_init_from_parts(parts, input, + // hparser_flags, mparser_flags); + parser = message_parser_init(pool_datastack_create(), + input, &mparser_set); + while ( message_parser_parse_next_block(parser, &block) > 0 ) { + struct sieve_message_part **body_part_idx; + struct message_header_line *hdr = block.hdr; + struct sieve_message_header *header; + unsigned char *data; + + if ( block.part != prev_mpart ) { + bool message_rfc822 = FALSE; + + /* Save previous body part */ + if ( body_part != NULL ) { + /* Treat message/rfc822 separately; headers become content */ + if ( block.part->parent == prev_mpart && + strcmp(body_part->content_type, "message/rfc822") == 0 ) { + message_rfc822 = TRUE; + } else { + if ( save_body ) { + sieve_message_part_save + (renv, buf, body_part, extract_text); + } + } + if ( iter_all && !array_is_created(&body_part->headers) && + array_count(&headers) > 0 ) { + p_array_init(&body_part->headers, pool, array_count(&headers)); + array_copy(&body_part->headers.arr, 0, + &headers.arr, 0, array_count(&headers)); + } + } + + /* Start processing next part */ + body_part_idx = array_idx_get_space + (&msgctx->cached_body_parts, idx); + if ( *body_part_idx == NULL ) + *body_part_idx = p_new(pool, struct sieve_message_part, 1); + body_part = *body_part_idx; + body_part->content_type = "text/plain"; + if ( iter_all ) + array_clear(&headers); + + /* Copy tree structure */ + if ( block.part->context != NULL ) { + struct sieve_message_part *epipart = + (struct sieve_message_part *)block.part->context; + i_assert(epipart != NULL); + + /* multipart epilogue */ + body_part->content_type = epipart->content_type; + body_part->have_body = TRUE; + body_part->epilogue = TRUE; + save_body = iter_all || _is_wanted_content_type + (content_types, body_part->content_type); + + } else { + struct sieve_message_part *parent = NULL; + + if ( block.part->parent != NULL ) { + body_part->parent = parent = + (struct sieve_message_part *) + block.part->parent->context; + } + + /* new part */ + block.part->context = (void*)body_part; + + if ( last_part != NULL ) { + i_assert( parent != NULL ); + if ( last_part->parent == parent ) { + last_part->next = body_part; + } else if (parent->children == NULL) { + parent->children = body_part; + } else { + struct sieve_message_part *child = parent->children; + while (child->next != NULL && child != body_part) + child = child->next; + if (child != body_part) + child->next = body_part; + } + } + } + last_part = body_part; + + /* If this is message/rfc822 content, retain the enveloping part for + * storing headers as content. + */ + if ( message_rfc822 ) { + i_assert(idx > 0); + body_part_idx = array_idx_modifiable + (&msgctx->cached_body_parts, idx-1); + header_part = *body_part_idx; + } else { + header_part = NULL; + } + + prev_mpart = block.part; + idx++; + } + + if ( hdr != NULL || block.size == 0 ) { + enum { + _HDR_CONTENT_TYPE, + _HDR_CONTENT_DISPOSITION, + _HDR_OTHER + } hdr_field; + + /* Reading headers */ + i_assert( body_part != NULL ); + + /* Decode block */ + (void)message_decoder_decode_next_block + (decoder, &block, &decoded); + + /* Check for end of headers */ + if ( hdr == NULL ) { + /* Save headers for message/rfc822 part */ + if ( header_part != NULL ) { + sieve_message_part_save + (renv, buf, header_part, FALSE); + header_part = NULL; + } + + /* Save bodies only if we have a wanted content-type */ + save_body = iter_all || _is_wanted_content_type + (content_types, body_part->content_type); + continue; + } + + /* Encountered the empty line that indicates the end of the headers and + * the start of the body + */ + if ( hdr->eoh ) { + body_part->have_body = TRUE; + continue; + } else if ( header_part != NULL ) { + /* Save message/rfc822 header as part content */ + if ( hdr->continued ) { + buffer_append(buf, hdr->value, hdr->value_len); + } else { + buffer_append(buf, hdr->name, hdr->name_len); + buffer_append(buf, hdr->middle, hdr->middle_len); + buffer_append(buf, hdr->value, hdr->value_len); + } + if ( !hdr->no_newline ) { + buffer_append(buf, "\r\n", 2); + } + } + + if ( strcasecmp(hdr->name, "Content-Type" ) == 0 ) + hdr_field = _HDR_CONTENT_TYPE; + else if ( strcasecmp(hdr->name, "Content-Disposition" ) == 0 ) + hdr_field = _HDR_CONTENT_DISPOSITION; + else if ( iter_all && !array_is_created(&body_part->headers) ) + hdr_field = _HDR_OTHER; + else { + /* Not interested in this header */ + continue; + } + + /* Header can have folding whitespace. Acquire the full value before + * continuing + */ + if ( hdr->continues ) { + hdr->use_full_value = TRUE; + continue; + } + + if ( iter_all && !array_is_created(&body_part->headers) ) { + const unsigned char *value, *vp; + size_t vlen; + + /* Add header */ + header = array_append_space(&headers); + header->name = p_strdup(pool, hdr->name); + + /* Trim end of field value (not done by parser) */ + value = hdr->full_value; + vp = value + hdr->full_value_len; + while ( vp > value && + (vp[-1] == '\t' || vp[-1] == ' ') ) + vp--; + vlen = (size_t)(vp - value); + + /* Decode MIME encoded-words. */ + str_truncate(hdr_content, 0); + message_header_decode_utf8 + (value, vlen, hdr_content, NULL); + if ( vlen != str_len(hdr_content) || + strncmp(str_c(hdr_content), (const char *)value, + vlen) != 0 ) { + if ( strlen(str_c(hdr_content)) != str_len(hdr_content) ) { + /* replace NULs with spaces */ + str_replace_nuls(hdr_content); + } + /* store raw */ + data = p_malloc(pool, vlen + 1); + data[vlen] = '\0'; + header->value = memcpy(data, value, vlen); + header->value_len = vlen; + /* store decoded */ + data = p_malloc(pool, str_len(hdr_content) + 1); + data[str_len(hdr_content)] = '\0'; + header->utf8_value = memcpy(data, + str_data(hdr_content), str_len(hdr_content)); + header->utf8_value_len = str_len(hdr_content); + } else { + /* raw == decoded */ + data = p_malloc(pool, vlen + 1); + data[vlen] = '\0'; + header->value = header->utf8_value = + memcpy(data, value, vlen); + header->value_len = header->utf8_value_len = vlen; + } + + if ( hdr_field == _HDR_OTHER ) + continue; + } + + /* Parse the content type from the Content-type header */ + T_BEGIN { + switch ( hdr_field ) { + case _HDR_CONTENT_TYPE: + body_part->content_type = + p_strdup(pool, _parse_content_type(block.hdr)); + break; + case _HDR_CONTENT_DISPOSITION: + body_part->content_disposition = + p_strdup(pool, _parse_content_disposition(block.hdr)); + break; + default: + i_unreached(); + } + } T_END; + + continue; + } + + /* Reading body */ + if ( save_body ) { + (void)message_decoder_decode_next_block + (decoder, &block, &decoded); + buffer_append(buf, decoded.data, decoded.size); + } + } + + /* even with an empty message there was at least the "end of headers" + block, which set the body_part. */ + i_assert( body_part != NULL ); + + /* Save last body part if necessary */ + if ( header_part != NULL ) { + sieve_message_part_save + (renv, buf, header_part, FALSE); + } else if ( save_body ) { + sieve_message_part_save + (renv, buf, body_part, extract_text); + } + if ( iter_all && !array_is_created(&body_part->headers) && + array_count(&headers) > 0 ) { + p_array_init(&body_part->headers, pool, array_count(&headers)); + array_copy(&body_part->headers.arr, 0, + &headers.arr, 0, array_count(&headers)); + } + + /* Try to fill the return_body_parts array once more */ + have_all = iter_all || sieve_message_body_get_return_parts + (renv, content_types, extract_text); + + /* This time, failure is a bug */ + i_assert(have_all); + + /* Cleanup */ + (void)message_parser_deinit(&parser, &mparts); + message_decoder_deinit(&decoder); + buffer_free(&buf); + + /* Return status */ + if ( input->stream_errno != 0 ) { + sieve_runtime_critical(renv, NULL, + "failed to read input message", + "read(%s) failed: %s", + i_stream_get_name(input), + i_stream_get_error(input)); + return SIEVE_EXEC_TEMP_FAILURE; + } + return SIEVE_EXEC_OK; +} + +int sieve_message_body_get_content +(const struct sieve_runtime_env *renv, + const char * const *content_types, + struct sieve_message_part_data **parts_r) +{ + struct sieve_message_context *msgctx = renv->msgctx; + int status; + + T_BEGIN { + /* Fill the return_body_parts array */ + status = sieve_message_parts_add_missing + (renv, content_types, FALSE, FALSE); + } T_END; + + /* Check status */ + if ( status <= 0 ) + return status; + + /* Return the array of body items */ + (void) array_append_space(&msgctx->return_body_parts); /* NULL-terminate */ + *parts_r = array_idx_modifiable(&msgctx->return_body_parts, 0); + + return status; +} + +int sieve_message_body_get_text +(const struct sieve_runtime_env *renv, + struct sieve_message_part_data **parts_r) +{ + static const char * const _text_content_types[] = + { "application/xhtml+xml", "text", NULL }; + struct sieve_message_context *msgctx = renv->msgctx; + int status; + + /* We currently only support extracting plain text from: + + - text/html -> HTML + - application/xhtml+xml -> XHTML + + Other text types are read as is. Any non-text types are skipped. + */ + + T_BEGIN { + /* Fill the return_body_parts array */ + status = sieve_message_parts_add_missing + (renv, _text_content_types, TRUE, FALSE); + } T_END; + + /* Check status */ + if ( status <= 0 ) + return status; + + /* Return the array of body items */ + (void) array_append_space(&msgctx->return_body_parts); /* NULL-terminate */ + *parts_r = array_idx_modifiable(&msgctx->return_body_parts, 0); + + return status; +} + +int sieve_message_body_get_raw +(const struct sieve_runtime_env *renv, + struct sieve_message_part_data **parts_r) +{ + struct sieve_message_context *msgctx = renv->msgctx; + struct sieve_message_part_data *return_part; + buffer_t *buf; + + if ( msgctx->raw_body == NULL ) { + struct mail *mail = sieve_message_get_mail(renv->msgctx); + struct istream *input; + struct message_size hdr_size, body_size; + const unsigned char *data; + size_t size; + int ret; + + msgctx->raw_body = buf = buffer_create_dynamic + (msgctx->context_pool, 1024*64); + + /* Get stream for message */ + if ( mail_get_stream(mail, &hdr_size, &body_size, &input) < 0 ) { + return sieve_runtime_mail_error(renv, mail, + "failed to open input message"); + } + + /* Skip stream to beginning of body */ + i_stream_skip(input, hdr_size.physical_size); + + /* Read raw message body */ + while ( (ret=i_stream_read_more(input, &data, &size)) > 0 ) { + buffer_append(buf, data, size); + + i_stream_skip(input, size); + } + + if ( ret < 0 && input->stream_errno != 0 ) { + sieve_runtime_critical(renv, NULL, + "failed to read input message", + "read(%s) failed: %s", + i_stream_get_name(input), + i_stream_get_error(input)); + return SIEVE_EXEC_TEMP_FAILURE; + } + + /* Add terminating NUL to the body part buffer */ + buffer_append_c(buf, '\0'); + + } else { + buf = msgctx->raw_body; + } + + /* Clear result array */ + array_clear(&msgctx->return_body_parts); + + if ( buf->used > 1 ) { + const char *data = (const char *)buf->data; + size_t size = buf->used - 1; + + i_assert( data[size] == '\0' ); + + /* Add single item to the result */ + return_part = array_append_space(&msgctx->return_body_parts); + return_part->content = data; + return_part->size = size; + } + + /* Return the array of body items */ + (void) array_append_space(&msgctx->return_body_parts); /* NULL-terminate */ + *parts_r = array_idx_modifiable(&msgctx->return_body_parts, 0); + + return SIEVE_EXEC_OK; +} + +/* + * Message part iterator + */ + +int sieve_message_part_iter_init +(struct sieve_message_part_iter *iter, + const struct sieve_runtime_env *renv) +{ + struct sieve_message_context *msgctx = renv->msgctx; + struct sieve_message_part *const *parts; + unsigned int count; + int status; + + T_BEGIN { + /* Fill the return_body_parts array */ + status = sieve_message_parts_add_missing + (renv, NULL, TRUE, TRUE); + } T_END; + + /* Check status */ + if ( status <= 0 ) + return status; + + i_zero(iter); + iter->renv = renv; + iter->index = 0; + iter->offset = 0; + + parts = array_get(&msgctx->cached_body_parts, &count); + if (count == 0) + iter->root = NULL; + else + iter->root = parts[0]; + + return SIEVE_EXEC_OK; +} + +void sieve_message_part_iter_subtree(struct sieve_message_part_iter *iter, + struct sieve_message_part_iter *subtree) +{ + const struct sieve_runtime_env *renv = iter->renv; + struct sieve_message_context *msgctx = renv->msgctx; + struct sieve_message_part *const *parts; + unsigned int count; + + *subtree = *iter; + + parts = array_get(&msgctx->cached_body_parts, &count); + if ( subtree->index >= count) + subtree->root = NULL; + else + subtree->root = parts[subtree->index]; + subtree->offset = subtree->index; +} + +void sieve_message_part_iter_children(struct sieve_message_part_iter *iter, + struct sieve_message_part_iter *child) +{ + const struct sieve_runtime_env *renv = iter->renv; + struct sieve_message_context *msgctx = renv->msgctx; + struct sieve_message_part *const *parts; + unsigned int count; + + *child = *iter; + + parts = array_get(&msgctx->cached_body_parts, &count); + if ( (child->index+1) >= count || parts[child->index]->children == NULL) + child->root = NULL; + else + child->root = parts[child->index++]; + child->offset = child->index; +} + +struct sieve_message_part *sieve_message_part_iter_current +(struct sieve_message_part_iter *iter) +{ + const struct sieve_runtime_env *renv = iter->renv; + struct sieve_message_context *msgctx = renv->msgctx; + struct sieve_message_part *const *parts; + unsigned int count; + + if ( iter->root == NULL ) + return NULL; + + parts = array_get(&msgctx->cached_body_parts, &count); + if ( iter->index >= count ) + return NULL; + do { + if ( parts[iter->index] == iter->root->next ) + return NULL; + if ( parts[iter->index] == iter->root->parent ) + return NULL; + } while ( parts[iter->index]->epilogue && ++iter->index < count ); + if ( iter->index >= count ) + return NULL; + return parts[iter->index]; +} + +struct sieve_message_part *sieve_message_part_iter_next +(struct sieve_message_part_iter *iter) +{ + const struct sieve_runtime_env *renv = iter->renv; + struct sieve_message_context *msgctx = renv->msgctx; + + if ( iter->index >= array_count(&msgctx->cached_body_parts) ) + return NULL; + iter->index++; + + return sieve_message_part_iter_current(iter); +} + +void sieve_message_part_iter_reset +(struct sieve_message_part_iter *iter) +{ + iter->index = iter->offset; +} + +/* + * MIME header list + */ + +/* Forward declarations */ + +static int sieve_mime_header_list_next_item + (struct sieve_header_list *_hdrlist, const char **name_r, + string_t **value_r); +static int sieve_mime_header_list_next_value + (struct sieve_stringlist *_strlist, string_t **value_r); +static void sieve_mime_header_list_reset + (struct sieve_stringlist *_strlist); + +/* Header list object */ + +struct sieve_mime_header_list { + struct sieve_header_list hdrlist; + + struct sieve_stringlist *field_names; + + struct sieve_message_part_iter part_iter; + + const char *header_name; + const struct sieve_message_header *headers; + unsigned int headers_index, headers_count; + + bool mime_decode:1; + bool children:1; +}; + +struct sieve_header_list *sieve_mime_header_list_create +(const struct sieve_runtime_env *renv, + struct sieve_stringlist *field_names, + struct sieve_message_part_iter *part_iter, + bool mime_decode, bool children) +{ + struct sieve_mime_header_list *hdrlist; + + hdrlist = t_new(struct sieve_mime_header_list, 1); + hdrlist->hdrlist.strlist.runenv = renv; + hdrlist->hdrlist.strlist.exec_status = SIEVE_EXEC_OK; + hdrlist->hdrlist.strlist.next_item = sieve_mime_header_list_next_value; + hdrlist->hdrlist.strlist.reset = sieve_mime_header_list_reset; + hdrlist->hdrlist.next_item = sieve_mime_header_list_next_item; + hdrlist->field_names = field_names; + hdrlist->mime_decode = mime_decode; + hdrlist->children = children; + + sieve_message_part_iter_subtree(part_iter, &hdrlist->part_iter); + + return &hdrlist->hdrlist; +} + +/* MIME list implementation */ + +static void sieve_mime_header_list_next_name +(struct sieve_mime_header_list *hdrlist) +{ + struct sieve_message_part *mpart; + + sieve_message_part_iter_reset(&hdrlist->part_iter); + mpart = sieve_message_part_iter_current(&hdrlist->part_iter); + + if ( mpart != NULL && array_is_created(&mpart->headers) ) { + hdrlist->headers = array_get + (&mpart->headers, &hdrlist->headers_count); + hdrlist->headers_index = 0; + } +} + +static int sieve_mime_header_list_next_item +(struct sieve_header_list *_hdrlist, const char **name_r, + string_t **value_r) +{ + struct sieve_mime_header_list *hdrlist = + (struct sieve_mime_header_list *) _hdrlist; + const struct sieve_runtime_env *renv = _hdrlist->strlist.runenv; + + if ( name_r != NULL ) + *name_r = NULL; + *value_r = NULL; + + for (;;) { + /* Check for end of current header list */ + if ( hdrlist->headers_count == 0 || + hdrlist->headers_index >= hdrlist->headers_count ) { + hdrlist->headers_count = 0; + hdrlist->headers_index = 0; + hdrlist->headers = NULL; + } + + /* Fetch more headers */ + while ( hdrlist->headers_count == 0 ) { + string_t *hdr_item = NULL; + int ret; + + if ( hdrlist->header_name != NULL && hdrlist->children ) { + struct sieve_message_part *mpart; + + mpart = sieve_message_part_iter_next(&hdrlist->part_iter); + if ( mpart != NULL && array_is_created(&mpart->headers) ) { + hdrlist->headers = array_get + (&mpart->headers, &hdrlist->headers_count); + hdrlist->headers_index = 0; + } + if ( hdrlist->headers_count > 0 ) { + if ( _hdrlist->strlist.trace ) { + sieve_runtime_trace(renv, 0, + "moving to next message part"); + } + break; + } + } + + /* Read next header name from source list */ + if ( (ret=sieve_stringlist_next_item + (hdrlist->field_names, &hdr_item)) <= 0 ) + return ret; + + hdrlist->header_name = str_c(hdr_item); + + if ( _hdrlist->strlist.trace ) { + sieve_runtime_trace(renv, 0, + "extracting `%s' headers from message part", + str_sanitize(str_c(hdr_item), 80)); + } + + sieve_mime_header_list_next_name(hdrlist); + } + + for ( ; hdrlist->headers_index < hdrlist->headers_count; + hdrlist->headers_index++ ) { + const struct sieve_message_header *header = + &hdrlist->headers[hdrlist->headers_index]; + + if ( strcasecmp(header->name, hdrlist->header_name) == 0 ) { + if ( name_r != NULL ) + *name_r = hdrlist->header_name; + if ( hdrlist->mime_decode ) { + *value_r = t_str_new_const + ((const char *)header->utf8_value, header->utf8_value_len); + } else { + *value_r = t_str_new_const + ((const char *)header->value, header->value_len); + } + hdrlist->headers_index++; + return 1; + } + } + } + + i_unreached(); + return -1; +} + +static int sieve_mime_header_list_next_value +(struct sieve_stringlist *_strlist, string_t **value_r) +{ + struct sieve_header_list *hdrlist = + (struct sieve_header_list *) _strlist; + + return sieve_mime_header_list_next_item + (hdrlist, NULL, value_r); +} + +static void sieve_mime_header_list_reset +(struct sieve_stringlist *strlist) +{ + struct sieve_mime_header_list *hdrlist = + (struct sieve_mime_header_list *) strlist; + + sieve_stringlist_reset(hdrlist->field_names); + hdrlist->header_name = NULL; +} diff --git a/pigeonhole/src/lib-sieve/sieve-message.h b/pigeonhole/src/lib-sieve/sieve-message.h new file mode 100644 index 0000000..4cb77cc --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-message.h @@ -0,0 +1,280 @@ +#ifndef SIEVE_MESSAGE_H +#define SIEVE_MESSAGE_H + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-objects.h" + +/* + * Message transmission + */ + +const char *sieve_message_get_new_id(const struct sieve_instance *svinst); + +/* + * Message context + */ + +struct sieve_message_context; + +struct sieve_message_context *sieve_message_context_create + (struct sieve_instance *svinst, struct mail_user *mail_user, + const struct sieve_message_data *msgdata); +void sieve_message_context_ref(struct sieve_message_context *msgctx); +void sieve_message_context_unref(struct sieve_message_context **msgctx); + +void sieve_message_context_reset(struct sieve_message_context *msgctx); + +pool_t sieve_message_context_pool + (struct sieve_message_context *msgctx) ATTR_PURE; +void sieve_message_context_time(struct sieve_message_context *msgctx, + struct timeval *time); + +/* Extension support */ + +void sieve_message_context_extension_set + (struct sieve_message_context *msgctx, const struct sieve_extension *ext, + void *context); +const void *sieve_message_context_extension_get + (struct sieve_message_context *msgctx, const struct sieve_extension *ext); + +/* Envelope */ + +const struct smtp_address *sieve_message_get_final_recipient + (struct sieve_message_context *msgctx); +const struct smtp_address *sieve_message_get_orig_recipient + (struct sieve_message_context *msgctx); + +const struct smtp_address *sieve_message_get_sender + (struct sieve_message_context *msgctx); + +/* Mail */ + +struct mail *sieve_message_get_mail + (struct sieve_message_context *msgctx); + +int sieve_message_substitute + (struct sieve_message_context *msgctx, struct istream *input); +struct edit_mail *sieve_message_edit + (struct sieve_message_context *msgctx); +void sieve_message_snapshot + (struct sieve_message_context *msgctx); + +/* + * Header stringlist + */ + +struct sieve_header_list { + struct sieve_stringlist strlist; + + int (*next_item) + (struct sieve_header_list *_hdrlist, const char **name_r, + string_t **value_r) ATTR_NULL(2); +}; + +static inline int sieve_header_list_next_item +(struct sieve_header_list *hdrlist, const char **name_r, + string_t **value_r) ATTR_NULL(2) +{ + return hdrlist->next_item(hdrlist, name_r, value_r); +} + +static inline void sieve_header_list_reset +(struct sieve_header_list *hdrlist) +{ + sieve_stringlist_reset(&hdrlist->strlist); +} + +static inline int sieve_header_list_get_length +(struct sieve_header_list *hdrlist) +{ + return sieve_stringlist_get_length(&hdrlist->strlist); +} + +static inline void sieve_header_list_set_trace +(struct sieve_header_list *hdrlist, bool trace) +{ + sieve_stringlist_set_trace(&hdrlist->strlist, trace); +} + +struct sieve_header_list *sieve_message_header_list_create + (const struct sieve_runtime_env *renv, + struct sieve_stringlist *field_names, + bool mime_decode); + +/* + * Message override + */ + +/* Header override object */ + +struct sieve_message_override_def { + struct sieve_object_def obj_def; + + unsigned int sequence; + + /* Context coding */ + + bool (*dump_context) + (const struct sieve_message_override *svmo, + const struct sieve_dumptime_env *denv, sieve_size_t *address); + int (*read_context) + (const struct sieve_message_override *svmo, + const struct sieve_runtime_env *renv, sieve_size_t *address, + void **se_context); + + /* Override */ + + int (*header_override) + (const struct sieve_message_override *svmo, + const struct sieve_runtime_env *renv, + bool mime_decode, struct sieve_stringlist **headers); +}; + +struct sieve_message_override { + struct sieve_object object; + + const struct sieve_message_override_def *def; + + void *context; +}; + +ARRAY_DEFINE_TYPE(sieve_message_override, + struct sieve_message_override); + +/* + * Message override operand + */ + +#define SIEVE_EXT_DEFINE_MESSAGE_OVERRIDE(SVMO) SIEVE_EXT_DEFINE_OBJECT(SVMO) +#define SIEVE_EXT_DEFINE_MESSAGE_OVERRIDES(SVMOS) SIEVE_EXT_DEFINE_OBJECTS(SMOS) + +#define SIEVE_OPT_MESSAGE_OVERRIDE (-2) + +extern const struct sieve_operand_class + sieve_message_override_operand_class; + +static inline void sieve_opr_message_override_emit +(struct sieve_binary_block *sblock, const struct sieve_extension *ext, + const struct sieve_message_override_def *seff) +{ + sieve_opr_object_emit(sblock, ext, &seff->obj_def); +} + +bool sieve_opr_message_override_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +int sieve_opr_message_override_read + (const struct sieve_runtime_env *renv, sieve_size_t *address, + struct sieve_message_override *svmo); + +/* + * Optional operands + */ + +int sieve_message_opr_optional_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address, + signed int *opt_code); + +int sieve_message_opr_optional_read + (const struct sieve_runtime_env *renv, sieve_size_t *address, + signed int *opt_code, int *exec_status, + struct sieve_address_part *addrp, struct sieve_match_type *mcht, + struct sieve_comparator *cmp, + ARRAY_TYPE(sieve_message_override) *svmos); + +/* + * Message header + */ + +int sieve_message_get_header_fields + (const struct sieve_runtime_env *renv, + struct sieve_stringlist *field_names, + ARRAY_TYPE(sieve_message_override) *svmos, + bool mime_decode, struct sieve_stringlist **fields_r); + +/* + * Message part + */ + +struct sieve_message_part; + +struct sieve_message_part_data { + const char *content_type; + const char *content_disposition; + + const char *content; + unsigned long size; +}; + +struct sieve_message_part *sieve_message_part_parent + (struct sieve_message_part *mpart) ATTR_PURE; +struct sieve_message_part *sieve_message_part_next + (struct sieve_message_part *mpart) ATTR_PURE; +struct sieve_message_part *sieve_message_part_children + (struct sieve_message_part *mpart) ATTR_PURE; + +const char *sieve_message_part_content_type + (struct sieve_message_part *mpart) ATTR_PURE; +const char *sieve_message_part_content_disposition + (struct sieve_message_part *mpart) ATTR_PURE; + +int sieve_message_part_get_first_header + (struct sieve_message_part *mpart, const char *field, + const char **value_r); + +void sieve_message_part_get_data + (struct sieve_message_part *mpart, + struct sieve_message_part_data *data, bool text); + +/* + * Message body + */ + +int sieve_message_body_get_content + (const struct sieve_runtime_env *renv, + const char * const *content_types, + struct sieve_message_part_data **parts_r); +int sieve_message_body_get_text + (const struct sieve_runtime_env *renv, + struct sieve_message_part_data **parts_r); +int sieve_message_body_get_raw + (const struct sieve_runtime_env *renv, + struct sieve_message_part_data **parts_r); + +/* + * Message part iterator + */ + +struct sieve_message_part_iter { + const struct sieve_runtime_env *renv; + struct sieve_message_part *root; + unsigned int index, offset; +}; + +int sieve_message_part_iter_init +(struct sieve_message_part_iter *iter, + const struct sieve_runtime_env *renv); +void sieve_message_part_iter_subtree(struct sieve_message_part_iter *iter, + struct sieve_message_part_iter *subtree); +void sieve_message_part_iter_children(struct sieve_message_part_iter *iter, + struct sieve_message_part_iter *child); + +struct sieve_message_part *sieve_message_part_iter_current +(struct sieve_message_part_iter *iter); +struct sieve_message_part *sieve_message_part_iter_next +(struct sieve_message_part_iter *iter); + +void sieve_message_part_iter_reset +(struct sieve_message_part_iter *iter); + +/* + * MIME header list + */ + +struct sieve_header_list *sieve_mime_header_list_create +(const struct sieve_runtime_env *renv, + struct sieve_stringlist *field_names, + struct sieve_message_part_iter *part_iter, + bool mime_decode, bool children); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-objects.c b/pigeonhole/src/lib-sieve/sieve-objects.c new file mode 100644 index 0000000..66fc969 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-objects.c @@ -0,0 +1,111 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-dump.h" +#include "sieve-interpreter.h" + +#include "sieve-objects.h" + +/* + * Object coding + */ + +void sieve_opr_object_emit +(struct sieve_binary_block *sblock, const struct sieve_extension *ext, + const struct sieve_object_def *obj_def) +{ + struct sieve_extension_objects *objs = + (struct sieve_extension_objects *) obj_def->operand->interface; + + (void) sieve_operand_emit(sblock, ext, obj_def->operand); + + if ( objs->count > 1 ) { + (void) sieve_binary_emit_byte(sblock, obj_def->code); + } +} + +bool sieve_opr_object_read_data +(struct sieve_binary_block *sblock, const struct sieve_operand *operand, + const struct sieve_operand_class *opclass, sieve_size_t *address, + struct sieve_object *obj) +{ + const struct sieve_extension_objects *objs; + unsigned int obj_code; + + if ( operand == NULL || operand->def->class != opclass ) + return FALSE; + + objs = (struct sieve_extension_objects *) operand->def->interface; + if ( objs == NULL ) + return FALSE; + + if ( objs->count > 1 ) { + if ( !sieve_binary_read_byte(sblock, address, &obj_code) ) + return FALSE; + + if ( obj_code < objs->count ) { + const struct sieve_object_def *const *objects = + (const struct sieve_object_def *const *) objs->objects; + + obj->def = objects[obj_code]; + obj->ext = operand->ext; + return TRUE; + } + } + + obj->def = (const struct sieve_object_def *) objs->objects; + obj->ext = operand->ext; + return TRUE; +} + +bool sieve_opr_object_read +(const struct sieve_runtime_env *renv, + const struct sieve_operand_class *opclass, sieve_size_t *address, + struct sieve_object *obj) +{ + struct sieve_operand operand; + + if ( !sieve_operand_read(renv->sblock, address, NULL, &operand) ) { + return FALSE; + } + + return sieve_opr_object_read_data + (renv->sblock, &operand, opclass, address, obj); +} + +bool sieve_opr_object_dump +(const struct sieve_dumptime_env *denv, + const struct sieve_operand_class *opclass, sieve_size_t *address, + struct sieve_object *obj) +{ + struct sieve_operand operand; + struct sieve_object obj_i; + const char *class; + + if ( obj == NULL ) + obj = &obj_i; + + sieve_code_mark(denv); + + if ( !sieve_operand_read(denv->sblock, address, NULL, &operand) ) { + return FALSE; + } + + if ( !sieve_opr_object_read_data + (denv->sblock, &operand, opclass, address, obj) ) + return FALSE; + + if ( operand.def->class == NULL ) + class = "OBJECT"; + else + class = operand.def->class->name; + + sieve_code_dumpf(denv, "%s: %s", class, obj->def->identifier); + + return TRUE; +} + diff --git a/pigeonhole/src/lib-sieve/sieve-objects.h b/pigeonhole/src/lib-sieve/sieve-objects.h new file mode 100644 index 0000000..e3f300f --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-objects.h @@ -0,0 +1,67 @@ +#ifndef SIEVE_OBJECTS_H +#define SIEVE_OBJECTS_H + +/* + * Object definition + */ + +struct sieve_object_def { + const char *identifier; + const struct sieve_operand_def *operand; + unsigned int code; +}; + +#define SIEVE_OBJECT(_identifier, _operand, _code) \ + .obj_def = { \ + .identifier = (_identifier), \ + .operand = (_operand), \ + .code = (_code) \ + } + +/* + * Object instance + */ + +struct sieve_object { + const struct sieve_object_def *def; + const struct sieve_extension *ext; +}; + +#define SIEVE_OBJECT_DEFAULT(_obj) \ + { &((_obj).obj_def), NULL } + +#define SIEVE_OBJECT_EXTENSION(_obj) \ + (_obj->object.ext) + +#define SIEVE_OBJECT_SET_DEF(_obj, def_value) \ + STMT_START { \ + (_obj)->def = def_value; \ + (_obj)->object.def = &(_obj)->def->obj_def; \ + } STMT_END + + +/* + * Object coding + */ + +void sieve_opr_object_emit + (struct sieve_binary_block *sblock, const struct sieve_extension *ext, + const struct sieve_object_def *obj_def); + +bool sieve_opr_object_read_data + (struct sieve_binary_block *sblock, const struct sieve_operand *operand, + const struct sieve_operand_class *opclass, sieve_size_t *address, + struct sieve_object *obj); + +bool sieve_opr_object_read + (const struct sieve_runtime_env *renv, + const struct sieve_operand_class *opclass, sieve_size_t *address, + struct sieve_object *obj); + +bool sieve_opr_object_dump + (const struct sieve_dumptime_env *denv, + const struct sieve_operand_class *opclass, sieve_size_t *address, + struct sieve_object *obj); + + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-parser.c b/pigeonhole/src/lib-sieve/sieve-parser.c new file mode 100644 index 0000000..ee54994 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-parser.c @@ -0,0 +1,670 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "istream.h" +#include "failures.h" + +#include "sieve-common.h" +#include "sieve-limits.h" +#include "sieve-script.h" +#include "sieve-lexer.h" +#include "sieve-parser.h" +#include "sieve-error.h" +#include "sieve-ast.h" + +/* + * Forward declarations + */ + +static int +sieve_parser_recover(struct sieve_parser *parser, + enum sieve_token_type end_token); + +/* + * Parser object + */ + +struct sieve_parser { + pool_t pool; + + bool valid; + + struct sieve_script *script; + + struct sieve_error_handler *ehandler; + + const struct sieve_lexer *lexer; + struct sieve_ast *ast; +}; + +struct sieve_parser * +sieve_parser_create(struct sieve_script *script, + struct sieve_error_handler *ehandler, + enum sieve_error *error_r) +{ + struct sieve_parser *parser; + const struct sieve_lexer *lexer; + + lexer = sieve_lexer_create(script, ehandler, error_r); + if (lexer != NULL) { + pool_t pool = pool_alloconly_create("sieve_parser", 4096); + + parser = p_new(pool, struct sieve_parser, 1); + parser->pool = pool; + parser->valid = TRUE; + + parser->ehandler = ehandler; + sieve_error_handler_ref(ehandler); + + parser->script = script; + sieve_script_ref(script); + + parser->lexer = lexer; + parser->ast = NULL; + + return parser; + } + + return NULL; +} + +void sieve_parser_free(struct sieve_parser **parser) +{ + if ((*parser)->ast != NULL) + sieve_ast_unref(&(*parser)->ast); + + sieve_lexer_free(&(*parser)->lexer); + sieve_script_unref(&(*parser)->script); + + sieve_error_handler_unref(&(*parser)->ehandler); + + pool_unref(&(*parser)->pool); + + *parser = NULL; +} + +/* + * Internal error handling + */ + +inline static void ATTR_FORMAT(4, 5) +sieve_parser_error(struct sieve_parser *parser, + const char *csrc_filename, unsigned int csrc_linenum, + const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_ERROR, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + }; + va_list args; + + va_start(args, fmt); + + /* Don't report a parse error if the lexer complained already */ + if (sieve_lexer_token_type(parser->lexer) != STT_ERROR) { + T_BEGIN { + params.location = sieve_error_script_location( + parser->script, + sieve_lexer_token_line(parser->lexer)); + sieve_logv(parser->ehandler, ¶ms, fmt, args); + } T_END; + } + + parser->valid = FALSE; + + va_end(args); +} +#define sieve_parser_error(parser, ...) \ + sieve_parser_error(parser, __FILE__, __LINE__, __VA_ARGS__) + +/* + * Sieve grammar parsing + */ + +/* sieve_parse_arguments(): + + Parses both command arguments and sub-tests: + arguments = *argument [test / test-list] + argument = string-list / number / tag + string = quoted-string / multi-line [[implicitly handled in lexer]] + string-list = "[" string *("," string) "]" / string ;; if + there is only a single string, the brackets are optional + test-list = "(" test *("," test) ")" + test = identifier arguments + */ +static int +sieve_parse_arguments(struct sieve_parser *parser, struct sieve_ast_node *node, + unsigned int depth) +{ + const struct sieve_lexer *lexer = parser->lexer; + struct sieve_ast_node *test = NULL; + bool test_present = TRUE; + bool arg_present = TRUE; + int result = 1; /* Indicates whether the parser is in a defined, not + necessarily error-free state */ + + /* Parse arguments */ + while (arg_present && result > 0) { + struct sieve_ast_argument *arg; + + if (!parser->valid && + !sieve_errors_more_allowed(parser->ehandler)) { + result = 0; + break; + } + + switch (sieve_lexer_token_type(lexer)) { + /* String list */ + case STT_LSQUARE: + /* Create stinglist object */ + arg = sieve_ast_argument_stringlist_create( + node, sieve_lexer_token_line(parser->lexer)); + if (arg == NULL) break; + sieve_lexer_skip_token(lexer); + + if (sieve_lexer_token_type(lexer) == STT_STRING) { + bool add_failed = FALSE; + + /* Add the string to the list */ + if (!sieve_ast_stringlist_add( + arg, sieve_lexer_token_str(lexer), + sieve_lexer_token_line(parser->lexer))) + add_failed = TRUE; + sieve_lexer_skip_token(lexer); + + while (!add_failed && + sieve_lexer_token_type(lexer) == STT_COMMA) { + sieve_lexer_skip_token(lexer); + + /* Check parser status */ + if (!parser->valid && + !sieve_errors_more_allowed(parser->ehandler)) { + result = sieve_parser_recover(parser, STT_RSQUARE); + break; + } + + if (sieve_lexer_token_type(lexer) == STT_STRING) { + /* Add the string to the list */ + if (!sieve_ast_stringlist_add( + arg, sieve_lexer_token_str(lexer), + sieve_lexer_token_line(parser->lexer))) + add_failed = TRUE; + + sieve_lexer_skip_token(lexer); + } else { + sieve_parser_error(parser, + "expecting string after ',' in string list, " + "but found %s", + sieve_lexer_token_description(lexer)); + result = sieve_parser_recover(parser, STT_RSQUARE); + break; + } + } + + if (add_failed) { + sieve_parser_error(parser, + "failed to accept more items in string list"); + return -1; + } + } else { + sieve_parser_error(parser, + "expecting string after '[' in string list, " + "but found %s", + sieve_lexer_token_description(lexer)); + result = sieve_parser_recover(parser, STT_RSQUARE); + } + + /* Finish the string list */ + if (sieve_lexer_token_type(lexer) == STT_RSQUARE) { + sieve_lexer_skip_token(lexer); + } else { + sieve_parser_error(parser, + "expecting ',' or end of string list ']', " + "but found %s", + sieve_lexer_token_description(lexer)); + + if ((result = sieve_parser_recover(parser, STT_RSQUARE)) > 0) + sieve_lexer_skip_token(lexer); + } + break; + /* Single string */ + case STT_STRING: + arg = sieve_ast_argument_string_create( + node, sieve_lexer_token_str(lexer), + sieve_lexer_token_line(parser->lexer)); + sieve_lexer_skip_token(lexer); + break; + /* Number */ + case STT_NUMBER: + arg = sieve_ast_argument_number_create( + node, sieve_lexer_token_int(lexer), + sieve_lexer_token_line(parser->lexer)); + sieve_lexer_skip_token(lexer); + break; + /* Tag */ + case STT_TAG: + arg = sieve_ast_argument_tag_create( + node, sieve_lexer_token_ident(lexer), + sieve_lexer_token_line(parser->lexer)); + sieve_lexer_skip_token(lexer); + break; + /* End of argument list, continue with tests */ + default: + arg_present = FALSE; + break; + } + + if (arg_present && arg == NULL) { + sieve_parser_error(parser, + "failed to accept more arguments for command '%s'", + node->identifier); + return -1; + } + + if (sieve_ast_argument_count(node) > SIEVE_MAX_COMMAND_ARGUMENTS) { + sieve_parser_error(parser, + "too many arguments for command '%s'", + node->identifier); + return 0; + } + } + + if (result <= 0) + return result; /* Defer recovery to caller */ + + /* --> [ test / test-list ] + test-list = "(" test *("," test) ")" + test = identifier arguments + */ + switch (sieve_lexer_token_type(lexer)) { + /* Single test */ + case STT_IDENTIFIER: + if ((depth + 1) > SIEVE_MAX_TEST_NESTING) { + sieve_parser_error(parser, + "cannot nest tests deeper than %u levels", + SIEVE_MAX_TEST_NESTING); + return 0; + } + + test = sieve_ast_test_create( + node, sieve_lexer_token_ident(lexer), + sieve_lexer_token_line(parser->lexer)); + sieve_lexer_skip_token(lexer); + + /* Theoretically, test can be NULL */ + if (test == NULL) + break; + + /* Parse test arguments, which may include more tests (recurse) */ + if (sieve_parse_arguments(parser, test, depth + 1) <= 0) { + return 0; /* Defer recovery to caller */ + } + + break; + + /* Test list */ + case STT_LBRACKET: + sieve_lexer_skip_token(lexer); + + if (depth+1 > SIEVE_MAX_TEST_NESTING) { + sieve_parser_error(parser, + "cannot nest tests deeper than %u levels", + SIEVE_MAX_TEST_NESTING); + result = sieve_parser_recover(parser, STT_RBRACKET); + + if (result > 0) + sieve_lexer_skip_token(lexer); + return result; + } + + node->test_list = TRUE; + + /* Test starts with identifier */ + if (sieve_lexer_token_type(lexer) == STT_IDENTIFIER) { + test = sieve_ast_test_create( + node, sieve_lexer_token_ident(lexer), + sieve_lexer_token_line(parser->lexer)); + sieve_lexer_skip_token(lexer); + + if (test == NULL) + break; + + /* Parse test arguments, which may include more tests (recurse) */ + if ((result = sieve_parse_arguments(parser, test, depth+1)) > 0) { + + /* More tests ? */ + while (sieve_lexer_token_type(lexer) == STT_COMMA) { + sieve_lexer_skip_token(lexer); + + /* Check parser status */ + if (!parser->valid && + !sieve_errors_more_allowed(parser->ehandler)) { + result = sieve_parser_recover(parser, STT_RBRACKET); + break; + } + + /* Test starts with identifier */ + if (sieve_lexer_token_type(lexer) == STT_IDENTIFIER) { + test = sieve_ast_test_create( + node, sieve_lexer_token_ident(lexer), + sieve_lexer_token_line(parser->lexer)); + sieve_lexer_skip_token(lexer); + + if (test == NULL) + break; + + /* Parse test arguments, which may include more tests (recurse) */ + if ((result = sieve_parse_arguments(parser, test, depth+1)) <= 0) { + if (result < 0) + return result; + result = sieve_parser_recover(parser, STT_RBRACKET); + break; + } + } else { + sieve_parser_error(parser, + "expecting test identifier after ',' in test list, " + "but found %s", + sieve_lexer_token_description(lexer)); + result = sieve_parser_recover(parser, STT_RBRACKET); + break; + } + } + if (test == NULL) + break; + } else { + if (result < 0) + return result; + + result = sieve_parser_recover(parser, STT_RBRACKET); + } + } else { + sieve_parser_error(parser, + "expecting test identifier after '(' in test list, " + "but found %s", + sieve_lexer_token_description(lexer)); + + result = sieve_parser_recover(parser, STT_RBRACKET); + } + + /* The next token should be a ')', indicating the end of the + test list + --> previous sieve_parser_recover calls try to restore this + situation after parse errors. + */ + if (sieve_lexer_token_type(lexer) == STT_RBRACKET) { + sieve_lexer_skip_token(lexer); + } else { + sieve_parser_error(parser, + "expecting ',' or end of test list ')', " + "but found %s", + sieve_lexer_token_description(lexer)); + + /* Recover function tries to make next token equal to + ')'. If it succeeds we need to skip it. + */ + if ((result = sieve_parser_recover(parser, STT_RBRACKET)) > 0) + sieve_lexer_skip_token(lexer); + } + break; + + default: + /* Not an error: test / test-list is optional + --> any errors are detected by the caller + */ + test_present = FALSE; + break; + } + + if (test_present && test == NULL) { + sieve_parser_error(parser, + "failed to accept more tests for command '%s'", + node->identifier); + return -1; + } + + return result; +} + +/* commands = *command + command = identifier arguments ( ";" / block ) + block = "{" commands "}" + */ +static int +sieve_parse_commands(struct sieve_parser *parser, struct sieve_ast_node *block, + unsigned int depth) +{ + const struct sieve_lexer *lexer = parser->lexer; + int result = 1; + + while (result > 0 && + sieve_lexer_token_type(lexer) == STT_IDENTIFIER) { + struct sieve_ast_node *command; + + /* Check parser status */ + if (!parser->valid && + !sieve_errors_more_allowed(parser->ehandler)) { + result = sieve_parser_recover(parser, STT_SEMICOLON); + break; + } + + /* Create command node */ + command = sieve_ast_command_create( + block, sieve_lexer_token_ident(lexer), + sieve_lexer_token_line(parser->lexer)); + sieve_lexer_skip_token(lexer); + + if (command == NULL) { + sieve_parser_error(parser, + "failed to accept more commands inside the block of command '%s'", + block->identifier); + return -1; + } + + result = sieve_parse_arguments(parser, command, 1); + + /* Check whether the command is properly terminated + (i.e. with ; or a new block) + */ + if (result > 0 && + sieve_lexer_token_type(lexer) != STT_SEMICOLON && + sieve_lexer_token_type(lexer) != STT_LCURLY) { + + sieve_parser_error(parser, + "expected end of command ';' or the beginning of a compound block '{', " + "but found %s", + sieve_lexer_token_description(lexer)); + result = 0; + } + + /* Try to recover from parse errors to reacquire a defined state + */ + if (result == 0) + result = sieve_parser_recover(parser, STT_SEMICOLON); + + /* Don't bother to continue if we are not in a defined state */ + if (result <= 0) + return result; + + switch (sieve_lexer_token_type(lexer)) { + /* End of the command */ + case STT_SEMICOLON: + sieve_lexer_skip_token(lexer); + break; + /* Command has a block {...} */ + case STT_LCURLY: + sieve_lexer_skip_token(lexer); + + /* Check current depth first */ + if ((depth + 1) > SIEVE_MAX_BLOCK_NESTING) { + sieve_parser_error(parser, + "cannot nest command blocks deeper than %u levels", + SIEVE_MAX_BLOCK_NESTING); + result = sieve_parser_recover(parser, STT_RCURLY); + + if (result > 0) + sieve_lexer_skip_token(lexer); + break; + } + + command->block = TRUE; + + if ((result = sieve_parse_commands(parser, command, depth + 1)) > 0) { + if (sieve_lexer_token_type(lexer) != STT_RCURLY) { + sieve_parser_error(parser, + "expected end of compound block '}', " + "but found %s", + sieve_lexer_token_description(lexer)); + result = sieve_parser_recover(parser, STT_RCURLY); + } else { + sieve_lexer_skip_token(lexer); + } + } else { + if (result < 0) + return result; + + if ((result = sieve_parser_recover(parser, STT_RCURLY)) > 0) + sieve_lexer_skip_token(lexer); + } + + break; + + default: + /* Recovered previously, so this cannot happen */ + i_unreached(); + } + } + + return result; +} + +bool sieve_parser_run(struct sieve_parser *parser, struct sieve_ast **ast) +{ + if (parser->ast != NULL) + sieve_ast_unref(&parser->ast); + + /* Create AST object if none is provided */ + if (*ast == NULL) + *ast = sieve_ast_create(parser->script); + else + sieve_ast_ref(*ast); + + parser->ast = *ast; + + /* Scan first token */ + sieve_lexer_skip_token(parser->lexer); + + /* Parse */ + if (sieve_parse_commands(parser, sieve_ast_root(parser->ast), 1) > 0 && + parser->valid) { + /* Parsed right to EOF ? */ + if (sieve_lexer_token_type(parser->lexer) != STT_EOF) { + sieve_parser_error(parser, + "unexpected %s found at (the presumed) end of file", + sieve_lexer_token_description(parser->lexer)); + parser->valid = FALSE; + } + } else { + parser->valid = FALSE; + } + + /* Clean up AST if parse failed */ + if (!parser->valid) { + parser->ast = NULL; + sieve_ast_unref(ast); + } + + return parser->valid; +} + +/* Error recovery: + To continue parsing after an error it is important to find the next + parsible item in the stream. The recover function skips over the remaining + garbage after an error. It tries to find the end of the failed syntax + structure and takes nesting of structures into account. + */ + +/* Assign useful names to priorities for readability */ +enum sieve_grammatical_prio { + SGP_BLOCK = 3, + SGP_COMMAND = 2, + SGP_TEST_LIST = 1, + SGP_STRING_LIST = 0, + + SGP_OTHER = -1 +}; + +static inline enum sieve_grammatical_prio +__get_token_priority(enum sieve_token_type token) +{ + switch (token) { + case STT_LCURLY: + case STT_RCURLY: + return SGP_BLOCK; + case STT_SEMICOLON: + return SGP_COMMAND; + case STT_LBRACKET: + case STT_RBRACKET: + return SGP_TEST_LIST; + case STT_LSQUARE: + case STT_RSQUARE: + return SGP_STRING_LIST; + default: + break; + } + + return SGP_OTHER; +} + +static int +sieve_parser_recover(struct sieve_parser *parser, + enum sieve_token_type end_token) +{ + /* The tokens that begin/end a specific block/command/list in order + of ascending grammatical priority. + */ + static const enum sieve_token_type begin_tokens[4] = { + STT_LSQUARE, STT_LBRACKET, STT_NONE, STT_LCURLY }; + static const enum sieve_token_type end_tokens[4] = { + STT_RSQUARE, STT_RBRACKET, STT_SEMICOLON, STT_RCURLY}; + const struct sieve_lexer *lexer = parser->lexer; + int nesting = 1; + enum sieve_grammatical_prio end_priority = + __get_token_priority(end_token); + + i_assert(end_priority != SGP_OTHER); + + while (sieve_lexer_token_type(lexer) != STT_EOF && + __get_token_priority(sieve_lexer_token_type(lexer)) + <= end_priority) { + if (sieve_lexer_token_type(lexer) == + begin_tokens[end_priority]) { + nesting++; + sieve_lexer_skip_token(lexer); + continue; + } + if (sieve_lexer_token_type(lexer) == + end_tokens[end_priority]) { + nesting--; + + if (nesting == 0) { + /* Next character is the end */ + return 1; + } + } + sieve_lexer_skip_token(lexer); + } + + /* Special case: COMMAND */ + if (end_token == STT_SEMICOLON && + sieve_lexer_token_type(lexer) == STT_LCURLY) { + return 1; + } + + /* End not found before eof or end of surrounding grammatical structure + */ + return 0; +} diff --git a/pigeonhole/src/lib-sieve/sieve-parser.h b/pigeonhole/src/lib-sieve/sieve-parser.h new file mode 100644 index 0000000..dfcb63c --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-parser.h @@ -0,0 +1,17 @@ +#ifndef SIEVE_PARSER_H +#define SIEVE_PARSER_H + +#include "lib.h" + +#include "sieve-common.h" + +struct sieve_parser; + +struct sieve_parser * +sieve_parser_create(struct sieve_script *script, + struct sieve_error_handler *ehandler, + enum sieve_error *error_r); +void sieve_parser_free(struct sieve_parser **parser); +bool sieve_parser_run(struct sieve_parser *parser, struct sieve_ast **ast); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-plugins.c b/pigeonhole/src/lib-sieve/sieve-plugins.c new file mode 100644 index 0000000..c0f32b1 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-plugins.c @@ -0,0 +1,181 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "module-dir.h" + +#include "sieve-settings.h" +#include "sieve-extensions.h" + +#include "sieve-common.h" +#include "sieve-plugins.h" + +/* + * Types + */ + +typedef void (*sieve_plugin_load_func_t) + (struct sieve_instance *svinst, void **context); +typedef void (*sieve_plugin_unload_func_t) + (struct sieve_instance *svinst, void *context); + +struct sieve_plugin { + struct module *module; + + void *context; + + struct sieve_plugin *next; +}; + +/* + * Plugin support + */ + +static struct module *sieve_modules = NULL; +static int sieve_modules_refcount = 0; + +static struct module *sieve_plugin_module_find(const char *name) +{ + struct module *module; + + module = sieve_modules; + while ( module != NULL ) { + const char *mod_name; + + /* Strip module names */ + mod_name = module_get_plugin_name(module); + + if ( strcmp(mod_name, name) == 0 ) + return module; + + module = module->next; + } + + return NULL; +} + +void sieve_plugins_load +(struct sieve_instance *svinst, const char *path, const char *plugins) +{ + struct module *module; + struct module_dir_load_settings mod_set; + const char **module_names; + unsigned int i; + + /* Determine what to load */ + + if ( path == NULL && plugins == NULL ) { + path = sieve_setting_get(svinst, "sieve_plugin_dir"); + plugins = sieve_setting_get(svinst, "sieve_plugins"); + } + + if ( plugins == NULL || *plugins == '\0' ) + return; + + if ( path == NULL || *path == '\0' ) + path = MODULEDIR"/sieve"; + + i_zero(&mod_set); + mod_set.abi_version = PIGEONHOLE_ABI_VERSION; + mod_set.require_init_funcs = TRUE; + mod_set.debug = FALSE; + + /* Load missing plugin modules */ + + sieve_modules = module_dir_load_missing + (sieve_modules, path, plugins, &mod_set); + + /* Call plugin load functions for this Sieve instance */ + + if ( svinst->plugins == NULL ) { + sieve_modules_refcount++; + } + + module_names = t_strsplit_spaces(plugins, ", "); + + for (i = 0; module_names[i] != NULL; i++) { + /* Allow giving the module names also in non-base form. */ + module_names[i] = module_file_get_name(module_names[i]); + } + + for (i = 0; module_names[i] != NULL; i++) { + struct sieve_plugin *plugin; + const char *name = module_names[i]; + sieve_plugin_load_func_t load_func; + + /* Find the module */ + module = sieve_plugin_module_find(name); + i_assert(module != NULL); + + /* Check whether the plugin is already loaded in this instance */ + plugin = svinst->plugins; + while ( plugin != NULL ) { + if ( plugin->module == module ) + break; + plugin = plugin->next; + } + + /* Skip it if it is loaded already */ + if ( plugin != NULL ) + continue; + + /* Create plugin list item */ + plugin = p_new(svinst->pool, struct sieve_plugin, 1); + plugin->module = module; + + /* Call load function */ + load_func = (sieve_plugin_load_func_t) module_get_symbol + (module, t_strdup_printf("%s_load", module->name)); + if ( load_func != NULL ) { + load_func(svinst, &plugin->context); + } + + /* Add plugin to the instance */ + if ( svinst->plugins == NULL ) + svinst->plugins = plugin; + else { + struct sieve_plugin *plugin_last; + + plugin_last = svinst->plugins; + while ( plugin_last->next != NULL ) + plugin_last = plugin_last->next; + + plugin_last->next = plugin; + } + } +} + +void sieve_plugins_unload(struct sieve_instance *svinst) +{ + struct sieve_plugin *plugin; + + if ( svinst->plugins == NULL ) + return; + + /* Call plugin unload functions for this instance */ + + plugin = svinst->plugins; + while ( plugin != NULL ) { + struct module *module = plugin->module; + sieve_plugin_unload_func_t unload_func; + + unload_func = (sieve_plugin_unload_func_t)module_get_symbol + (module, t_strdup_printf("%s_unload", module->name)); + if ( unload_func != NULL ) { + unload_func(svinst, plugin->context); + } + + plugin = plugin->next; + } + + /* Physically unload modules */ + + i_assert(sieve_modules_refcount > 0); + + if ( --sieve_modules_refcount != 0 ) + return; + + module_dir_unload(&sieve_modules); +} + diff --git a/pigeonhole/src/lib-sieve/sieve-plugins.h b/pigeonhole/src/lib-sieve/sieve-plugins.h new file mode 100644 index 0000000..996af41 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-plugins.h @@ -0,0 +1,9 @@ +#ifndef SIEVE_PLUGINS_H +#define SIEVE_PLUGINS_H + +#include "sieve-common.h" + +void sieve_plugins_load(struct sieve_instance *svinst, const char *path, const char *plugins); +void sieve_plugins_unload(struct sieve_instance *svinst); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-result.c b/pigeonhole/src/lib-sieve/sieve-result.c new file mode 100644 index 0000000..89d249e --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-result.c @@ -0,0 +1,2445 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "mempool.h" +#include "ostream.h" +#include "hash.h" +#include "str.h" +#include "llist.h" +#include "strfuncs.h" +#include "str-sanitize.h" +#include "var-expand.h" +#include "message-address.h" +#include "mail-storage.h" + +#include "sieve-common.h" +#include "sieve-limits.h" +#include "sieve-script.h" +#include "sieve-error.h" +#include "sieve-interpreter.h" +#include "sieve-actions.h" +#include "sieve-message.h" + +#include "sieve-result.h" + +#include <stdio.h> + +struct event_category event_category_sieve_action = { + .parent = &event_category_sieve, + .name = "sieve-action", +}; + +/* + * Types + */ + +enum sieve_action_execution_state { + SIEVE_ACTION_EXECUTION_STATE_INIT = 0, + SIEVE_ACTION_EXECUTION_STATE_STARTED, + SIEVE_ACTION_EXECUTION_STATE_EXECUTED, + SIEVE_ACTION_EXECUTION_STATE_FINALIZED, +}; + +struct sieve_result_action { + struct sieve_action action; + + struct sieve_side_effects_list *seffects; + + struct sieve_result_action *prev, *next; +}; + +struct sieve_side_effects_list { + struct sieve_result *result; + + struct sieve_result_side_effect *first_effect; + struct sieve_result_side_effect *last_effect; +}; + +struct sieve_result_side_effect { + struct sieve_side_effect seffect; + + struct sieve_result_side_effect *prev, *next; +}; + +struct sieve_result_action_context { + const struct sieve_action_def *action; + struct sieve_side_effects_list *seffects; +}; + +/* + * Result object + */ + +struct sieve_result { + pool_t pool; + int refcount; + + struct sieve_instance *svinst; + struct event *event; + + /* Context data for extensions */ + ARRAY(void *) ext_contexts; + + const struct sieve_execute_env *exec_env; + struct sieve_error_handler *ehandler; + struct sieve_message_context *msgctx; + + unsigned int exec_seq; + struct sieve_result_execution *exec; + + struct sieve_action keep_action; + struct sieve_action failure_action; + + unsigned int action_count; + struct sieve_result_action *actions_head, *actions_tail; + + HASH_TABLE(const struct sieve_action_def *, + struct sieve_result_action_context *) action_contexts; +}; + +static const char * +sieve_result_event_log_message(struct sieve_result *result, + enum log_type log_type, const char *message) +{ + const struct sieve_script_env *senv = result->exec_env->scriptenv; + + i_assert(senv->result_amend_log_message != NULL); + return senv->result_amend_log_message(senv, log_type, message); +} + +struct sieve_result * +sieve_result_create(struct sieve_instance *svinst, pool_t pool, + const struct sieve_execute_env *eenv) +{ + const struct sieve_script_env *senv = eenv->scriptenv; + const struct sieve_message_data *msgdata = eenv->msgdata; + struct sieve_result *result; + + pool_ref(pool); + + result = p_new(pool, struct sieve_result, 1); + result->refcount = 1; + result->pool = pool; + result->svinst = svinst; + + result->event = event_create(eenv->event); + event_add_category(result->event, &event_category_sieve_action); + if (senv->result_amend_log_message != NULL) { + event_set_log_message_callback( + result->event, sieve_result_event_log_message, result); + } + + p_array_init(&result->ext_contexts, pool, 4); + + result->exec_env = eenv; + result->msgctx = + sieve_message_context_create(svinst, senv->user, msgdata); + + result->keep_action.def = &act_store; + result->keep_action.ext = NULL; + result->failure_action.def = &act_store; + result->failure_action.ext = NULL; + + result->action_count = 0; + result->actions_head = NULL; + result->actions_tail = NULL; + + return result; +} + +void sieve_result_ref(struct sieve_result *result) +{ + result->refcount++; +} + +static void +sieve_result_action_deinit(struct sieve_result_action *ract) +{ + event_unref(&ract->action.event); +} + +void sieve_result_unref(struct sieve_result **_result) +{ + struct sieve_result *result = *_result; + struct sieve_result_action *ract; + + i_assert(result->refcount > 0); + + if (--result->refcount != 0) + return; + + sieve_message_context_unref(&result->msgctx); + + hash_table_destroy(&result->action_contexts); + + ract = result->actions_head; + while (ract != NULL) { + sieve_result_action_deinit(ract); + ract = ract->next; + } + event_unref(&result->event); + + pool_unref(&result->pool); + *_result = NULL; +} + +pool_t sieve_result_pool(struct sieve_result *result) +{ + return result->pool; +} + +/* + * Getters/Setters + */ + +const struct sieve_script_env * +sieve_result_get_script_env(struct sieve_result *result) +{ + return result->exec_env->scriptenv; +} + +const struct sieve_message_data * +sieve_result_get_message_data(struct sieve_result *result) +{ + return result->exec_env->msgdata; +} + +struct sieve_message_context * +sieve_result_get_message_context(struct sieve_result *result) +{ + return result->msgctx; +} + +unsigned int sieve_result_get_exec_seq(struct sieve_result *result) +{ + return result->exec_seq; +} + +/* + * Extension support + */ + +void sieve_result_extension_set_context(struct sieve_result *result, + const struct sieve_extension *ext, + void *context) +{ + if (ext->id < 0) + return; + + array_idx_set(&result->ext_contexts, (unsigned int) ext->id, &context); +} + +const void * +sieve_result_extension_get_context(struct sieve_result *result, + const struct sieve_extension *ext) +{ + void * const *ctx; + + if (ext->id < 0 || ext->id >= (int) array_count(&result->ext_contexts)) + return NULL; + + ctx = array_idx(&result->ext_contexts, (unsigned int) ext->id); + + return *ctx; +} + +/* + * Result composition + */ + +static void +sieve_result_init_action_event(struct sieve_result *result, + struct sieve_action *action, bool add_prefix) +{ + const char *name = sieve_action_name(action); + + if (action->event != NULL) + return; + + action->event = event_create(result->event); + if (add_prefix && name != NULL) { + event_set_append_log_prefix( + action->event, t_strconcat(name, " action: ", NULL)); + } + event_add_str(action->event, "action_name", name); + event_add_str(action->event, "script_location", action->location); +} + +void sieve_result_add_implicit_side_effect( + struct sieve_result *result, const struct sieve_action_def *to_action, + bool to_keep, const struct sieve_extension *ext, + const struct sieve_side_effect_def *seff_def, void *context) +{ + struct sieve_result_action_context *actctx = NULL; + struct sieve_side_effect seffect; + + to_action = to_keep ? &act_store : to_action; + + if (!hash_table_is_created(result->action_contexts)) { + hash_table_create_direct(&result->action_contexts, + result->pool, 0); + } else { + actctx = hash_table_lookup(result->action_contexts, to_action); + } + + if (actctx == NULL) { + actctx = p_new(result->pool, + struct sieve_result_action_context, 1); + actctx->action = to_action; + actctx->seffects = sieve_side_effects_list_create(result); + + hash_table_insert(result->action_contexts, to_action, actctx); + } + + seffect.object.def = &seff_def->obj_def; + seffect.object.ext = ext; + seffect.def = seff_def; + seffect.context = context; + + sieve_side_effects_list_add(actctx->seffects, &seffect); +} + +static int +sieve_result_side_effects_merge(const struct sieve_runtime_env *renv, + const struct sieve_action *action, + struct sieve_result_action *old_action, + struct sieve_side_effects_list *new_seffects) +{ + struct sieve_side_effects_list *old_seffects = old_action->seffects; + int ret; + struct sieve_result_side_effect *rsef, *nrsef; + + /* Allow side-effects to merge with existing copy */ + + /* Merge existing side effects */ + rsef = old_seffects != NULL ? old_seffects->first_effect : NULL; + while (rsef != NULL) { + struct sieve_side_effect *seffect = &rsef->seffect; + bool found = FALSE; + + i_assert(seffect->def != NULL); + if (seffect->def->merge != NULL) { + /* Try to find it among the new */ + nrsef = (new_seffects != NULL ? + new_seffects->first_effect : NULL); + while (nrsef != NULL) { + struct sieve_side_effect *nseffect = &nrsef->seffect; + + if (nseffect->def == seffect->def) { + if (seffect->def->merge( + renv, action, seffect, nseffect, + &seffect->context) < 0) + return -1; + + found = TRUE; + break; + } + nrsef = nrsef->next; + } + + /* Not found? */ + if (!found && seffect->def->merge( + renv, action, seffect, NULL, + &rsef->seffect.context) < 0) + return -1; + } + rsef = rsef->next; + } + + /* Merge new Side effects */ + nrsef = new_seffects != NULL ? new_seffects->first_effect : NULL; + while (nrsef != NULL) { + struct sieve_side_effect *nseffect = &nrsef->seffect; + bool found = FALSE; + + i_assert(nseffect->def != NULL); + if (nseffect->def->merge != NULL) { + /* Try to find it among the exising */ + rsef = (old_seffects != NULL ? + old_seffects->first_effect : NULL); + while (rsef != NULL) { + if (rsef->seffect.def == nseffect->def) { + found = TRUE; + break; + } + rsef = rsef->next; + } + + /* Not found? */ + if (!found) { + void *new_context = NULL; + + if ((ret = nseffect->def->merge( + renv, action, nseffect, nseffect, + &new_context)) < 0) + return -1; + + if (ret != 0) { + if (old_action->seffects == NULL) { + old_action->seffects = old_seffects = + sieve_side_effects_list_create(renv->result); + } + + nseffect->context = new_context; + + /* Add side effect */ + sieve_side_effects_list_add(old_seffects, + nseffect); + } + } + } + nrsef = nrsef->next; + } + + return 1; +} + +static void +sieve_result_action_detach(struct sieve_result *result, + struct sieve_result_action *raction) +{ + if (result->actions_head == raction) + result->actions_head = raction->next; + + if (result->actions_tail == raction) + result->actions_tail = raction->prev; + + if (raction->next != NULL) + raction->next->prev = raction->prev; + if (raction->prev != NULL) + raction->prev->next = raction->next; + + raction->next = NULL; + raction->prev = NULL; + + if (result->action_count > 0) + result->action_count--; +} + +static int +_sieve_result_add_action(const struct sieve_runtime_env *renv, + const struct sieve_extension *ext, const char *name, + const struct sieve_action_def *act_def, + struct sieve_side_effects_list *seffects, + void *context, unsigned int instance_limit, + bool preserve_mail, bool keep) +{ + int ret = 0; + unsigned int instance_count = 0; + struct sieve_instance *svinst = renv->exec_env->svinst; + struct sieve_result *result = renv->result; + struct sieve_result_action *raction = NULL, *kaction = NULL; + struct sieve_action action; + + i_assert(name != NULL || act_def != NULL); + action.name = name; + action.def = act_def; + action.ext = ext; + action.location = sieve_runtime_get_full_command_location(renv); + action.context = context; + action.exec_seq = result->exec_seq; + + /* First, check for duplicates or conflicts */ + raction = result->actions_head; + while (raction != NULL) { + const struct sieve_action *oact = &raction->action; + bool oact_new = (oact->exec_seq == result->exec_seq); + + if (keep && raction->action.keep) { + /* Duplicate keep */ + if (oact->def == NULL || !oact_new) { + /* Keep action from preceeding execution */ + + /* Detach existing keep action */ + sieve_result_action_detach(result, raction); + + /* Merge existing side-effects with new keep action */ + if (kaction == NULL) + kaction = raction; + + if ((ret = sieve_result_side_effects_merge( + renv, &action, kaction, seffects)) <= 0) + return ret; + } else { + /* True duplicate */ + return sieve_result_side_effects_merge( + renv, &action, raction, seffects); + } + } else if ( act_def != NULL && raction->action.def == act_def ) { + instance_count++; + + /* Possible duplicate */ + if (act_def->check_duplicate != NULL) { + if ((ret = act_def->check_duplicate( + renv, &action, &raction->action)) < 0) + return ret; + + /* Duplicate */ + if (ret == 1) { + if (keep && !oact->keep) { + /* New keep has higher precedence than + existing duplicate non-keep action. + So, take over the result action object + and transform it into a keep. + */ + if ((ret = sieve_result_side_effects_merge( + renv, &action, raction, seffects)) < 0) + return ret; + + if (kaction == NULL) { + raction->action.context = NULL; + raction->action.location = + p_strdup(result->pool, action.location); + + /* Note that existing execution + status is retained, making sure + that keep is not executed + multiple times. + */ + kaction = raction; + } else { + sieve_result_action_detach(result, raction); + + if ((ret = sieve_result_side_effects_merge( + renv, &action, kaction, + raction->seffects)) < 0) + return ret; + } + } else { + /* Merge side-effects, but don't add new action + */ + return sieve_result_side_effects_merge( + renv, &action, raction, seffects); + } + } + } + } else { + if (act_def != NULL && oact->def != NULL) { + /* Check conflict */ + if (act_def->check_conflict != NULL && + (ret = act_def->check_conflict( + renv, &action, &raction->action)) != 0) + return ret; + + if (oact_new && + oact->def->check_conflict != NULL && + (ret = oact->def->check_conflict( + renv, &raction->action, &action)) != 0) + return ret; + } + } + raction = raction->next; + } + + if (kaction != NULL) { + /* Use existing keep action to define new one */ + raction = kaction; + } else { + /* Check policy limit on total number of actions */ + if (svinst->max_actions > 0 && + result->action_count >= svinst->max_actions) + { + sieve_runtime_error( + renv, action.location, + "total number of actions exceeds policy limit " + "(%u > %u)", + result->action_count+1, svinst->max_actions); + return -1; + } + + /* Check policy limit on number of this class of actions */ + if (instance_limit > 0 && instance_count >= instance_limit) { + sieve_runtime_error( + renv, action.location, + "number of %s actions exceeds policy limit " + "(%u > %u)", + act_def->name, instance_count+1, + instance_limit); + return -1; + } + + /* Create new action object */ + raction = p_new(result->pool, struct sieve_result_action, 1); + raction->seffects = seffects; + } + + raction->action.name = (action.name == NULL ? + act_def->name : + p_strdup(result->pool, action.name)); + raction->action.context = context; + raction->action.def = act_def; + raction->action.ext = ext; + raction->action.location = p_strdup(result->pool, action.location); + raction->action.keep = keep; + raction->action.exec_seq = result->exec_seq; + + if (raction->prev == NULL && raction != result->actions_head) { + /* Add */ + if (result->actions_head == NULL) { + result->actions_head = raction; + result->actions_tail = raction; + raction->prev = NULL; + raction->next = NULL; + } else { + result->actions_tail->next = raction; + raction->prev = result->actions_tail; + result->actions_tail = raction; + raction->next = NULL; + } + result->action_count++; + + /* Apply any implicit side effects */ + if (hash_table_is_created(result->action_contexts)) { + struct sieve_result_action_context *actctx; + + /* Check for implicit side effects to this particular + action */ + actctx = hash_table_lookup( + result->action_contexts, + (keep ? &act_store : act_def)); + + if (actctx != NULL) { + struct sieve_result_side_effect *iseff; + + /* Iterate through all implicit side effects and + add those that are missing. + */ + iseff = actctx->seffects->first_effect; + while (iseff != NULL) { + struct sieve_result_side_effect *seff; + bool exists = FALSE; + + /* Scan for presence */ + if (seffects != NULL) { + seff = seffects->first_effect; + while (seff != NULL) { + if (seff->seffect.def == iseff->seffect.def) { + exists = TRUE; + break; + } + + seff = seff->next; + } + } else { + raction->seffects = seffects = + sieve_side_effects_list_create(result); + } + + /* If not present, add it */ + if (!exists) { + sieve_side_effects_list_add(seffects, &iseff->seffect); + } + + iseff = iseff->next; + } + } + } + } + + if (preserve_mail) { + raction->action.mail = sieve_message_get_mail(renv->msgctx); + sieve_message_snapshot(renv->msgctx); + } else { + raction->action.mail = NULL; + } + + sieve_result_init_action_event(result, &raction->action, !keep); + return 0; +} + +int sieve_result_add_action(const struct sieve_runtime_env *renv, + const struct sieve_extension *ext, const char *name, + const struct sieve_action_def *act_def, + struct sieve_side_effects_list *seffects, + void *context, unsigned int instance_limit, + bool preserve_mail) +{ + return _sieve_result_add_action(renv, ext, name, act_def, seffects, + context, instance_limit, preserve_mail, + FALSE); +} + +int sieve_result_add_keep(const struct sieve_runtime_env *renv, + struct sieve_side_effects_list *seffects) +{ + return _sieve_result_add_action(renv, renv->result->keep_action.ext, + "keep", renv->result->keep_action.def, + seffects, NULL, 0, TRUE, TRUE); +} + +void sieve_result_set_keep_action(struct sieve_result *result, + const struct sieve_extension *ext, + const struct sieve_action_def *act_def) +{ + result->keep_action.def = act_def; + result->keep_action.ext = ext; +} + +void sieve_result_set_failure_action(struct sieve_result *result, + const struct sieve_extension *ext, + const struct sieve_action_def *act_def) +{ + result->failure_action.def = act_def; + result->failure_action.ext = ext; +} + +/* + * Result printing + */ + +void sieve_result_vprintf(const struct sieve_result_print_env *penv, + const char *fmt, va_list args) +{ + string_t *outbuf = t_str_new(128); + + str_vprintfa(outbuf, fmt, args); + + o_stream_nsend(penv->stream, str_data(outbuf), str_len(outbuf)); +} + +void sieve_result_printf(const struct sieve_result_print_env *penv, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + sieve_result_vprintf(penv, fmt, args); + va_end(args); +} + +void sieve_result_action_printf(const struct sieve_result_print_env *penv, + const char *fmt, ...) +{ + string_t *outbuf = t_str_new(128); + va_list args; + + va_start(args, fmt); + str_append(outbuf, " * "); + str_vprintfa(outbuf, fmt, args); + str_append_c(outbuf, '\n'); + va_end(args); + + o_stream_nsend(penv->stream, str_data(outbuf), str_len(outbuf)); +} + +void sieve_result_seffect_printf(const struct sieve_result_print_env *penv, + const char *fmt, ...) +{ + string_t *outbuf = t_str_new(128); + va_list args; + + va_start(args, fmt); + str_append(outbuf, " + "); + str_vprintfa(outbuf, fmt, args); + str_append_c(outbuf, '\n'); + va_end(args); + + o_stream_nsend(penv->stream, str_data(outbuf), str_len(outbuf)); +} + +static void +sieve_result_print_side_effects(struct sieve_result_print_env *rpenv, + const struct sieve_action *action, + struct sieve_side_effects_list *slist, + bool *implicit_keep) +{ + struct sieve_result_side_effect *rsef; + + /* Print side effects */ + rsef = (slist != NULL ? slist->first_effect : NULL); + while (rsef != NULL) { + const struct sieve_side_effect *sef = &rsef->seffect; + + i_assert(sef->def != NULL); + + if (sef->def->print != NULL) { + sef->def->print(sef, action, rpenv, + implicit_keep); + } + rsef = rsef->next; + } +} + +static void +sieve_result_print_implicit_side_effects(struct sieve_result_print_env *rpenv) +{ + struct sieve_result *result = rpenv->result; + bool dummy = TRUE; + + /* Print any implicit side effects if applicable */ + if (hash_table_is_created(result->action_contexts)) { + struct sieve_result_action_context *actctx; + + /* Check for implicit side effects to keep action */ + actctx = hash_table_lookup(rpenv->result->action_contexts, + &act_store); + + if (actctx != NULL && actctx->seffects != NULL) { + sieve_result_print_side_effects( + rpenv, &result->keep_action, + actctx->seffects, &dummy); + } + } +} + +bool sieve_result_print(struct sieve_result *result, + const struct sieve_script_env *senv, + struct ostream *stream, bool *keep) +{ + struct sieve_action act_keep = result->keep_action; + struct sieve_result_print_env penv; + bool implicit_keep = TRUE, printed_any = FALSE; + struct sieve_result_action *rac; + + if (keep != NULL) + *keep = FALSE; + + /* Prepare environment */ + + penv.result = result; + penv.stream = stream; + penv.scriptenv = senv; + + sieve_result_printf(&penv, "\nPerformed actions:\n\n"); + + rac = result->actions_head; + while (rac != NULL) { + bool impl_keep = TRUE; + const struct sieve_action *act = &rac->action; + + if (act->exec_seq < result->exec_seq) { + rac = rac->next; + continue; + } + + if (rac->action.keep && keep != NULL) + *keep = TRUE; + + if (act->def != NULL) { + if (act->def->print != NULL) + act->def->print(act, &penv, &impl_keep); + else { + sieve_result_action_printf( + &penv, "%s", act->def->name); + } + } else { + if (act->keep) { + sieve_result_action_printf(&penv, "keep"); + impl_keep = FALSE; + } else { + sieve_result_action_printf(&penv, "[NULL]"); + } + } + printed_any = TRUE; + + /* Print side effects */ + sieve_result_print_side_effects( + &penv, &rac->action, rac->seffects, &impl_keep); + + implicit_keep = implicit_keep && impl_keep; + + rac = rac->next; + } + if (!printed_any) + sieve_result_printf(&penv, " (none)\n"); + + if (implicit_keep && keep != NULL) + *keep = TRUE; + + sieve_result_printf(&penv, "\nImplicit keep:\n\n"); + + if (implicit_keep) { + bool dummy = TRUE; + + if (act_keep.def == NULL) { + sieve_result_action_printf(&penv, "keep"); + + sieve_result_print_implicit_side_effects(&penv); + } else { + /* Scan for execution of keep-equal actions */ + rac = result->actions_head; + while (act_keep.def != NULL && rac != NULL) { + if (rac->action.def == act_keep.def && + act_keep.def->equals != NULL && + act_keep.def->equals(senv, NULL, &rac->action) && + sieve_action_is_executed(&rac->action, + result)) + act_keep.def = NULL; + + rac = rac->next; + } + + if (act_keep.def == NULL) { + sieve_result_printf(&penv, + " (none; keep or equivalent action executed earlier)\n"); + } else { + act_keep.def->print(&act_keep, &penv, &dummy); + + sieve_result_print_implicit_side_effects(&penv); + } + } + } else { + sieve_result_printf(&penv, " (none)\n"); + } + + sieve_result_printf(&penv, "\n"); + + return TRUE; +} + +/* + * Result execution + */ + +struct sieve_side_effect_execution { + struct sieve_result_side_effect *seffect; + + void *tr_context; + + struct sieve_side_effect_execution *prev, *next; +}; + +struct sieve_action_execution { + struct sieve_result_action *action; + unsigned int exec_seq; + struct sieve_action_execution *prev, *next; + + struct sieve_side_effect_execution *seffects_head, *seffects_tail; + + struct sieve_error_handler *ehandler; + void *tr_context; + enum sieve_action_execution_state state; + int status; + + bool commit:1; +}; + +struct sieve_result_execution { + pool_t pool; + struct sieve_action_exec_env action_env; + struct sieve_error_handler *ehandler; + struct event *event; + + int status; + + struct sieve_action_execution *actions_head, *actions_tail; + + struct sieve_result_action keep_action; + struct sieve_action_execution keep; + struct sieve_action_execution *keep_equiv_action; + int keep_status; + + bool keep_success:1; + bool keep_explicit:1; + bool keep_implicit:1; + bool keep_finalizing:1; + bool seen_delivery:1; + bool executed:1; + bool executed_delivery:1; + bool committed:1; +}; + +void sieve_result_mark_executed(struct sieve_result *result) +{ + result->exec_seq++; +} + +/* Side effect */ + +static int +sieve_result_side_effect_pre_execute(struct sieve_result_execution *rexec, + struct sieve_action_execution *aexec, + struct sieve_side_effect_execution *seexec) +{ + struct sieve_result_side_effect *rsef = seexec->seffect; + struct sieve_side_effect *sef = &rsef->seffect; + + i_assert(sef->def != NULL); + if (sef->def->pre_execute == NULL) + return SIEVE_EXEC_OK; + + return sef->def->pre_execute(sef, &rexec->action_env, + aexec->tr_context, &seexec->tr_context); +} + +static int +sieve_result_side_effect_post_execute( + struct sieve_result_execution *rexec, + struct sieve_action_execution *aexec, + struct sieve_side_effect_execution *seexec, bool *impl_keep) +{ + struct sieve_result_side_effect *rsef = seexec->seffect; + struct sieve_side_effect *sef = &rsef->seffect; + + i_assert(sef->def != NULL); + if (sef->def->post_execute == NULL) + return SIEVE_EXEC_OK; + + return sef->def->post_execute(sef, &rexec->action_env, + aexec->tr_context, seexec->tr_context, + impl_keep); +} + +static void +sieve_result_side_effect_post_commit(struct sieve_result_execution *rexec, + struct sieve_action_execution *aexec, + struct sieve_side_effect_execution *seexec, + int commit_status) +{ + struct sieve_result_side_effect *rsef = seexec->seffect; + struct sieve_side_effect *sef = &rsef->seffect; + + i_assert(sef->def != NULL); + if (sef->def->post_commit == NULL) + return; + + sef->def->post_commit(sef, &rexec->action_env, + aexec->tr_context, seexec->tr_context, + commit_status); +} + +static void +sieve_result_side_effect_rollback(struct sieve_result_execution *rexec, + struct sieve_action_execution *aexec, + struct sieve_side_effect_execution *seexec) +{ + struct sieve_result_side_effect *rsef = seexec->seffect; + struct sieve_side_effect *sef = &rsef->seffect; + + i_assert(sef->def != NULL); + if (sef->def->rollback == NULL) + return; + + sef->def->rollback(sef, &rexec->action_env, + aexec->tr_context, seexec->tr_context, + (aexec->status == SIEVE_EXEC_OK)); +} + +static void +sieve_action_execution_add_side_effect(struct sieve_result_execution *rexec, + struct sieve_action_execution *aexec, + struct sieve_result_side_effect *seffect) +{ + struct sieve_side_effect_execution *seexec; + + seexec = aexec->seffects_head; + while (seexec != NULL) { + if (seexec->seffect == seffect) + return; + seexec = seexec->next; + } + + seexec = p_new(rexec->pool, struct sieve_side_effect_execution, 1); + seexec->seffect = seffect; + + DLLIST2_APPEND(&aexec->seffects_head, &aexec->seffects_tail, seexec); +} + +static void +sieve_action_execution_add_side_effects(struct sieve_result_execution *rexec, + struct sieve_action_execution *aexec, + struct sieve_result_action *rac) +{ + struct sieve_result_side_effect *rsef; + + rsef = (rac->seffects == NULL ? NULL : rac->seffects->first_effect); + while (rsef != NULL) { + sieve_action_execution_add_side_effect(rexec, aexec, rsef); + rsef = rsef->next; + } +} + +/* Action */ + +static void +sieve_action_execution_pre(struct sieve_result_execution *rexec, + struct sieve_action_execution *aexec) +{ + if (aexec->ehandler == NULL) + aexec->ehandler = rexec->ehandler; + rexec->action_env.action = &aexec->action->action; + rexec->action_env.event = aexec->action->action.event; + rexec->action_env.ehandler = aexec->ehandler; +} + +static void +sieve_action_execution_post(struct sieve_result_execution *rexec) +{ + rexec->action_env.action = NULL; + rexec->action_env.event = rexec->action_env.result->event; + rexec->action_env.ehandler = NULL; +} + +static int +sieve_result_action_start(struct sieve_result_execution *rexec, + struct sieve_action_execution *aexec) +{ + struct sieve_result_action *rac = aexec->action; + struct sieve_action *act = &rac->action; + int status = SIEVE_EXEC_OK; + + /* Skip actions that are already started. */ + if (aexec->state >= SIEVE_ACTION_EXECUTION_STATE_STARTED) + return status; + aexec->state = SIEVE_ACTION_EXECUTION_STATE_STARTED; + aexec->status = status; + + /* Skip non-actions (inactive keep). */ + if (act->def == NULL) + return status; + + if (act->def->start != NULL) { + sieve_action_execution_pre(rexec, aexec); + status = act->def->start(&rexec->action_env, + &aexec->tr_context); + aexec->status = status; + sieve_action_execution_post(rexec); + } + return status; +} + +static int +sieve_result_action_execute(struct sieve_result_execution *rexec, + struct sieve_action_execution *aexec, + int start_status) +{ + struct sieve_result_action *rac = aexec->action; + struct sieve_action *act = &rac->action; + struct sieve_side_effect_execution *seexec; + int status = start_status; + bool impl_keep = TRUE; + + /* Skip actions that are already executed. */ + if (aexec->state >= SIEVE_ACTION_EXECUTION_STATE_EXECUTED) + return status; + aexec->state = SIEVE_ACTION_EXECUTION_STATE_EXECUTED; + + /* Record explicit keep when it is not the final implicit keep */ + if (act->keep && aexec != &rexec->keep) + rexec->keep_explicit = TRUE; + + /* Skip non-actions (inactive keep) */ + if (act->def == NULL) { + i_assert(aexec != &rexec->keep); + if (act->keep) + e_debug(rexec->event, "Executed explicit keep"); + return status; + } + + /* Don't execute if others already failed */ + if (status != SIEVE_EXEC_OK) + return status; + + if (aexec == &rexec->keep) + e_debug(rexec->event, "Executing implicit keep action"); + else { + e_debug(rexec->event, "Executing %s action%s", + sieve_action_name(act), + (act->keep ? " (explicit keep)" : "")); + } + + sieve_action_execution_pre(rexec, aexec); + + /* Execute pre-execute event of side effects */ + seexec = aexec->seffects_head; + while (status == SIEVE_EXEC_OK && seexec != NULL) { + status = sieve_result_side_effect_pre_execute( + rexec, aexec, seexec); + seexec = seexec->next; + } + + /* Execute the action itself */ + if (status == SIEVE_EXEC_OK && act->def != NULL && + act->def->execute != NULL) { + status = act->def->execute(&rexec->action_env, + aexec->tr_context, + &impl_keep); + if (status == SIEVE_EXEC_OK) + rexec->executed = TRUE; + } + + /* Execute post-execute event of side effects */ + seexec = aexec->seffects_head; + while (status == SIEVE_EXEC_OK && seexec != NULL) { + status = sieve_result_side_effect_post_execute( + rexec, aexec, seexec, &impl_keep); + seexec = seexec->next; + } + + if (aexec == &rexec->keep) { + e_debug(rexec->event, + "Finished executing implicit keep action (status=%s)", + sieve_execution_exitcode_to_str(status)); + } else { + e_debug(rexec->event, "Finished executing %s action " + "(status=%s, keep=%s)", sieve_action_name(act), + sieve_execution_exitcode_to_str(status), + (act->keep ? "explicit" : + (impl_keep && rexec->keep_implicit ? + "implicit" : "canceled"))); + } + + if (status == SIEVE_EXEC_OK && + (act->def->flags & SIEVE_ACTFLAG_TRIES_DELIVER) != 0) + rexec->seen_delivery = TRUE; + + /* Update implicit keep status (but only when we're not running the + implicit keep right now). */ + if (aexec != &rexec->keep) + rexec->keep_implicit = rexec->keep_implicit && impl_keep; + + sieve_action_execution_post(rexec); + + aexec->status = status; + return status; +} + +static int +sieve_result_action_commit(struct sieve_result_execution *rexec, + struct sieve_action_execution *aexec) +{ + struct sieve_result_action *rac = aexec->action; + struct sieve_action *act = &rac->action; + struct sieve_side_effect_execution *seexec; + int cstatus = SIEVE_EXEC_OK; + + if (aexec == &rexec->keep) { + e_debug(rexec->event, "Commit implicit keep action"); + } else { + e_debug(rexec->event, "Commit %s action%s", + sieve_action_name(act), + (act->keep ? " (explicit keep)" : "")); + } + + sieve_action_execution_pre(rexec, aexec); + + if (act->def->commit != NULL) { + cstatus = act->def->commit(&rexec->action_env, + aexec->tr_context); + if (cstatus == SIEVE_EXEC_OK) + rexec->committed = TRUE; + } + + /* Execute post_commit event of side effects */ + seexec = aexec->seffects_head; + while (seexec != NULL) { + sieve_result_side_effect_post_commit( + rexec, aexec, seexec, cstatus); + seexec = seexec->next; + } + + sieve_action_execution_post(rexec); + + return cstatus; +} + +static void +sieve_result_action_rollback(struct sieve_result_execution *rexec, + struct sieve_action_execution *aexec) +{ + struct sieve_result_action *rac = aexec->action; + struct sieve_action *act = &rac->action; + struct sieve_side_effect_execution *seexec; + + if (aexec == &rexec->keep) { + e_debug(rexec->event, "Roll back implicit keep action"); + } else { + e_debug(rexec->event, "Roll back %s action%s", + sieve_action_name(act), + (act->keep ? " (explicit keep)" : "")); + } + + sieve_action_execution_pre(rexec, aexec); + + if (act->def->rollback != NULL) { + act->def->rollback(&rexec->action_env, aexec->tr_context, + (aexec->status == SIEVE_EXEC_OK)); + } + + /* Rollback side effects */ + seexec = aexec->seffects_head; + while (seexec != NULL) { + sieve_result_side_effect_rollback(rexec, aexec, seexec); + seexec = seexec->next; + } + + sieve_action_execution_post(rexec); +} + +static int +sieve_result_action_commit_or_rollback(struct sieve_result_execution *rexec, + struct sieve_action_execution *aexec, + int status, int *commit_status) +{ + struct sieve_result_action *rac = aexec->action; + struct sieve_action *act = &rac->action; + + /* Skip actions that are already finalized. */ + if (aexec->state >= SIEVE_ACTION_EXECUTION_STATE_FINALIZED) + return status; + aexec->state = SIEVE_ACTION_EXECUTION_STATE_FINALIZED; + + if (aexec == &rexec->keep) { + e_debug(rexec->event, "Finalize implicit keep action" + "(status=%s, action_status=%s, commit_status=%s)", + sieve_execution_exitcode_to_str(status), + sieve_execution_exitcode_to_str(aexec->status), + sieve_execution_exitcode_to_str(*commit_status)); + } else { + e_debug(rexec->event, "Finalize %s action " + "(%sstatus=%s, action_status=%s, commit_status=%s, " + "pre-commit=%s)", + sieve_action_name(act), + (act->keep ? "explicit keep, " : ""), + sieve_execution_exitcode_to_str(status), + sieve_execution_exitcode_to_str(aexec->status), + sieve_execution_exitcode_to_str(*commit_status), + (aexec->commit ? "yes" : "no")); + } + + /* Skip non-actions (inactive keep) */ + if (act->def == NULL) + return status; + + if (aexec->status == SIEVE_EXEC_OK && + (status == SIEVE_EXEC_OK || + (aexec->commit && *commit_status == SIEVE_EXEC_OK))) { + int cstatus = SIEVE_EXEC_OK; + + cstatus = sieve_result_action_commit(rexec, aexec); + if (cstatus != SIEVE_EXEC_OK) { + /* This is bad; try to salvage as much as possible */ + if (*commit_status == SIEVE_EXEC_OK) { + *commit_status = cstatus; + if (!rexec->committed) { + /* We haven't executed anything yet; + continue as rollback */ + status = cstatus; + } + } + } + } else { + sieve_result_action_rollback(rexec, aexec); + } + + if (act->keep) { + if (status == SIEVE_EXEC_FAILURE) + status = SIEVE_EXEC_KEEP_FAILED; + if (*commit_status == SIEVE_EXEC_FAILURE) + *commit_status = SIEVE_EXEC_KEEP_FAILED; + } + + return status; +} + +static void +sieve_result_action_finish(struct sieve_result_execution *rexec, + struct sieve_action_execution *aexec, int status) +{ + struct sieve_result_action *rac = aexec->action; + struct sieve_action *act = &rac->action; + + /* Skip non-actions (inactive keep) */ + if (act->def == NULL) + return; + + if (aexec == &rexec->keep) { + e_debug(rexec->event, "Finish implicit keep action"); + } else { + e_debug(rexec->event, "Finish %s action%s", + sieve_action_name(act), + (act->keep ? " (explicit keep)" : "")); + } + + if (act->def->finish != NULL) { + sieve_action_execution_pre(rexec, aexec); + act->def->finish(&rexec->action_env, aexec->tr_context, status); + sieve_action_execution_post(rexec); + } +} + +static void +sieve_result_action_abort(struct sieve_result_execution *rexec, + struct sieve_action_execution *aexec) +{ + if (aexec->state > SIEVE_ACTION_EXECUTION_STATE_INIT && + aexec->state < SIEVE_ACTION_EXECUTION_STATE_FINALIZED) + sieve_result_action_rollback(rexec, aexec); + DLLIST2_REMOVE(&rexec->actions_head, &rexec->actions_tail, aexec); +} + +static void +sieve_action_execution_update(struct sieve_result_execution *rexec, + struct sieve_action_execution *aexec) +{ + const struct sieve_action_exec_env *aenv = &rexec->action_env; + struct sieve_result *result = aenv->result; + struct sieve_result_action *rac; + + rac = result->actions_head; + while (rac != NULL) { + if (aexec->action == rac) + break; + rac = rac->next; + } + + if (rac == NULL) { + /* Action was removed; abort it. */ + sieve_result_action_abort(rexec, aexec); + return; + } + + if (aexec->exec_seq != rac->action.exec_seq) { + i_assert(rac->action.keep); + + /* Recycled keep */ + aexec->exec_seq = rac->action.exec_seq; + aexec->state = SIEVE_ACTION_EXECUTION_STATE_INIT; + } + + sieve_action_execution_add_side_effects(rexec, aexec, rac); +} + +static void +sieve_result_execution_add_action(struct sieve_result_execution *rexec, + struct sieve_result_action *rac) +{ + struct sieve_action_execution *aexec; + + aexec = rexec->actions_head; + while (aexec != NULL) { + if (aexec->action == rac) + return; + aexec = aexec->next; + } + + aexec = p_new(rexec->pool, struct sieve_action_execution, 1); + aexec->action = rac; + aexec->exec_seq = rac->action.exec_seq; + aexec->ehandler = rexec->ehandler; + + DLLIST2_APPEND(&rexec->actions_head, &rexec->actions_tail, aexec); + + sieve_action_execution_add_side_effects(rexec, aexec, rac); +} + +/* Result */ + +struct sieve_result_execution * +sieve_result_execution_create(struct sieve_result *result, pool_t pool) +{ + struct sieve_result_execution *rexec; + + pool_ref(pool); + rexec = p_new(pool, struct sieve_result_execution, 1); + rexec->pool = pool; + rexec->event = result->event; + rexec->action_env.result = result; + rexec->action_env.event = result->event; + rexec->action_env.exec_env = result->exec_env; + rexec->action_env.msgctx = result->msgctx; + rexec->status = SIEVE_EXEC_OK; + rexec->keep_success = TRUE; + rexec->keep_status = SIEVE_EXEC_OK; + rexec->keep_explicit = FALSE; + rexec->keep_implicit = TRUE; + + sieve_result_ref(result); + result->exec = rexec; + + return rexec; +} + +void sieve_result_execution_destroy(struct sieve_result_execution **_rexec) +{ + struct sieve_result_execution *rexec = *_rexec; + + *_rexec = NULL; + + if (rexec == NULL) + return; + + rexec->action_env.result->exec = NULL; + sieve_result_unref(&rexec->action_env.result); + pool_unref(&rexec->pool); +} + +static void +sieve_result_implicit_keep_execute(struct sieve_result_execution *rexec) +{ + const struct sieve_action_exec_env *aenv = &rexec->action_env; + struct sieve_result *result = aenv->result; + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_action_execution *aexec; + int status = SIEVE_EXEC_OK; + struct sieve_action_execution *aexec_keep = &rexec->keep; + struct sieve_result_action *ract_keep = &rexec->keep_action; + struct sieve_action *act_keep = &ract_keep->action; + bool success = FALSE; + + switch (rexec->status) { + case SIEVE_EXEC_OK: + success = TRUE; + break; + case SIEVE_EXEC_TEMP_FAILURE: + case SIEVE_EXEC_RESOURCE_LIMIT: + if (rexec->committed) { + e_debug(rexec->event, + "Temporary failure occurred (status=%s), " + "but other actions were already committed: " + "execute failure implicit keep", + sieve_execution_exitcode_to_str(rexec->status)); + break; + } + if (rexec->keep_finalizing) + break; + + e_debug(rexec->event, + "Skip implicit keep for temporary failure " + "(state=execute, status=%s)", + sieve_execution_exitcode_to_str(rexec->status)); + return; + default: + break; + } + + if (rexec->keep_equiv_action != NULL) { + e_debug(rexec->event, "No implicit keep needed " + "(equivalent action already executed)"); + return; + } + + rexec->keep.action = &rexec->keep_action; + rexec->keep.ehandler = rexec->ehandler; + rexec->keep_success = success; + rexec->keep_status = status; + + if ((eenv->flags & SIEVE_EXECUTE_FLAG_DEFER_KEEP) != 0) { + e_debug(rexec->event, "Execution of implicit keep is deferred"); + return; + } + + if (!success) + *act_keep = result->failure_action; + else + *act_keep = result->keep_action; + act_keep->name = "keep"; + act_keep->mail = NULL; + act_keep->keep = TRUE; + + /* If keep is a non-action, return right away */ + if (act_keep->def == NULL) { + e_debug(rexec->event, "Keep is not defined yet"); + return; + } + + /* Scan for execution of keep-equal actions */ + aexec = rexec->actions_head; + while (aexec != NULL) { + struct sieve_result_action *rac = aexec->action; + + if (rac->action.def == act_keep->def && + act_keep->def->equals != NULL && + act_keep->def->equals(eenv->scriptenv, NULL, + &rac->action) && + aexec->state >= SIEVE_ACTION_EXECUTION_STATE_EXECUTED) { + e_debug(rexec->event, "No implicit keep needed " + "(equivalent %s action already executed)", + sieve_action_name(&rac->action)); + rexec->keep_equiv_action = aexec; + return; + } + + aexec = aexec->next; + } + + /* Scan for deferred keep */ + aexec = rexec->actions_tail; + while (aexec != NULL) { + struct sieve_result_action *rac = aexec->action; + + if (aexec->state < SIEVE_ACTION_EXECUTION_STATE_EXECUTED) { + aexec = NULL; + break; + } + if (rac->action.keep && rac->action.def == NULL) + break; + aexec = aexec->prev; + } + + if (aexec == NULL) { + if (success) + act_keep->mail = sieve_message_get_mail(aenv->msgctx); + } else { + e_debug(rexec->event, "Found deferred keep action"); + + if (success) { + act_keep->location = aexec->action->action.location; + act_keep->mail = aexec->action->action.mail; + ract_keep->seffects = aexec->action->seffects; + } + aexec->state = SIEVE_ACTION_EXECUTION_STATE_FINALIZED; + } + + if (ract_keep->seffects == NULL) { + /* Apply any implicit side effects if applicable */ + if (success && hash_table_is_created(result->action_contexts)) { + struct sieve_result_action_context *actctx; + + /* Check for implicit side effects to keep action */ + actctx = hash_table_lookup(result->action_contexts, + act_keep->def); + + if (actctx != NULL) + ract_keep->seffects = actctx->seffects; + } + } + + e_debug(rexec->event, "Execute implicit keep (status=%s)", + sieve_execution_exitcode_to_str(rexec->status)); + + /* Initialize side effects */ + sieve_action_execution_add_side_effects(rexec, aexec_keep, ract_keep); + + /* Initialize keep action event */ + sieve_result_init_action_event(result, act_keep, FALSE); + + /* Start keep action */ + status = sieve_result_action_start(rexec, aexec_keep); + + /* Execute keep action */ + if (status == SIEVE_EXEC_OK) + status = sieve_result_action_execute(rexec, aexec_keep, status); + if (status == SIEVE_EXEC_OK) + aexec_keep->commit = TRUE; + + rexec->executed_delivery = rexec->seen_delivery; + rexec->keep_status = status; + sieve_action_execution_post(rexec); +} + +static int +sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec) +{ + const struct sieve_action_exec_env *aenv = &rexec->action_env; + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_action_execution *aexec_keep = &rexec->keep; + struct sieve_result_action *ract_keep = &rexec->keep_action; + struct sieve_action *act_keep = &ract_keep->action; + int commit_status = SIEVE_EXEC_OK; + bool success = FALSE, temp_failure = FALSE; + + switch (rexec->status) { + case SIEVE_EXEC_OK: + success = TRUE; + break; + case SIEVE_EXEC_TEMP_FAILURE: + case SIEVE_EXEC_RESOURCE_LIMIT: + if (rexec->committed) { + e_debug(rexec->event, + "Temporary failure occurred (status=%s), " + "but other actions were already committed: " + "commit failure implicit keep", + sieve_execution_exitcode_to_str(rexec->status)); + break; + } + + if (aexec_keep->state != + SIEVE_ACTION_EXECUTION_STATE_EXECUTED) { + e_debug(rexec->event, + "Skip implicit keep for temporary failure " + "(state=commit, status=%s)", + sieve_execution_exitcode_to_str(rexec->status)); + return rexec->status; + } + /* Roll back for temporary failure when no other action + is committed. */ + commit_status = rexec->status; + temp_failure = TRUE; + break; + default: + break; + } + + if ((eenv->flags & SIEVE_EXECUTE_FLAG_DEFER_KEEP) != 0) { + e_debug(rexec->event, "Execution of implicit keep is deferred"); + return rexec->keep_status; + } + + rexec->keep_finalizing = TRUE; + + /* Start keep if necessary */ + if (temp_failure) { + rexec->keep_status = rexec->status; + } else if (act_keep->def == NULL || + aexec_keep->state != SIEVE_ACTION_EXECUTION_STATE_EXECUTED) { + sieve_result_implicit_keep_execute(rexec); + /* Switch to failure keep if necessary. */ + } else if (rexec->keep_success && !success){ + e_debug(rexec->event, "Switch to failure implicit keep"); + + /* Failed transaction, rollback success keep action. */ + sieve_result_action_rollback(rexec, aexec_keep); + + event_unref(&act_keep->event); + i_zero(aexec_keep); + + /* Start failure keep action. */ + sieve_result_implicit_keep_execute(rexec); + } + if (act_keep->def == NULL) + return rexec->keep_status; + + if (rexec->keep_equiv_action != NULL) { + struct sieve_action_execution *ke_aexec = + rexec->keep_equiv_action; + + i_assert(ke_aexec->state >= + SIEVE_ACTION_EXECUTION_STATE_FINALIZED); + + e_debug(rexec->event, "No implicit keep needed " + "(equivalent %s action already finalized)", + sieve_action_name(&ke_aexec->action->action)); + return ke_aexec->status; + } + + e_debug(rexec->event, "Finalize implicit keep (status=%s)", + sieve_execution_exitcode_to_str(rexec->status)); + + i_assert(aexec_keep->state == SIEVE_ACTION_EXECUTION_STATE_EXECUTED); + + /* Finalize keep action */ + rexec->keep_status = sieve_result_action_commit_or_rollback( + rexec, aexec_keep, rexec->keep_status, &commit_status); + + /* Finish keep action */ + sieve_result_action_finish(rexec, aexec_keep, + rexec->keep_status); + + sieve_action_execution_post(rexec); + event_unref(&act_keep->event); + + if (rexec->keep_status == SIEVE_EXEC_FAILURE) + rexec->keep_status = SIEVE_EXEC_KEEP_FAILED; + return rexec->keep_status; +} + +bool sieve_result_executed(struct sieve_result_execution *rexec) +{ + return rexec->executed; +} + +bool sieve_result_committed(struct sieve_result_execution *rexec) +{ + return rexec->committed; +} + +bool sieve_result_executed_delivery(struct sieve_result_execution *rexec) +{ + return rexec->executed_delivery; +} + +static int sieve_result_transaction_start(struct sieve_result_execution *rexec) +{ + struct sieve_action_execution *aexec; + int status = SIEVE_EXEC_OK; + + e_debug(rexec->event, "Starting execution of actions"); + + aexec = rexec->actions_head; + while (status == SIEVE_EXEC_OK && aexec != NULL) { + status = sieve_result_action_start(rexec, aexec); + aexec = aexec->next; + } + sieve_action_execution_post(rexec); + + return status; +} + +static int +sieve_result_transaction_execute(struct sieve_result_execution *rexec, + int start_status) +{ + struct sieve_action_execution *aexec; + int status = SIEVE_EXEC_OK; + + e_debug(rexec->event, "Executing actions"); + + rexec->seen_delivery = FALSE; + aexec = rexec->actions_head; + while (status == SIEVE_EXEC_OK && aexec != NULL) { + status = sieve_result_action_execute(rexec, aexec, + start_status); + aexec = aexec->next; + } + sieve_action_execution_post(rexec); + + if (status == SIEVE_EXEC_OK) { + /* Since this execution series is successful so far, mark all + actions in it to be committed. */ + aexec = rexec->actions_head; + while (aexec != NULL) { + aexec->commit = TRUE; + aexec = aexec->next; + } + + rexec->executed_delivery = + rexec->executed_delivery || rexec->seen_delivery; + } + + e_debug(rexec->event, "Finished executing actions " + "(status=%s, keep=%s, executed=%s)", + sieve_execution_exitcode_to_str(status), + (rexec->keep_explicit ? "explicit" : + (rexec->keep_implicit ? "implicit" : "none")), + (rexec->executed ? "yes" : "no")); + return status; +} + +static int +sieve_result_transaction_commit_or_rollback( + struct sieve_result_execution *rexec, int status) +{ + struct sieve_action_execution *aexec; + int commit_status = SIEVE_EXEC_OK; + + switch (status) { + case SIEVE_EXEC_TEMP_FAILURE: + /* Roll back all actions */ + commit_status = status; + break; + default: + break; + } + + e_debug(rexec->event, "Finalizing actions"); + + /* First commit/rollback all storage actions */ + aexec = rexec->actions_head; + while (aexec != NULL) { + struct sieve_result_action *rac = aexec->action; + struct sieve_action *act = &rac->action; + + if (act->def == NULL || + (act->def->flags & SIEVE_ACTFLAG_MAIL_STORAGE) == 0) { + aexec = aexec->next; + continue; + } + + status = sieve_result_action_commit_or_rollback( + rexec, aexec, status, &commit_status); + + aexec = aexec->next; + } + + /* Then commit/rollback all other actions */ + aexec = rexec->actions_head; + while (aexec != NULL) { + struct sieve_result_action *rac = aexec->action; + struct sieve_action *act = &rac->action; + + if (act->def != NULL && + (act->def->flags & SIEVE_ACTFLAG_MAIL_STORAGE) != 0) { + aexec = aexec->next; + continue; + } + + status = sieve_result_action_commit_or_rollback( + rexec, aexec, status, &commit_status); + + aexec = aexec->next; + } + + e_debug(rexec->event, "Finished finalizing actions " + "(status=%s, keep=%s, committed=%s)", + sieve_execution_exitcode_to_str(status), + (rexec->keep_explicit ? "explicit" : + (rexec->keep_implicit ? "implicit" : "none")), + (rexec->committed ? "yes" : "no")); + + return commit_status; +} + +static void +sieve_result_transaction_finish(struct sieve_result_execution *rexec, + int status) +{ + struct sieve_action_execution *aexec; + + e_debug(rexec->event, "Finishing actions"); + + aexec = rexec->actions_head; + while (aexec != NULL) { + sieve_result_action_finish(rexec, aexec, status); + aexec = aexec->next; + } + sieve_action_execution_post(rexec); +} + +static void +sieve_result_execute_update_status(struct sieve_result_execution *rexec, + int status) +{ + switch (status) { + case SIEVE_EXEC_OK: + break; + case SIEVE_EXEC_TEMP_FAILURE: + rexec->status = status; + break; + case SIEVE_EXEC_BIN_CORRUPT: + i_unreached(); + case SIEVE_EXEC_FAILURE: + case SIEVE_EXEC_KEEP_FAILED: + if (rexec->status == SIEVE_EXEC_OK) + rexec->status = status; + break; + case SIEVE_EXEC_RESOURCE_LIMIT: + if (rexec->status != SIEVE_EXEC_TEMP_FAILURE) + rexec->status = status; + break; + } +} + +static void +sieve_result_execution_update(struct sieve_result_execution *rexec) +{ + const struct sieve_action_exec_env *aenv = &rexec->action_env; + struct sieve_result *result = aenv->result; + struct sieve_action_execution *aexec; + struct sieve_result_action *rac; + + aexec = rexec->actions_head; + while (aexec != NULL) { + struct sieve_action_execution *aexec_next = aexec->next; + + sieve_action_execution_update(rexec, aexec); + aexec = aexec_next; + } + + rac = result->actions_head; + while (rac != NULL) { + sieve_result_execution_add_action(rexec, rac); + rac = rac->next; + } +} + +int sieve_result_execute(struct sieve_result_execution *rexec, int status, + bool commit, struct sieve_error_handler *ehandler, + bool *keep_r) +{ + const struct sieve_action_exec_env *aenv = &rexec->action_env; + struct sieve_result *result = aenv->result; + int result_status, ret; + + e_debug(rexec->event, "Executing result (status=%s, commit=%s)", + sieve_execution_exitcode_to_str(status), + (commit ? "yes" : "no")); + + if (keep_r != NULL) + *keep_r = FALSE; + sieve_result_mark_executed(result); + + /* Prepare environment */ + + rexec->ehandler = ehandler; + + /* Update actions in execution from result */ + + sieve_result_execution_update(rexec); + + /* Transaction start and execute */ + + if (status != SIEVE_EXEC_OK) { + sieve_result_execute_update_status(rexec, status); + } else if (rexec->status == SIEVE_EXEC_OK) { + /* Transaction start */ + + status = sieve_result_transaction_start(rexec); + + /* Transaction execute */ + + status = sieve_result_transaction_execute(rexec, status); + sieve_result_execute_update_status(rexec, status); + } + + if (!commit) { + sieve_action_execution_post(rexec); + rexec->ehandler = NULL; + + /* Merge explicit keep status into implicit keep for the next + execution round. */ + rexec->keep_implicit = (rexec->keep_explicit || + rexec->keep_implicit); + rexec->keep_explicit = FALSE; + + e_debug(rexec->event, "Finished executing result " + "(no commit, status=%s, keep=%s)", + sieve_execution_exitcode_to_str(rexec->status), + (rexec->keep_implicit ? "yes" : "no")); + + if (keep_r != NULL) + *keep_r = rexec->keep_implicit; + return rexec->status; + } + + /* Execute implicit keep if the transaction failed or when the + implicit keep was not canceled during transaction. + */ + if (rexec->status != SIEVE_EXEC_OK || rexec->keep_implicit) + sieve_result_implicit_keep_execute(rexec); + + /* Transaction commit/rollback */ + + status = sieve_result_transaction_commit_or_rollback(rexec, status); + sieve_result_execute_update_status(rexec, status); + + /* Commit implicit keep if necessary */ + + result_status = rexec->status; + + /* Commit implicit keep if the transaction failed or when the + implicit keep was not canceled during transaction. + */ + if (rexec->status != SIEVE_EXEC_OK || rexec->keep_implicit) { + ret = sieve_result_implicit_keep_finalize(rexec); + switch (ret) { + case SIEVE_EXEC_OK: + if (result_status == SIEVE_EXEC_TEMP_FAILURE) + result_status = SIEVE_EXEC_FAILURE; + break; + case SIEVE_EXEC_TEMP_FAILURE: + case SIEVE_EXEC_RESOURCE_LIMIT: + if (!rexec->committed) { + result_status = ret; + break; + } + /* fall through */ + default: + result_status = SIEVE_EXEC_KEEP_FAILED; + } + } + if (rexec->status == SIEVE_EXEC_OK) + rexec->status = result_status; + + /* Finish execution */ + + sieve_result_transaction_finish(rexec, rexec->status); + + sieve_action_execution_post(rexec); + rexec->ehandler = NULL; + + rexec->status = result_status; + + /* Merge explicit keep status into implicit keep (in this case only for + completeness). + */ + rexec->keep_implicit = (rexec->keep_explicit || + rexec->keep_implicit); + rexec->keep_explicit = FALSE; + + e_debug(rexec->event, "Finished executing result " + "(final, status=%s, keep=%s)", + sieve_execution_exitcode_to_str(result_status), + (rexec->keep_implicit ? "yes" : "no")); + + if (keep_r != NULL) + *keep_r = rexec->keep_implicit; + return result_status; +} + +/* + * Result evaluation + */ + +struct sieve_result_iterate_context { + struct sieve_result *result; + struct sieve_result_action *current_action; + struct sieve_result_action *next_action; +}; + +struct sieve_result_iterate_context * +sieve_result_iterate_init(struct sieve_result *result) +{ + struct sieve_result_iterate_context *rictx = + t_new(struct sieve_result_iterate_context, 1); + + rictx->result = result; + rictx->current_action = NULL; + rictx->next_action = result->actions_head; + + return rictx; +} + +const struct sieve_action * +sieve_result_iterate_next(struct sieve_result_iterate_context *rictx, + bool *keep) +{ + struct sieve_result_action *rac; + + if (rictx == NULL) + return NULL; + + rac = rictx->current_action = rictx->next_action; + if (rac != NULL) { + rictx->next_action = rac->next; + + if (keep != NULL) + *keep = rac->action.keep; + + return &rac->action; + } + + return NULL; +} + +void sieve_result_iterate_delete(struct sieve_result_iterate_context *rictx) +{ + struct sieve_result *result; + struct sieve_result_action *rac; + + if (rictx == NULL || rictx->current_action == NULL) + return; + + result = rictx->result; + rac = rictx->current_action; + + /* Delete action */ + + if (rac->prev == NULL) + result->actions_head = rac->next; + else + rac->prev->next = rac->next; + + if (rac->next == NULL) + result->actions_tail = rac->prev; + else + rac->next->prev = rac->prev; + + sieve_result_action_deinit(rac); + + /* Skip to next action in iteration */ + + rictx->current_action = NULL; +} + +/* + * Side effects list + */ + +struct sieve_side_effects_list * +sieve_side_effects_list_create(struct sieve_result *result) +{ + struct sieve_side_effects_list *list = + p_new(result->pool, struct sieve_side_effects_list, 1); + + list->result = result; + list->first_effect = NULL; + list->last_effect = NULL; + + return list; +} + +void sieve_side_effects_list_add(struct sieve_side_effects_list *list, + const struct sieve_side_effect *seffect) +{ + struct sieve_result_side_effect *reffect, *reffect_pos; + + /* Prevent duplicates */ + reffect = list->first_effect; + reffect_pos = NULL; + while (reffect != NULL) { + const struct sieve_side_effect_def *ref_def = reffect->seffect.def; + const struct sieve_side_effect_def *sef_def = seffect->def; + + i_assert(ref_def != NULL); + i_assert(sef_def != NULL); + + if (sef_def == ref_def) { + /* already listed */ + i_assert(reffect_pos == NULL); + return; + } + if (sef_def->precedence > ref_def->precedence) { + /* insert it before this position */ + reffect_pos = reffect; + } + + reffect = reffect->next; + } + + /* Create new side effect object */ + reffect = p_new(list->result->pool, struct sieve_result_side_effect, 1); + reffect->seffect = *seffect; + + if (reffect_pos != NULL) { + /* Insert */ + reffect->next = reffect_pos; + reffect_pos->prev = reffect; + if (list->first_effect == reffect_pos) + list->first_effect = reffect; + } else { + /* Add */ + if ( list->first_effect == NULL ) { + list->first_effect = reffect; + list->last_effect = reffect; + reffect->prev = NULL; + reffect->next = NULL; + } else { + list->last_effect->next = reffect; + reffect->prev = list->last_effect; + list->last_effect = reffect; + reffect->next = NULL; + } + } +} + +/* + * Error handling + */ + +#undef sieve_result_error +void sieve_result_error(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, unsigned int csrc_linenum, + const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_ERROR, + .event = aenv->event, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + }; + va_list args; + + va_start(args, fmt); + sieve_logv(aenv->ehandler, ¶ms, fmt, args); + va_end(args); +} + +#undef sieve_result_global_error +void sieve_result_global_error(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, + unsigned int csrc_linenum, const char *fmt, ...) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_error_params params = { + .log_type = LOG_TYPE_ERROR, + .event = aenv->event, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + }; + va_list args; + + va_start(args, fmt); + sieve_global_logv(eenv->svinst, aenv->ehandler, ¶ms, fmt, args); + va_end(args); +} + +#undef sieve_result_warning +void sieve_result_warning(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, unsigned int csrc_linenum, + const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_WARNING, + .event = aenv->event, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + }; + va_list args; + + va_start(args, fmt); + sieve_logv(aenv->ehandler, ¶ms, fmt, args); + va_end(args); +} + +#undef sieve_result_global_warning +void sieve_result_global_warning(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, + unsigned int csrc_linenum, + const char *fmt, ...) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_error_params params = { + .log_type = LOG_TYPE_WARNING, + .event = aenv->event, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + }; + va_list args; + + va_start(args, fmt); + sieve_global_logv(eenv->svinst, aenv->ehandler, ¶ms, fmt, args); + va_end(args); +} + +#undef sieve_result_log +void sieve_result_log(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, unsigned int csrc_linenum, + const char *fmt, ...) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_error_params params = { + .log_type = (HAS_ALL_BITS(eenv->flags, + SIEVE_EXECUTE_FLAG_LOG_RESULT) ? + LOG_TYPE_INFO : LOG_TYPE_DEBUG), + .event = aenv->event, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + }; + va_list args; + + va_start(args, fmt); + sieve_logv(aenv->ehandler, ¶ms, fmt, args); + va_end(args); +} + +#undef sieve_result_global_log +void sieve_result_global_log(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, + unsigned int csrc_linenum, const char *fmt, ...) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_error_params params = { + .log_type = (HAS_ALL_BITS(eenv->flags, + SIEVE_EXECUTE_FLAG_LOG_RESULT) ? + LOG_TYPE_INFO : LOG_TYPE_DEBUG), + .event = aenv->event, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + }; + va_list args; + + va_start(args, fmt); + sieve_global_logv(eenv->svinst, aenv->ehandler, ¶ms, fmt, args); + va_end(args); +} + +#undef sieve_result_global_log_error +void sieve_result_global_log_error(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, + unsigned int csrc_linenum, + const char *fmt, ...) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_error_params params = { + .log_type = LOG_TYPE_ERROR, + .event = aenv->event, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + }; + va_list args; + + va_start(args, fmt); + sieve_global_info_logv(eenv->svinst, aenv->ehandler, ¶ms, + fmt, args); + va_end(args); +} + +#undef sieve_result_global_log_warning +void sieve_result_global_log_warning(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, + unsigned int csrc_linenum, + const char *fmt, ...) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_error_params params = { + .log_type = LOG_TYPE_WARNING, + .event = aenv->event, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + }; + va_list args; + + va_start(args, fmt); + sieve_global_info_logv(eenv->svinst, aenv->ehandler, ¶ms, + fmt, args); + va_end(args); +} + +#undef sieve_result_event_log +void sieve_result_event_log(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, + unsigned int csrc_linenum, struct event *event, + const char *fmt, ...) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_error_params params = { + .log_type = (HAS_ALL_BITS(eenv->flags, + SIEVE_EXECUTE_FLAG_LOG_RESULT) ? + LOG_TYPE_INFO : LOG_TYPE_DEBUG), + .event = event, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + }; + va_list args; + + va_start(args, fmt); + sieve_global_logv(eenv->svinst, aenv->ehandler, ¶ms, fmt, args); + va_end(args); +} + + +#undef sieve_result_critical +void sieve_result_critical(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, unsigned int csrc_linenum, + const char *user_prefix, const char *fmt, ...) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_error_params params = { + .log_type = LOG_TYPE_ERROR, + .event = aenv->event, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + }; + va_list args; + + va_start(args, fmt); + + T_BEGIN { + sieve_criticalv(eenv->svinst, aenv->ehandler, ¶ms, + user_prefix, fmt, args); + } T_END; + + va_end(args); +} + +#undef sieve_result_mail_error +int sieve_result_mail_error(const struct sieve_action_exec_env *aenv, + struct mail *mail, + const char *csrc_filename, + unsigned int csrc_linenum, const char *fmt, ...) +{ + const char *error_msg, *user_prefix; + va_list args; + + error_msg = mailbox_get_last_internal_error(mail->box, NULL); + + va_start(args, fmt); + user_prefix = t_strdup_vprintf(fmt, args); + sieve_result_critical(aenv, csrc_filename, csrc_linenum, + user_prefix, "%s: %s", user_prefix, error_msg); + va_end(args); + + return SIEVE_EXEC_TEMP_FAILURE; +} diff --git a/pigeonhole/src/lib-sieve/sieve-result.h b/pigeonhole/src/lib-sieve/sieve-result.h new file mode 100644 index 0000000..a9fcadc --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-result.h @@ -0,0 +1,224 @@ +#ifndef SIEVE_RESULT_H +#define SIEVE_RESULT_H + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-execute.h" + +/* + * Types + */ + +struct sieve_side_effects_list; + +/* + * Result object + */ + +struct sieve_result; + +struct sieve_result * +sieve_result_create(struct sieve_instance *svinst, pool_t pool, + const struct sieve_execute_env *eenv); + +void sieve_result_ref(struct sieve_result *result); + +void sieve_result_unref(struct sieve_result **result); + +pool_t sieve_result_pool(struct sieve_result *result); + +/* + * Getters/Setters + */ + +const struct sieve_script_env * +sieve_result_get_script_env(struct sieve_result *result); +const struct sieve_message_data * +sieve_result_get_message_data(struct sieve_result *result); +struct sieve_message_context * +sieve_result_get_message_context(struct sieve_result *result); +unsigned int sieve_result_get_exec_seq(struct sieve_result *result); + +/* + * Extension support + */ + +void sieve_result_extension_set_context(struct sieve_result *result, + const struct sieve_extension *ext, + void *context); +const void * +sieve_result_extension_get_context(struct sieve_result *result, + const struct sieve_extension *ext); + +/* + * Result printing + */ + +struct sieve_result_print_env { + struct sieve_result *result; + const struct sieve_script_env *scriptenv; + struct ostream *stream; +}; + +void sieve_result_vprintf(const struct sieve_result_print_env *penv, + const char *fmt, va_list args) ATTR_FORMAT(2, 0); +void sieve_result_printf(const struct sieve_result_print_env *penv, + const char *fmt, ...) ATTR_FORMAT(2, 3); +void sieve_result_action_printf(const struct sieve_result_print_env *penv, + const char *fmt, ...) ATTR_FORMAT(2, 3); +void sieve_result_seffect_printf(const struct sieve_result_print_env *penv, + const char *fmt, ...) ATTR_FORMAT(2, 3); + +bool sieve_result_print(struct sieve_result *result, + const struct sieve_script_env *senv, + struct ostream *stream, bool *keep); + +/* + * Result composition + */ + +void sieve_result_add_implicit_side_effect( + struct sieve_result *result, const struct sieve_action_def *to_action, + bool to_keep, const struct sieve_extension *ext, + const struct sieve_side_effect_def *seffect, void *context); + +int sieve_result_add_action(const struct sieve_runtime_env *renv, + const struct sieve_extension *ext, const char *name, + const struct sieve_action_def *act_def, + struct sieve_side_effects_list *seffects, + void *context, unsigned int instance_limit, + bool preserve_mail); +int sieve_result_add_keep(const struct sieve_runtime_env *renv, + struct sieve_side_effects_list *seffects); + +void sieve_result_set_keep_action(struct sieve_result *result, + const struct sieve_extension *ext, + const struct sieve_action_def *act_def); +void sieve_result_set_failure_action(struct sieve_result *result, + const struct sieve_extension *ext, + const struct sieve_action_def *act_def); + +/* + * Result execution + */ + +struct sieve_result_execution; + +void sieve_result_mark_executed(struct sieve_result *result); + +struct sieve_result_execution * +sieve_result_execution_create(struct sieve_result *result, pool_t pool); +void sieve_result_execution_destroy(struct sieve_result_execution **_rexec); + +void *sieve_result_execution_get_dup_transaction( + struct sieve_result_execution *rexec); + +int sieve_result_execute(struct sieve_result_execution *rexec, int status, + bool commit, struct sieve_error_handler *ehandler, + bool *keep_r); + +bool sieve_result_executed(struct sieve_result_execution *rexec); +bool sieve_result_committed(struct sieve_result_execution *rexec); + +bool sieve_result_executed_delivery(struct sieve_result_execution *rexec); + +/* + * Result evaluation + */ + +struct sieve_result_iterate_context; + +struct sieve_result_iterate_context * +sieve_result_iterate_init(struct sieve_result *result); +const struct sieve_action * +sieve_result_iterate_next(struct sieve_result_iterate_context *rictx, + bool *keep); +void sieve_result_iterate_delete(struct sieve_result_iterate_context *rictx); + +/* + * Side effects list + */ + +struct sieve_side_effects_list * +sieve_side_effects_list_create(struct sieve_result *result); +void sieve_side_effects_list_add(struct sieve_side_effects_list *list, + const struct sieve_side_effect *seffect); + +/* + * Error handling + */ + +void sieve_result_error(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, unsigned int csrc_linenum, + const char *fmt, ...) + ATTR_FORMAT(4, 5); +#define sieve_result_error(aenv, ...) \ + sieve_result_error(aenv, __FILE__, __LINE__, __VA_ARGS__) +void sieve_result_global_error(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, + unsigned int csrc_linenum, const char *fmt, ...) + ATTR_FORMAT(4, 5); +#define sieve_result_global_error(aenv, ...) \ + sieve_result_global_error(aenv, __FILE__, __LINE__, __VA_ARGS__) +void sieve_result_warning(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, unsigned int csrc_linenum, + const char *fmt, ...) + ATTR_FORMAT(4, 5); +#define sieve_result_warning(aenv, ...) \ + sieve_result_warning(aenv, __FILE__, __LINE__, __VA_ARGS__) +void sieve_result_global_warning(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, + unsigned int csrc_linenum, + const char *fmt, ...) + ATTR_FORMAT(4, 5); +#define sieve_result_global_warning(aenv, ...) \ + sieve_result_global_warning(aenv, __FILE__, __LINE__, __VA_ARGS__) +void sieve_result_log(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, unsigned int csrc_linenum, + const char *fmt, ...) + ATTR_FORMAT(4, 5); +#define sieve_result_log(aenv, ...) \ + sieve_result_log(aenv, __FILE__, __LINE__, __VA_ARGS__) +void sieve_result_global_log(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, + unsigned int csrc_linenum, const char *fmt, ...) + ATTR_FORMAT(4, 5); +#define sieve_result_global_log(aenv, ...) \ + sieve_result_global_log(aenv, __FILE__, __LINE__, __VA_ARGS__) +void sieve_result_global_log_error(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, + unsigned int csrc_linenum, + const char *fmt, ...) + ATTR_FORMAT(4, 5); +#define sieve_result_global_log_error(aenv, ...) \ + sieve_result_global_log_error(aenv, __FILE__, __LINE__, __VA_ARGS__) +void sieve_result_global_log_warning(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, + unsigned int csrc_linenum, + const char *fmt, ...) + ATTR_FORMAT(4, 5); +#define sieve_result_global_log_warning(aenv, ...) \ + sieve_result_global_log_warning(aenv, __FILE__, __LINE__, __VA_ARGS__) + +void sieve_result_event_log(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, + unsigned int csrc_linenum, struct event *event, + const char *fmt, ...) ATTR_FORMAT(5, 0); +#define sieve_result_event_log(aenv, event, ...) \ + sieve_result_event_log(aenv, __FILE__, __LINE__, event, __VA_ARGS__) + +void sieve_result_critical(const struct sieve_action_exec_env *aenv, + const char *csrc_filename, unsigned int csrc_linenum, + const char *user_prefix, const char *fmt, ...) + ATTR_FORMAT(5, 6); +#define sieve_result_critical(aenv, ...) \ + sieve_result_critical(aenv, __FILE__, __LINE__, __VA_ARGS__) +int sieve_result_mail_error(const struct sieve_action_exec_env *aenv, + struct mail *mail, + const char *csrc_filename, + unsigned int csrc_linenum, const char *fmt, ...) + ATTR_FORMAT(5, 6); +#define sieve_result_mail_error(aenv, mail, ...) \ + sieve_result_mail_error(aenv, mail, __FILE__, __LINE__, __VA_ARGS__) + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-runtime-trace.c b/pigeonhole/src/lib-sieve/sieve-runtime-trace.c new file mode 100644 index 0000000..a9351a3 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-runtime-trace.c @@ -0,0 +1,151 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "ostream.h" + +#include "sieve-common.h" +#include "sieve-script.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-interpreter.h" +#include "sieve-runtime.h" +#include "sieve-runtime-trace.h" + +static inline string_t *_trace_line_new +(const struct sieve_runtime_env *renv, sieve_size_t address, unsigned int cmd_line) +{ + string_t *trline; + unsigned int i; + + trline = t_str_new(128); + if ( (renv->trace->config.flags & SIEVE_TRFLG_ADDRESSES) > 0 ) + str_printfa(trline, "%08llx: ", (unsigned long long) address); + if ( cmd_line > 0 ) + str_printfa(trline, "%4d: ", cmd_line); + else + str_append(trline, " "); + + for ( i = 0; i < renv->trace->indent; i++ ) + str_append(trline, " "); + + return trline; +} + +static inline void _trace_line_print +(string_t *trline, const struct sieve_runtime_env *renv) +{ + sieve_trace_log_write_line(renv->trace->log, trline); +} + +static inline void _trace_line_print_empty +(const struct sieve_runtime_env *renv) +{ + sieve_trace_log_write_line(renv->trace->log, NULL); +} + +/* + * Trace errors + */ + +void _sieve_runtime_trace_error +(const struct sieve_runtime_env *renv, const char *fmt, va_list args) +{ + string_t *trline = _trace_line_new(renv, renv->pc, 0); + + str_printfa(trline, "%s: #ERROR#: ", sieve_operation_mnemonic(renv->oprtn)); + str_vprintfa(trline, fmt, args); + + _trace_line_print(trline, renv); +} + +void _sieve_runtime_trace_operand_error +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + const char *fmt, va_list args) +{ + string_t *trline = _trace_line_new(renv, oprnd->address, + sieve_runtime_get_source_location(renv, oprnd->address)); + + str_printfa(trline, "%s: #ERROR#: ", sieve_operation_mnemonic(renv->oprtn)); + + if ( oprnd->field_name != NULL ) + str_printfa(trline, "%s: ", oprnd->field_name); + + str_vprintfa(trline, fmt, args); + + _trace_line_print(trline, renv); +} + +/* + * Trace info + */ + +static inline void ATTR_FORMAT(4, 0) _sieve_runtime_trace_vprintf +(const struct sieve_runtime_env *renv, sieve_size_t address, + unsigned int cmd_line, const char *fmt, va_list args) +{ + string_t *trline = _trace_line_new(renv, address, cmd_line); + + str_vprintfa(trline, fmt, args); + + _trace_line_print(trline, renv); +} + +static inline void ATTR_FORMAT(4, 5) _sieve_runtime_trace_printf +(const struct sieve_runtime_env *renv, sieve_size_t address, + unsigned int cmd_line, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + _sieve_runtime_trace_vprintf(renv, address, cmd_line, fmt, args); + va_end(args); +} + +void ATTR_FORMAT(2, 0) _sieve_runtime_trace +(const struct sieve_runtime_env *renv, const char *fmt, va_list args) +{ + _sieve_runtime_trace_vprintf + (renv, renv->oprtn->address, sieve_runtime_get_command_location(renv), + fmt, args); +} + +void _sieve_runtime_trace_address +(const struct sieve_runtime_env *renv, sieve_size_t address, + const char *fmt, va_list args) +{ + _sieve_runtime_trace_vprintf + (renv, address, sieve_runtime_get_source_location(renv, address), fmt, + args); +} + +/* + * Trace boundaries + */ + +void _sieve_runtime_trace_begin(const struct sieve_runtime_env *renv) +{ + const char *script_name = ( renv->script != NULL ? + sieve_script_name(renv->script) : sieve_binary_path(renv->sbin) ); + + _trace_line_print_empty(renv); + _sieve_runtime_trace_printf(renv, renv->pc, 0, + "## Started executing script '%s'", script_name); +} + +void _sieve_runtime_trace_end(const struct sieve_runtime_env *renv) +{ + const char *script_name = ( renv->script != NULL ? + sieve_script_name(renv->script) : sieve_binary_path(renv->sbin) ); + + _sieve_runtime_trace_printf(renv, renv->pc, 0, + "## Finished executing script '%s'", script_name); + _trace_line_print_empty(renv); +} + +void _sieve_runtime_trace_sep(const struct sieve_runtime_env *renv) +{ + _trace_line_print_empty(renv); +} + diff --git a/pigeonhole/src/lib-sieve/sieve-runtime-trace.h b/pigeonhole/src/lib-sieve/sieve-runtime-trace.h new file mode 100644 index 0000000..b165586 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-runtime-trace.h @@ -0,0 +1,182 @@ +#ifndef SIEVE_RUNTIME_TRACE_H +#define SIEVE_RUNTIME_TRACE_H + +#include "sieve-common.h" +#include "sieve-runtime.h" + +/* + * Runtime trace + */ + +struct sieve_runtime_trace { + struct sieve_trace_config config; + struct sieve_trace_log *log; + unsigned int indent; +}; + +/* Trace configuration */ + +static inline bool sieve_runtime_trace_active +(const struct sieve_runtime_env *renv, sieve_trace_level_t trace_level) +{ + return ( renv->trace != NULL && trace_level <= renv->trace->config.level ); +} + +static inline bool sieve_runtime_trace_hasflag +(const struct sieve_runtime_env *renv, unsigned int flag) +{ + return ( renv->trace != NULL && (renv->trace->config.flags & flag) != 0 ); +} + +/* Trace indent */ + +static inline void sieve_runtime_trace_descend +(const struct sieve_runtime_env *renv) +{ + if ( renv->trace != NULL ) renv->trace->indent++; +} + +static inline void sieve_runtime_trace_ascend +(const struct sieve_runtime_env *renv) +{ + if ( renv->trace != NULL ) renv->trace->indent--; +} + +static inline void sieve_runtime_trace_toplevel +(const struct sieve_runtime_env *renv) +{ + if ( renv->trace != NULL ) renv->trace->indent = 0; +} + +/* Trace errors */ + +void _sieve_runtime_trace_error + (const struct sieve_runtime_env *renv, const char *fmt, va_list args) + ATTR_FORMAT(2, 0); + +void _sieve_runtime_trace_operand_error + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + const char *fmt, va_list args) ATTR_FORMAT(3, 0); + +static inline void sieve_runtime_trace_error + (const struct sieve_runtime_env *renv, const char *fmt, ...) + ATTR_FORMAT(2, 3); + +static inline void sieve_runtime_trace_operand_error + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + const char *fmt, ...) ATTR_FORMAT(3, 4); + +static inline void ATTR_FORMAT(2, 3) sieve_runtime_trace_error + (const struct sieve_runtime_env *renv, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + if ( renv->trace != NULL ) + _sieve_runtime_trace_error(renv, fmt, args); + va_end(args); +} + +static inline void ATTR_FORMAT(3, 4) sieve_runtime_trace_operand_error + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + if ( renv->trace != NULL ) + _sieve_runtime_trace_operand_error(renv, oprnd, fmt, args); + va_end(args); +} + +/* Trace info */ + +void _sieve_runtime_trace + (const struct sieve_runtime_env *renv, const char *fmt, va_list args) + ATTR_FORMAT(2, 0); + +static inline void sieve_runtime_trace + (const struct sieve_runtime_env *renv, sieve_trace_level_t trace_level, + const char *fmt, ...) ATTR_FORMAT(3, 4); + +static inline void ATTR_FORMAT(3, 4) sieve_runtime_trace +(const struct sieve_runtime_env *renv, sieve_trace_level_t trace_level, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + + if ( renv->trace != NULL && trace_level <= renv->trace->config.level ) { + _sieve_runtime_trace(renv, fmt, args); + } + + va_end(args); +} + +void _sieve_runtime_trace_address + (const struct sieve_runtime_env *renv, sieve_size_t address, + const char *fmt, va_list args) ATTR_FORMAT(3, 0); + +static inline void sieve_runtime_trace_address + (const struct sieve_runtime_env *renv, sieve_trace_level_t trace_level, + sieve_size_t address, const char *fmt, ...) ATTR_FORMAT(4, 5); + +static inline void ATTR_FORMAT(4, 5) sieve_runtime_trace_address +(const struct sieve_runtime_env *renv, sieve_trace_level_t trace_level, + sieve_size_t address, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + + if ( renv->trace != NULL && trace_level <= renv->trace->config.level ) { + _sieve_runtime_trace_address(renv, address, fmt, args); + } + + va_end(args); +} + +static inline void ATTR_FORMAT(3, 4) sieve_runtime_trace_here +(const struct sieve_runtime_env *renv, sieve_trace_level_t trace_level, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + + if ( renv->trace != NULL && trace_level <= renv->trace->config.level ) { + _sieve_runtime_trace_address(renv, renv->pc, fmt, args); + } + + va_end(args); +} + +/* Trace boundaries */ + +void _sieve_runtime_trace_begin(const struct sieve_runtime_env *renv); +void _sieve_runtime_trace_end(const struct sieve_runtime_env *renv); +void _sieve_runtime_trace_sep(const struct sieve_runtime_env *renv); + +static inline void sieve_runtime_trace_begin +(const struct sieve_runtime_env *renv) +{ + if ( renv->trace != NULL ) + _sieve_runtime_trace_begin(renv); +} + +static inline void sieve_runtime_trace_end +(const struct sieve_runtime_env *renv) +{ + if ( renv->trace != NULL ) + _sieve_runtime_trace_end(renv); +} + +static inline void sieve_runtime_trace_sep +(const struct sieve_runtime_env *renv) +{ + if ( renv->trace != NULL ) + _sieve_runtime_trace_sep(renv); +} + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-runtime.h b/pigeonhole/src/lib-sieve/sieve-runtime.h new file mode 100644 index 0000000..fa50602 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-runtime.h @@ -0,0 +1,40 @@ +#ifndef SIEVE_RUNTIME_H +#define SIEVE_RUNTIME_H + +#include "sieve-common.h" +#include "sieve-execute.h" + +/* + * Runtime environment + */ + +struct sieve_runtime_env { + const struct sieve_execute_env *exec_env; + struct event *event; + + /* Interpreter */ + struct sieve_interpreter *interp; + struct sieve_error_handler *ehandler; + + /* Executing script */ + struct sieve_script *script; + + /* Executing binary */ + struct sieve_binary *sbin; + struct sieve_binary_block *sblock; + + /* Current code */ + sieve_size_t pc; + const struct sieve_operation *oprtn; + + /* Tested message */ + struct sieve_message_context *msgctx; + + /* Filter result */ + struct sieve_result *result; + + /* Runtime tracing */ + struct sieve_runtime_trace *trace; +}; + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-script-private.h b/pigeonhole/src/lib-sieve/sieve-script-private.h new file mode 100644 index 0000000..7f23c19 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-script-private.h @@ -0,0 +1,100 @@ +#ifndef SIEVE_SCRIPT_PRIVATE_H +#define SIEVE_SCRIPT_PRIVATE_H + +#include "sieve-common.h" +#include "sieve-script.h" + +/* + * Script object + */ + +struct sieve_script_vfuncs { + void (*destroy)(struct sieve_script *script); + + int (*open)(struct sieve_script *script, enum sieve_error *error_r); + + int (*get_stream)(struct sieve_script *script, + struct istream **stream_r, enum sieve_error *error_r); + + /* binary */ + int (*binary_read_metadata)(struct sieve_script *_script, + struct sieve_binary_block *sblock, + sieve_size_t *offset); + void (*binary_write_metadata)(struct sieve_script *script, + struct sieve_binary_block *sblock); + bool (*binary_dump_metadata)(struct sieve_script *script, + struct sieve_dumptime_env *denv, + struct sieve_binary_block *sblock, + sieve_size_t *offset); + struct sieve_binary *(*binary_load)(struct sieve_script *script, + enum sieve_error *error_r); + int (*binary_save)(struct sieve_script *script, + struct sieve_binary *sbin, bool update, + enum sieve_error *error_r); + const char *(*binary_get_prefix)(struct sieve_script *script); + + /* management */ + int (*rename)(struct sieve_script *script, const char *newname); + int (*delete)(struct sieve_script *script); + int (*is_active)(struct sieve_script *script); + int (*activate)(struct sieve_script *script); + + /* properties */ + int (*get_size)(const struct sieve_script *script, uoff_t *size_r); + + /* matching */ + bool (*equals)(const struct sieve_script *script, + const struct sieve_script *other); +}; + +struct sieve_script { + pool_t pool; + unsigned int refcount; + struct sieve_storage *storage; + struct event *event; + + const char *driver_name; + const struct sieve_script *script_class; + struct sieve_script_vfuncs v; + + const char *name; + const char *location; + + /* Stream */ + struct istream *stream; + + bool open:1; +}; + +void sieve_script_init(struct sieve_script *script, + struct sieve_storage *storage, + const struct sieve_script *script_class, + const char *location, const char *name); + +/* + * Built-in script drivers + */ + +extern const struct sieve_script sieve_data_script; +extern const struct sieve_script sieve_file_script; +extern const struct sieve_script sieve_dict_script; +extern const struct sieve_script sieve_ldap_script; + +/* + * Error handling + */ + +void sieve_script_set_error(struct sieve_script *script, enum sieve_error error, + const char *fmt, ...) ATTR_FORMAT(3, 4); +void sieve_script_set_internal_error(struct sieve_script *script); +void sieve_script_set_critical(struct sieve_script *script, + const char *fmt, ...) ATTR_FORMAT(2, 3); + +/* + * Script sequence + */ + +void sieve_script_sequence_init(struct sieve_script_sequence *seq, + struct sieve_storage *storage); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-script.c b/pigeonhole/src/lib-sieve/sieve-script.c new file mode 100644 index 0000000..32963a0 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-script.c @@ -0,0 +1,906 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "compat.h" +#include "unichar.h" +#include "str.h" +#include "str-sanitize.h" +#include "hash.h" +#include "array.h" +#include "eacces-error.h" +#include "istream.h" + +#include "sieve-common.h" +#include "sieve-limits.h" +#include "sieve-settings.h" +#include "sieve-error.h" +#include "sieve-dump.h" +#include "sieve-binary.h" + +#include "sieve-storage-private.h" +#include "sieve-script-private.h" + +/* + * Script name + */ + +bool sieve_script_name_is_valid(const char *scriptname) +{ + ARRAY_TYPE(unichars) uni_name; + unsigned int count, i; + const unichar_t *name_chars; + size_t namelen = strlen(scriptname); + + /* Check minimum length */ + if (namelen == 0) + return FALSE; + + /* Check worst-case maximum length */ + if (namelen > SIEVE_MAX_SCRIPT_NAME_LEN * 4) + return FALSE; + + /* Intialize array for unicode characters */ + t_array_init(&uni_name, namelen * 4); + + /* Convert UTF-8 to UCS4/UTF-32 */ + if (uni_utf8_to_ucs4(scriptname, &uni_name) < 0) + return FALSE; + name_chars = array_get(&uni_name, &count); + + /* Check true maximum length */ + if (count > SIEVE_MAX_SCRIPT_NAME_LEN) + return FALSE; + + /* Scan name for invalid characters + * FIXME: compliance with Net-Unicode Definition (Section 2 of + * RFC 5198) is not checked fully and no normalization + * is performed. + */ + for (i = 0; i < count; i++) { + /* 0000-001F; [CONTROL CHARACTERS] */ + if (name_chars[i] <= 0x001f) + return FALSE; + /* 002F; SLASH (not RFC-prohibited, but '/' is dangerous) */ + if (name_chars[i] == 0x002f) + return FALSE; + /* 007F; DELETE */ + if (name_chars[i] == 0x007f) + return FALSE; + /* 0080-009F; [CONTROL CHARACTERS] */ + if (name_chars[i] >= 0x0080 && name_chars[i] <= 0x009f) + return FALSE; + /* 00FF */ + if (name_chars[i] == 0x00ff) + return FALSE; + /* 2028; LINE SEPARATOR */ + /* 2029; PARAGRAPH SEPARATOR */ + if (name_chars[i] == 0x2028 || name_chars[i] == 0x2029) + return FALSE; + } + + return TRUE; +} + +/* + * Script instance + */ + +void sieve_script_init(struct sieve_script *script, + struct sieve_storage *storage, + const struct sieve_script *script_class, + const char *location, const char *name) +{ + i_assert(storage != NULL); + + script->script_class = script_class; + script->refcount = 1; + script->storage = storage; + script->location = p_strdup_empty(script->pool, location); + script->name = p_strdup(script->pool, name); + + script->event = event_create(storage->event); + event_add_str(script->event, "script_name", name); + event_add_str(script->event, "script_location", location); + if (name == NULL) + event_set_append_log_prefix(script->event, "script: "); + else { + event_set_append_log_prefix( + script->event, t_strdup_printf("script `%s': ", name)); + } + + sieve_storage_ref(storage); +} + +struct sieve_script * +sieve_script_create(struct sieve_instance *svinst, const char *location, + const char *name, enum sieve_error *error_r) +{ + struct sieve_storage *storage; + struct sieve_script *script; + enum sieve_error error; + + if (error_r != NULL) + *error_r = SIEVE_ERROR_NONE; + else + error_r = &error; + + storage = sieve_storage_create(svinst, location, 0, error_r); + if (storage == NULL) + return NULL; + + script = sieve_storage_get_script(storage, name, error_r); + + sieve_storage_unref(&storage); + return script; +} + +void sieve_script_ref(struct sieve_script *script) +{ + script->refcount++; +} + +void sieve_script_unref(struct sieve_script **_script) +{ + struct sieve_script *script = *_script; + + *_script = NULL; + + if (script == NULL) + return; + + i_assert(script->refcount > 0); + if (--script->refcount != 0) + return; + + if (script->stream != NULL) { + struct event_passthrough *e = + event_create_passthrough(script->event)-> + set_name("sieve_script_closed"); + e_debug(e->event(), "Closed script"); + } + i_stream_unref(&script->stream); + + if (script->v.destroy != NULL) + script->v.destroy(script); + + sieve_storage_unref(&script->storage); + event_unref(&script->event); + pool_unref(&script->pool); +} + +int sieve_script_open(struct sieve_script *script, enum sieve_error *error_r) +{ + enum sieve_error error; + + if (error_r != NULL) + *error_r = SIEVE_ERROR_NONE; + else + error_r = &error; + + if (script->open) + return 0; + + if (script->v.open(script, error_r) < 0) + return -1; + + i_assert(script->location != NULL); + i_assert(script->name != NULL); + script->open = TRUE; + + if (*script->name != '\0') { + e_debug(script->event, "Opened script `%s' from `%s'", + script->name, script->location); + } else { + e_debug(script->event, "Opened nameless script from `%s'", + script->location); + } + return 0; +} + +int sieve_script_open_as(struct sieve_script *script, const char *name, + enum sieve_error *error_r) +{ + if (sieve_script_open(script, error_r) < 0) + return -1; + + /* override name */ + script->name = p_strdup(script->pool, name); + event_add_str(script->event, "script_name", name); + return 0; +} + +struct sieve_script * +sieve_script_create_open(struct sieve_instance *svinst, const char *location, + const char *name, enum sieve_error *error_r) +{ + struct sieve_script *script; + + script = sieve_script_create(svinst, location, name, error_r); + if (script == NULL) + return NULL; + + if (sieve_script_open(script, error_r) < 0) { + sieve_script_unref(&script); + return NULL; + } + + return script; +} + +int sieve_script_check(struct sieve_instance *svinst, const char *location, + const char *name, enum sieve_error *error_r) +{ + struct sieve_script *script; + enum sieve_error error; + + if (error_r == NULL) + error_r = &error; + + script = sieve_script_create_open(svinst, location, name, error_r); + if (script == NULL) + return (*error_r == SIEVE_ERROR_NOT_FOUND ? 0 : -1); + + sieve_script_unref(&script); + return 1; +} + +/* + * Properties + */ + +const char *sieve_script_name(const struct sieve_script *script) +{ + return script->name; +} + +const char *sieve_script_location(const struct sieve_script *script) +{ + return script->location; +} + +struct sieve_instance *sieve_script_svinst(const struct sieve_script *script) +{ + return script->storage->svinst; +} + +int sieve_script_get_size(struct sieve_script *script, uoff_t *size_r) +{ + struct istream *stream; + int ret; + + if (script->v.get_size != NULL) { + if ((ret = script->v.get_size(script, size_r)) != 0) + return ret; + } + + /* Try getting size from the stream */ + if (script->stream == NULL && + sieve_script_get_stream(script, &stream, NULL) < 0) + return -1; + + if (i_stream_get_size(script->stream, TRUE, size_r) < 0) { + sieve_storage_set_critical(script->storage, + "i_stream_get_size(%s) failed: %s", + i_stream_get_name(script->stream), + i_stream_get_error(script->stream)); + return -1; + } + return 0; +} + +bool sieve_script_is_open(const struct sieve_script *script) +{ + return script->open; +} + +bool sieve_script_is_default(const struct sieve_script *script) +{ + return script->storage->is_default; +} + +/* + * Stream management + */ + +int sieve_script_get_stream(struct sieve_script *script, + struct istream **stream_r, + enum sieve_error *error_r) +{ + struct sieve_storage *storage = script->storage; + enum sieve_error error; + int ret; + + if (error_r != NULL) + *error_r = SIEVE_ERROR_NONE; + else + error_r = &error; + + if (script->stream != NULL) { + *stream_r = script->stream; + return 0; + } + + // FIXME: necessary? + i_assert(script->open); + + T_BEGIN { + ret = script->v.get_stream(script, &script->stream, error_r); + } T_END; + + if (ret < 0) { + struct event_passthrough *e = + event_create_passthrough(script->event)-> + add_str("error", storage->error)-> + set_name("sieve_script_opened"); + e_debug(e->event(), "Failed to open script for reading: %s", + storage->error); + return -1; + } + + struct event_passthrough *e = + event_create_passthrough(script->event)-> + set_name("sieve_script_opened"); + e_debug(e->event(), "Opened script for reading"); + + *stream_r = script->stream; + return 0; +} + +/* + * Comparison + */ + +bool sieve_script_equals(const struct sieve_script *script, + const struct sieve_script *other) +{ + if (script == other) + return TRUE; + if (script == NULL || other == NULL) + return FALSE; + if (script->script_class != other->script_class) + return FALSE; + + if (script->v.equals == NULL) { + i_assert (script->location != NULL && other->location != NULL); + + return (strcmp(script->location, other->location) == 0); + } + + return script->v.equals(script, other); +} + +unsigned int sieve_script_hash(const struct sieve_script *script) +{ + i_assert(script->name != NULL); + + return str_hash(script->name); +} + +/* + * Binary + */ + +int sieve_script_binary_read_metadata(struct sieve_script *script, + struct sieve_binary_block *sblock, + sieve_size_t *offset) +{ + struct sieve_binary *sbin = sieve_binary_block_get_binary(sblock); + string_t *storage_class, *location; + unsigned int version; + + if ((sieve_binary_block_get_size(sblock) - *offset) == 0) + return 0; + + /* storage class */ + if (!sieve_binary_read_string(sblock, offset, &storage_class)) { + e_error(script->event, + "Binary `%s' has invalid metadata for script `%s': " + "Invalid storage class", + sieve_binary_path(sbin), script->location); + return -1; + } + if (strcmp(str_c(storage_class), script->driver_name) != 0) { + e_debug(script->event, + "Binary `%s' reports unexpected driver name for script `%s' " + "(`%s' rather than `%s')", + sieve_binary_path(sbin), script->location, + str_c(storage_class), script->driver_name); + return 0; + } + + /* version */ + if (!sieve_binary_read_unsigned(sblock, offset, &version)) { + e_error(script->event, + "Binary `%s' has invalid metadata for script `%s': " + "Invalid version", + sieve_binary_path(sbin), script->location); + return -1; + } + if (script->storage->version != version) { + e_debug(script->event, + "Binary `%s' was compiled with " + "a different version of the `%s' script storage class " + "(compiled v%d, expected v%d; " + "automatically fixed when re-compiled)", + sieve_binary_path(sbin), script->driver_name, + version, script->storage->version); + return 0; + } + + /* location */ + if (!sieve_binary_read_string(sblock, offset, &location)) { + e_error(script->event, + "Binary `%s' has invalid metadata for script `%s': " + "Invalid location", + sieve_binary_path(sbin), script->location); + return -1; + } + i_assert(script->location != NULL); + if (strcmp(str_c(location), script->location) != 0) { + e_debug(script->event, + "Binary `%s' reports different location " + "for script `%s' (binary points to `%s')", + sieve_binary_path(sbin), script->location, + str_c(location)); + return 0; + } + + if (script->v.binary_read_metadata == NULL) + return 1; + + return script->v.binary_read_metadata(script, sblock, offset); +} + +void sieve_script_binary_write_metadata(struct sieve_script *script, + struct sieve_binary_block *sblock) +{ + sieve_binary_emit_cstring(sblock, script->driver_name); + sieve_binary_emit_unsigned(sblock, script->storage->version); + sieve_binary_emit_cstring(sblock, (script->location == NULL ? + "" : script->location)); + + if (script->v.binary_write_metadata == NULL) + return; + + script->v.binary_write_metadata(script, sblock); +} + +bool sieve_script_binary_dump_metadata(struct sieve_script *script, + struct sieve_dumptime_env *denv, + struct sieve_binary_block *sblock, + sieve_size_t *offset) +{ + struct sieve_binary *sbin = sieve_binary_block_get_binary(sblock); + struct sieve_instance *svinst = sieve_binary_svinst(sbin); + string_t *storage_class, *location; + struct sieve_script *adhoc_script = NULL; + unsigned int version; + bool result = TRUE; + + /* storage class */ + if (!sieve_binary_read_string(sblock, offset, &storage_class)) + return FALSE; + sieve_binary_dumpf(denv, "class = %s\n", str_c(storage_class)); + + /* version */ + if (!sieve_binary_read_unsigned(sblock, offset, &version)) + return FALSE; + sieve_binary_dumpf(denv, "class.version = %d\n", version); + + /* location */ + if (!sieve_binary_read_string(sblock, offset, &location)) + return FALSE; + sieve_binary_dumpf(denv, "location = %s\n", str_c(location)); + + if (script == NULL) { + script = adhoc_script = + sieve_script_create(svinst, str_c(location), + NULL, NULL); + } + + if (script != NULL && script->v.binary_dump_metadata != NULL) { + result = script->v.binary_dump_metadata( + script, denv, sblock, offset); + } + + if (adhoc_script != NULL) + sieve_script_unref(&adhoc_script); + return result; +} + +struct sieve_binary * +sieve_script_binary_load(struct sieve_script *script, enum sieve_error *error_r) +{ + if (script->v.binary_load == NULL) { + *error_r = SIEVE_ERROR_NOT_POSSIBLE; + return NULL; + } + + return script->v.binary_load(script, error_r); +} + +int sieve_script_binary_save(struct sieve_script *script, + struct sieve_binary *sbin, bool update, + enum sieve_error *error_r) +{ + struct sieve_script *bin_script = sieve_binary_script(sbin); + enum sieve_error error; + + if (error_r != NULL) + *error_r = SIEVE_ERROR_NONE; + else + error_r = &error; + + i_assert(bin_script == NULL || sieve_script_equals(bin_script, script)); + + if (script->v.binary_save == NULL) { + *error_r = SIEVE_ERROR_NOT_POSSIBLE; + return -1; + } + + return script->v.binary_save(script, sbin, update, error_r); +} + +const char *sieve_script_binary_get_prefix(struct sieve_script *script) +{ + struct sieve_storage *storage = script->storage; + + if (storage->bin_dir != NULL && + sieve_storage_setup_bindir(storage, 0700) >= 0) { + return t_strconcat(storage->bin_dir, "/", script->name, NULL); + } + + if (script->v.binary_get_prefix == NULL) + return NULL; + + return script->v.binary_get_prefix(script); +} + +/* + * Management + */ + +static int +sieve_script_copy_from_default(struct sieve_script *script, const char *newname) +{ + struct sieve_storage *storage = script->storage; + struct istream *input; + int ret; + + /* copy from default */ + if ((ret = sieve_script_open(script, NULL)) < 0 || + (ret = sieve_script_get_stream(script, &input, NULL)) < 0) { + sieve_storage_copy_error(storage->default_for, storage); + return ret; + } + + ret = sieve_storage_save_as(storage->default_for, input, newname); + if (ret < 0) { + sieve_storage_copy_error(storage, storage->default_for); + } else if (sieve_script_is_active(script) > 0) { + struct sieve_script *newscript; + enum sieve_error error; + + newscript = sieve_storage_open_script(storage->default_for, + newname, &error); + if (newscript == NULL) { + /* Somehow not actually saved */ + ret = (error == SIEVE_ERROR_NOT_FOUND ? 0 : -1); + } else if (sieve_script_activate(newscript, (time_t)-1) < 0) { + /* Failed to activate; roll back */ + ret = -1; + (void)sieve_script_delete(newscript, TRUE); + } + if (newscript != NULL) + sieve_script_unref(&newscript); + + if (ret < 0) { + e_error(storage->event, + "Failed to implicitly activate script `%s' " + "after rename", newname); + sieve_storage_copy_error(storage->default_for, storage); + } + } + + return ret; +} + +int sieve_script_rename(struct sieve_script *script, const char *newname) +{ + struct sieve_storage *storage = script->storage; + const char *oldname = script->name; + struct event_passthrough *event; + int ret; + + i_assert(newname != NULL); + + /* Check script name */ + if (!sieve_script_name_is_valid(newname)) { + sieve_script_set_error(script, + SIEVE_ERROR_BAD_PARAMS, + "Invalid new Sieve script name `%s'.", + str_sanitize(newname, 80)); + return -1; + } + + i_assert(script->open); // FIXME: auto-open? + + if (storage->default_for == NULL) { + i_assert((storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0); + + /* rename script */ + i_assert(script->v.rename != NULL); + ret = script->v.rename(script, newname); + + /* rename INBOX mailbox attribute */ + if (ret >= 0 && oldname != NULL) { + (void)sieve_storage_sync_script_rename(storage, oldname, + newname); + } + } else if (sieve_storage_check_script(storage->default_for, + newname, NULL) > 0) { + sieve_script_set_error(script, SIEVE_ERROR_EXISTS, + "A sieve script with that name already exists."); + sieve_storage_copy_error(storage->default_for, storage); + ret = -1; + } else { + ret = sieve_script_copy_from_default(script, newname); + } + + event = event_create_passthrough(script->event)-> + clear_field("script_name")-> + add_str("old_script_name", script->name)-> + add_str("new_script_name", newname)-> + set_name("sieve_script_renamed"); + + if (ret >= 0) { + e_debug(event->event(), "Script renamed to `%s'", newname); + } else { + event = event->add_str("error", storage->error); + + e_debug(event->event(), "Failed to rename script: %s", + storage->error); + } + + return ret; +} + +int sieve_script_delete(struct sieve_script *script, bool ignore_active) +{ + struct sieve_storage *storage = script->storage; + bool is_active = FALSE; + int ret = 0; + + i_assert(script->open); // FIXME: auto-open? + + /* Is the requested script active? */ + if (sieve_script_is_active(script) > 0) { + is_active = TRUE; + if (!ignore_active) { + sieve_script_set_error(script, SIEVE_ERROR_ACTIVE, + "Cannot delete the active Sieve script."); + if (storage->default_for != NULL) { + sieve_storage_copy_error(storage->default_for, + storage); + } + return -1; + } + } + + /* Trying to delete the default script? */ + if (storage->is_default) { + /* ignore */ + return 0; + } + + i_assert((script->storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0); + + /* Deactivate it explicity */ + if (ignore_active && is_active) + (void)sieve_storage_deactivate(storage, (time_t)-1); + + i_assert(script->v.delete != NULL); + ret = script->v.delete(script); + + if (ret >= 0) { + struct event_passthrough *e = + event_create_passthrough(script->event)-> + set_name("sieve_script_deleted"); + e_debug(e->event(), "Script deleted"); + + /* unset INBOX mailbox attribute */ + (void)sieve_storage_sync_script_delete(storage, script->name); + } else { + struct event_passthrough *e = + event_create_passthrough(script->event)-> + add_str("error", storage->error)-> + set_name("sieve_script_deleted"); + e_debug(e->event(), "Failed to delete script: %s", + storage->error); + } + return ret; +} + +int sieve_script_is_active(struct sieve_script *script) +{ + struct sieve_storage *storage = script->storage; + + /* Special handling if this is a default script */ + if (storage->default_for != NULL) { + int ret = sieve_storage_active_script_is_default( + storage->default_for); + if (ret < 0) + sieve_storage_copy_error(storage, storage->default_for); + return ret; + } + + if (script->v.is_active == NULL) + return 0; + return script->v.is_active(script); +} + +int sieve_script_activate(struct sieve_script *script, time_t mtime) +{ + struct sieve_storage *storage = script->storage; + int ret = 0; + + i_assert(script->open); // FIXME: auto-open? + + if (storage->default_for == NULL) { + i_assert((storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0); + + i_assert(script->v.activate != NULL); + ret = script->v.activate(script); + + if (ret >= 0) { + struct event_passthrough *e = + event_create_passthrough(script->event)-> + set_name("sieve_script_activated"); + e_debug(e->event(), "Script activated"); + + sieve_storage_set_modified(storage, mtime); + (void)sieve_storage_sync_script_activate(storage); + } else { + struct event_passthrough *e = + event_create_passthrough(script->event)-> + add_str("error", storage->error)-> + set_name("sieve_script_activated"); + e_debug(e->event(), "Failed to activate script: %s", + storage->error); + } + + } else { + /* Activating the default script is equal to deactivating + the storage */ + ret = sieve_storage_deactivate(storage->default_for, + (time_t)-1); + if (ret < 0) + sieve_storage_copy_error(storage, storage->default_for); + } + + return ret; +} + +/* + * Error handling + */ + +void sieve_script_set_error(struct sieve_script *script, enum sieve_error error, + const char *fmt, ...) +{ + struct sieve_storage *storage = script->storage; + va_list va; + + sieve_storage_clear_error(storage); + + if (fmt != NULL) { + va_start(va, fmt); + storage->error = i_strdup_vprintf(fmt, va); + va_end(va); + } + storage->error_code = error; +} + +void sieve_script_set_internal_error(struct sieve_script *script) +{ + sieve_storage_set_internal_error(script->storage); +} + +void sieve_script_set_critical(struct sieve_script *script, + const char *fmt, ...) +{ + struct sieve_storage *storage = script->storage; + + va_list va; + + if (fmt != NULL) { + if ((storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0) { + va_start(va, fmt); + e_error(script->event, "%s", t_strdup_vprintf(fmt, va)); + va_end(va); + + sieve_storage_set_internal_error(storage); + + } else { + sieve_storage_clear_error(storage); + + /* no user is involved while synchronizing, so do it the + normal way */ + va_start(va, fmt); + storage->error = i_strdup_vprintf(fmt, va); + va_end(va); + + storage->error_code = SIEVE_ERROR_TEMP_FAILURE; + } + } +} + +const char * +sieve_script_get_last_error(struct sieve_script *script, + enum sieve_error *error_r) +{ + return sieve_storage_get_last_error(script->storage, error_r); +} + +const char *sieve_script_get_last_error_lcase(struct sieve_script *script) +{ + return sieve_error_from_external(script->storage->error); +} + +/* + * Script sequence + */ + +void sieve_script_sequence_init(struct sieve_script_sequence *seq, + struct sieve_storage *storage) +{ + seq->storage = storage; + sieve_storage_ref(storage); +} + +struct sieve_script_sequence * +sieve_script_sequence_create(struct sieve_instance *svinst, + const char *location, enum sieve_error *error_r) +{ + struct sieve_storage *storage; + struct sieve_script_sequence *seq; + enum sieve_error error; + + if (error_r != NULL) + *error_r = SIEVE_ERROR_NONE; + else + error_r = &error; + + storage = sieve_storage_create(svinst, location, 0, error_r); + if (storage == NULL) + return NULL; + + seq = sieve_storage_get_script_sequence(storage, error_r); + + sieve_storage_unref(&storage); + return seq; +} + +struct sieve_script * +sieve_script_sequence_next(struct sieve_script_sequence *seq, + enum sieve_error *error_r) +{ + struct sieve_storage *storage = seq->storage; + + i_assert(storage->v.script_sequence_next != NULL); + return storage->v.script_sequence_next(seq, error_r); +} + +void sieve_script_sequence_free(struct sieve_script_sequence **_seq) +{ + struct sieve_script_sequence *seq = *_seq; + struct sieve_storage *storage = seq->storage; + + if (storage->v.script_sequence_destroy != NULL) + storage->v.script_sequence_destroy(seq); + + sieve_storage_unref(&storage); + *_seq = NULL; +} + diff --git a/pigeonhole/src/lib-sieve/sieve-script.h b/pigeonhole/src/lib-sieve/sieve-script.h new file mode 100644 index 0000000..8ee53f4 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-script.h @@ -0,0 +1,163 @@ +#ifndef SIEVE_SCRIPT_H +#define SIEVE_SCRIPT_H + +#include "sieve-common.h" + +#include <sys/types.h> + + +/* + * Sieve script name + */ + +bool sieve_script_name_is_valid(const char *scriptname); + +/* + * Sieve script file + */ + +bool sieve_script_file_has_extension(const char *filename); + +/* + * Sieve script class + */ + +void sieve_script_class_register(struct sieve_instance *svinst, + const struct sieve_script *script_class); +void sieve_script_class_unregister(struct sieve_instance *svinst, + const struct sieve_script *script_class); + +/* + * Sieve script instance + */ + +struct sieve_script; + +ARRAY_DEFINE_TYPE(sieve_script, struct sieve_script *); + +struct sieve_script * +sieve_script_create(struct sieve_instance *svinst, const char *location, + const char *name, enum sieve_error *error_r) ATTR_NULL(3,4); + +void sieve_script_ref(struct sieve_script *script); +void sieve_script_unref(struct sieve_script **script); + +int sieve_script_open(struct sieve_script *script, enum sieve_error *error_r) + ATTR_NULL(2); +int sieve_script_open_as(struct sieve_script *script, const char *name, + enum sieve_error *error_r) ATTR_NULL(3); + +struct sieve_script * +sieve_script_create_open(struct sieve_instance *svinst, const char *location, + const char *name, enum sieve_error *error_r) + ATTR_NULL(3, 4); +int sieve_script_check(struct sieve_instance *svinst, const char *location, + const char *name, enum sieve_error *error_r) + ATTR_NULL(3, 4); + +/* + * Data script + */ + +struct sieve_script * +sieve_data_script_create_from_input(struct sieve_instance *svinst, + const char *name, struct istream *input); + +/* + * Binary + */ + +int sieve_script_binary_read_metadata(struct sieve_script *script, + struct sieve_binary_block *sblock, + sieve_size_t *offset); +void sieve_script_binary_write_metadata(struct sieve_script *script, + struct sieve_binary_block *sblock); +bool sieve_script_binary_dump_metadata(struct sieve_script *script, + struct sieve_dumptime_env *denv, + struct sieve_binary_block *sblock, + sieve_size_t *offset) ATTR_NULL(1); + +struct sieve_binary * +sieve_script_binary_load(struct sieve_script *script, + enum sieve_error *error_r); +int sieve_script_binary_save(struct sieve_script *script, + struct sieve_binary *sbin, bool update, + enum sieve_error *error_r) ATTR_NULL(4); + +const char *sieve_script_binary_get_prefix(struct sieve_script *script); + +/* + * Stream management + */ + +int sieve_script_get_stream(struct sieve_script *script, + struct istream **stream_r, + enum sieve_error *error_r) ATTR_NULL(3); + +/* + * Management + */ + +// FIXME: check read/write flag! + +int sieve_script_rename(struct sieve_script *script, const char *newname); +int sieve_script_is_active(struct sieve_script *script); +int sieve_script_activate(struct sieve_script *script, time_t mtime); +int sieve_script_delete(struct sieve_script *script, bool ignore_active); + +/* + * Properties + */ + +const char *sieve_script_name(const struct sieve_script *script) ATTR_PURE; +const char *sieve_script_location(const struct sieve_script *script) ATTR_PURE; +struct sieve_instance * +sieve_script_svinst(const struct sieve_script *script) ATTR_PURE; + +int sieve_script_get_size(struct sieve_script *script, uoff_t *size_r); +bool sieve_script_is_open(const struct sieve_script *script) ATTR_PURE; +bool sieve_script_is_default(const struct sieve_script *script) ATTR_PURE; + +const char * +sieve_file_script_get_dirpath(const struct sieve_script *script) ATTR_PURE; +const char * +sieve_file_script_get_path(const struct sieve_script *script) ATTR_PURE; + +/* + * Comparison + */ + +bool sieve_script_equals(const struct sieve_script *script, + const struct sieve_script *other); + +unsigned int sieve_script_hash(const struct sieve_script *script); +static inline int +sieve_script_cmp(const struct sieve_script *script, + const struct sieve_script *other) +{ + return ( sieve_script_equals(script, other) ? 0 : -1 ); +} + +/* + * Error handling + */ + +const char *sieve_script_get_last_error(struct sieve_script *script, + enum sieve_error *error_r) ATTR_NULL(2); +const char *sieve_script_get_last_error_lcase(struct sieve_script *script); + +/* + * Script sequence + */ + +struct sieve_script_sequence; + +struct sieve_script_sequence * +sieve_script_sequence_create(struct sieve_instance *svinst, + const char *location, enum sieve_error *error_r); +struct sieve_script * +sieve_script_sequence_next(struct sieve_script_sequence *seq, + enum sieve_error *error_r); +void sieve_script_sequence_free(struct sieve_script_sequence **_seq); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-settings.c b/pigeonhole/src/lib-sieve/sieve-settings.c new file mode 100644 index 0000000..47f70da --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-settings.c @@ -0,0 +1,270 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-limits.h" +#include "sieve-error.h" +#include "sieve-address.h" +#include "sieve-address-source.h" +#include "sieve-settings.h" + +#include <ctype.h> + +/* + * Access to settings + */ + +bool sieve_setting_get_uint_value(struct sieve_instance *svinst, + const char *setting, + unsigned long long int *value_r) +{ + const char *str_value; + + str_value = sieve_setting_get(svinst, setting); + + if (str_value == NULL || *str_value == '\0') + return FALSE; + + if (str_to_ullong(str_value, value_r) < 0) { + e_warning(svinst->event, + "invalid unsigned integer value for setting '%s': " + "'%s'", setting, str_value); + return FALSE; + } + return TRUE; +} + +bool sieve_setting_get_int_value(struct sieve_instance *svinst, + const char *setting, long long int *value_r) +{ + const char *str_value; + + str_value = sieve_setting_get(svinst, setting); + if (str_value == NULL || *str_value == '\0') + return FALSE; + + if (str_to_llong(str_value, value_r) < 0) { + e_warning(svinst->event, + "invalid integer value for setting '%s': '%s'", + setting, str_value); + return FALSE; + } + return TRUE; +} + +bool sieve_setting_get_size_value(struct sieve_instance *svinst, + const char *setting, size_t *value_r) +{ + const char *str_value; + uintmax_t value, multiply = 1; + const char *endp; + + str_value = sieve_setting_get(svinst, setting); + if (str_value == NULL || *str_value == '\0') + return FALSE; + + if (str_parse_uintmax(str_value, &value, &endp) < 0) { + e_warning(svinst->event, + "invalid size value for setting '%s': '%s'", + setting, str_value); + return FALSE; + } + switch (i_toupper(*endp)) { + case '\0': /* default */ + case 'B': /* byte (useless) */ + multiply = 1; + break; + case 'K': /* kilobyte */ + multiply = 1024; + break; + case 'M': /* megabyte */ + multiply = 1024*1024; + break; + case 'G': /* gigabyte */ + multiply = 1024*1024*1024; + break; + case 'T': /* terabyte */ + multiply = 1024ULL*1024*1024*1024; + break; + default: + e_warning(svinst->event, + "invalid size value for setting '%s': '%s'", + setting, str_value); + return FALSE; + } + + if (value > SSIZE_T_MAX / multiply) { + e_warning(svinst->event, + "overflowing size value for setting '%s': '%s'", + setting, str_value); + return FALSE; + } + + *value_r = (size_t)(value * multiply); + return TRUE; +} + +bool sieve_setting_get_bool_value(struct sieve_instance *svinst, + const char *setting, bool *value_r) +{ + const char *str_value; + + str_value = sieve_setting_get(svinst, setting); + if (str_value == NULL) + return FALSE; + + str_value = t_str_trim(str_value, "\t "); + if (*str_value == '\0') + return FALSE; + + if (strcasecmp(str_value, "yes") == 0) { + *value_r = TRUE; + return TRUE; + } + + if (strcasecmp(str_value, "no") == 0) { + *value_r = FALSE; + return TRUE; + } + + e_warning(svinst->event, + "invalid boolean value for setting '%s': '%s'", + setting, str_value); + return FALSE; +} + +bool sieve_setting_get_duration_value(struct sieve_instance *svinst, + const char *setting, + sieve_number_t *value_r) +{ + const char *str_value; + uintmax_t value, multiply = 1; + const char *endp; + + str_value = sieve_setting_get(svinst, setting); + if (str_value == NULL) + return FALSE; + + str_value = t_str_trim(str_value, "\t "); + if (*str_value == '\0') + return FALSE; + + if (str_parse_uintmax(str_value, &value, &endp) < 0) { + e_warning(svinst->event, + "invalid duration value for setting '%s': '%s'", + setting, str_value); + return FALSE; + } + + switch (i_tolower(*endp)) { + case '\0': /* default */ + case 's': /* seconds */ + multiply = 1; + break; + case 'm': /* minutes */ + multiply = 60; + break; + case 'h': /* hours */ + multiply = 60*60; + break; + case 'd': /* days */ + multiply = 24*60*60; + break; + default: + e_warning(svinst->event, + "invalid duration value for setting '%s': '%s'", + setting, str_value); + return FALSE; + } + + if (value > SIEVE_MAX_NUMBER / multiply) { + e_warning(svinst->event, + "overflowing duration value for setting '%s': '%s'", + setting, str_value); + return FALSE; + } + + *value_r = (unsigned int)(value * multiply); + return TRUE; +} + +/* + * Main Sieve engine settings + */ + +void sieve_settings_load(struct sieve_instance *svinst) +{ + const char *str_setting, *error; + unsigned long long int uint_setting; + size_t size_setting; + sieve_number_t period; + + svinst->max_script_size = SIEVE_DEFAULT_MAX_SCRIPT_SIZE; + if (sieve_setting_get_size_value(svinst, "sieve_max_script_size", + &size_setting)) + svinst->max_script_size = size_setting; + + svinst->max_actions = SIEVE_DEFAULT_MAX_ACTIONS; + if (sieve_setting_get_uint_value(svinst, "sieve_max_actions", + &uint_setting)) + svinst->max_actions = (unsigned int)uint_setting; + + svinst->max_redirects = SIEVE_DEFAULT_MAX_REDIRECTS; + if (sieve_setting_get_uint_value(svinst, "sieve_max_redirects", + &uint_setting)) + svinst->max_redirects = (unsigned int)uint_setting; + + svinst->max_cpu_time_secs = + (svinst->env_location == SIEVE_ENV_LOCATION_MS ? + 0 : SIEVE_DEFAULT_MAX_CPU_TIME_SECS); + if (sieve_setting_get_duration_value(svinst, "sieve_max_cpu_time", + &period)) { + if (period > (UINT_MAX / 1000)) + svinst->max_cpu_time_secs = (UINT_MAX / 1000); + else + svinst->max_cpu_time_secs = (unsigned int)period; + } + svinst->resource_usage_timeout_secs = + SIEVE_DEFAULT_RESOURCE_USAGE_TIMEOUT_SECS; + if (sieve_setting_get_duration_value( + svinst, "sieve_resource_usage_timeout", &period)) { + if (period > UINT_MAX) + svinst->resource_usage_timeout_secs = UINT_MAX; + else { + svinst->resource_usage_timeout_secs = + (unsigned int)period; + } + } + + (void)sieve_address_source_parse_from_setting( + svinst, svinst->pool, "sieve_redirect_envelope_from", + &svinst->redirect_from); + + svinst->redirect_duplicate_period = DEFAULT_REDIRECT_DUPLICATE_PERIOD; + if (sieve_setting_get_duration_value( + svinst, "sieve_redirect_duplicate_period", &period)) { + if (period > UINT_MAX) + svinst->redirect_duplicate_period = UINT_MAX; + else { + svinst->redirect_duplicate_period = + (unsigned int)period; + } + } + + str_setting = sieve_setting_get(svinst, "sieve_user_email"); + if (str_setting != NULL && *str_setting != '\0') { + struct smtp_address *address; + if (smtp_address_parse_path( + svinst->pool, str_setting, + SMTP_ADDRESS_PARSE_FLAG_BRACKETS_OPTIONAL, + &address, &error) < 0) { + e_warning(svinst->event, + "Invalid address value for setting " + "`sieve_user_email': %s", error); + } else { + svinst->user_email = address; + } + } +} diff --git a/pigeonhole/src/lib-sieve/sieve-settings.h b/pigeonhole/src/lib-sieve/sieve-settings.h new file mode 100644 index 0000000..f2dfca2 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-settings.h @@ -0,0 +1,57 @@ +#ifndef SIEVE_SETTINGS_H +#define SIEVE_SETTINGS_H + +#include "sieve-common.h" + +/* + * Access to settings + */ + +static inline const char * +sieve_setting_get(struct sieve_instance *svinst, const char *identifier) +{ + const struct sieve_callbacks *callbacks = svinst->callbacks; + + if (callbacks == NULL || callbacks->get_setting == NULL) + return NULL; + + return callbacks->get_setting(svinst->context, identifier); +} + +bool sieve_setting_get_uint_value(struct sieve_instance *svinst, + const char *setting, + unsigned long long int *value_r); +bool sieve_setting_get_int_value(struct sieve_instance *svinst, + const char *setting, long long int *value_r); +bool sieve_setting_get_size_value(struct sieve_instance *svinst, + const char *setting, size_t *value_r); +bool sieve_setting_get_bool_value(struct sieve_instance *svinst, + const char *setting, bool *value_r); +bool sieve_setting_get_duration_value(struct sieve_instance *svinst, + const char *setting, + sieve_number_t *value_r); + +/* + * Main Sieve engine settings + */ + +void sieve_settings_load(struct sieve_instance *svinst); + +/* + * Home directory + */ + +static inline const char * +sieve_environment_get_homedir(struct sieve_instance *svinst) +{ + const struct sieve_callbacks *callbacks = svinst->callbacks; + + if (svinst->home_dir != NULL) + return svinst->home_dir; + if (callbacks == NULL || callbacks->get_homedir == NULL) + return NULL; + + return callbacks->get_homedir(svinst->context); +} + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-smtp.c b/pigeonhole/src/lib-sieve/sieve-smtp.c new file mode 100644 index 0000000..40b40ea --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-smtp.c @@ -0,0 +1,95 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ +#include "lib.h" +#include "smtp-address.h" + +#include "sieve-common.h" +#include "sieve-smtp.h" + +struct sieve_smtp_context { + const struct sieve_script_env *senv; + void *handle; + + bool sent:1; +}; + +bool sieve_smtp_available +(const struct sieve_script_env *senv) +{ + return ( senv->smtp_start != NULL && senv->smtp_add_rcpt != NULL && + senv->smtp_send != NULL && senv->smtp_finish != NULL ); +} + +struct sieve_smtp_context *sieve_smtp_start +(const struct sieve_script_env *senv, + const struct smtp_address *mail_from) +{ + struct sieve_smtp_context *sctx; + void *handle; + + if ( !sieve_smtp_available(senv) ) + return NULL; + + handle = senv->smtp_start(senv, mail_from); + i_assert( handle != NULL ); + + sctx = i_new(struct sieve_smtp_context, 1); + sctx->senv = senv; + sctx->handle = handle; + + return sctx; +} + +void sieve_smtp_add_rcpt +(struct sieve_smtp_context *sctx, + const struct smtp_address *rcpt_to) +{ + i_assert(!sctx->sent); + sctx->senv->smtp_add_rcpt(sctx->senv, sctx->handle, rcpt_to); +} + +struct ostream *sieve_smtp_send +(struct sieve_smtp_context *sctx) +{ + i_assert(!sctx->sent); + sctx->sent = TRUE; + + return sctx->senv->smtp_send(sctx->senv, sctx->handle); +} + +struct sieve_smtp_context *sieve_smtp_start_single +(const struct sieve_script_env *senv, + const struct smtp_address *rcpt_to, + const struct smtp_address *mail_from, + struct ostream **output_r) +{ + struct sieve_smtp_context *sctx; + + sctx = sieve_smtp_start(senv, mail_from); + sieve_smtp_add_rcpt(sctx, rcpt_to); + *output_r = sieve_smtp_send(sctx); + + return sctx; +} + +void sieve_smtp_abort +(struct sieve_smtp_context *sctx) +{ + const struct sieve_script_env *senv = sctx->senv; + void *handle = sctx->handle; + + i_free(sctx); + i_assert(senv->smtp_abort != NULL); + senv->smtp_abort(senv, handle); +} + +int sieve_smtp_finish +(struct sieve_smtp_context *sctx, const char **error_r) +{ + const struct sieve_script_env *senv = sctx->senv; + void *handle = sctx->handle; + + i_free(sctx); + return senv->smtp_finish(senv, handle, error_r); +} + diff --git a/pigeonhole/src/lib-sieve/sieve-smtp.h b/pigeonhole/src/lib-sieve/sieve-smtp.h new file mode 100644 index 0000000..f7b9c84 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-smtp.h @@ -0,0 +1,31 @@ +#ifndef SIEVE_SMTP_H +#define SIEVE_SMTP_H + +#include "sieve-common.h" + +bool sieve_smtp_available + (const struct sieve_script_env *senv); + +struct sieve_smtp_context; + +struct sieve_smtp_context *sieve_smtp_start + (const struct sieve_script_env *senv, + const struct smtp_address *mail_from); +void sieve_smtp_add_rcpt + (struct sieve_smtp_context *sctx, + const struct smtp_address *rcpt_to); +struct ostream *sieve_smtp_send + (struct sieve_smtp_context *sctx); + +struct sieve_smtp_context *sieve_smtp_start_single + (const struct sieve_script_env *senv, + const struct smtp_address *rcpt_to, + const struct smtp_address *mail_from, + struct ostream **output_r); + +void sieve_smtp_abort + (struct sieve_smtp_context *sctx); +int sieve_smtp_finish + (struct sieve_smtp_context *sctx, const char **error_r); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-storage-private.h b/pigeonhole/src/lib-sieve/sieve-storage-private.h new file mode 100644 index 0000000..16af3d4 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-storage-private.h @@ -0,0 +1,256 @@ +#ifndef SIEVE_STORAGE_PRIVATE_H +#define SIEVE_STORAGE_PRIVATE_H + +#include "sieve.h" +#include "sieve-error-private.h" + +#include "sieve-storage.h" + +#define MAILBOX_ATTRIBUTE_PREFIX_SIEVE \ + MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER"sieve/" +#define MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES \ + MAILBOX_ATTRIBUTE_PREFIX_SIEVE"files/" +#define MAILBOX_ATTRIBUTE_SIEVE_DEFAULT \ + MAILBOX_ATTRIBUTE_PREFIX_SIEVE"default" + +#define MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_LINK 'L' +#define MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_SCRIPT 'S' + +struct sieve_storage; + +ARRAY_DEFINE_TYPE(sieve_storage_class, const struct sieve_storage *); + +struct sieve_storage_vfuncs { + struct sieve_storage *(*alloc)(void); + void (*destroy)(struct sieve_storage *storage); + int (*init)(struct sieve_storage *storage, const char *const *options, + enum sieve_error *error_r); + + int (*get_last_change)(struct sieve_storage *storage, + time_t *last_change_r); + void (*set_modified)(struct sieve_storage *storage, time_t mtime); + + int (*is_singular)(struct sieve_storage *storage); + + /* script access */ + struct sieve_script *(*get_script)(struct sieve_storage *storage, + const char *name); + + /* script sequence */ + struct sieve_script_sequence *(*get_script_sequence)( + struct sieve_storage *storage, enum sieve_error *error_r); + struct sieve_script *(*script_sequence_next)( + struct sieve_script_sequence *seq, enum sieve_error *error_r); + void (*script_sequence_destroy)(struct sieve_script_sequence *seq); + + /* active script */ + int (*active_script_get_name)(struct sieve_storage *storage, + const char **name_r); + struct sieve_script *(*active_script_open)( + struct sieve_storage *storage); + int (*deactivate)(struct sieve_storage *storage); + int (*active_script_get_last_change)(struct sieve_storage *storage, + time_t *last_change_r); + + /* listing scripts */ + struct sieve_storage_list_context *(*list_init)( + struct sieve_storage *storage); + const char *(*list_next)(struct sieve_storage_list_context *lctx, + bool *active_r); + int (*list_deinit)(struct sieve_storage_list_context *lctx); + + /* saving scripts */ + // FIXME: simplify this API; reduce this mostly to a single save function + struct sieve_storage_save_context *(*save_alloc)( + struct sieve_storage *storage); + int (*save_init)(struct sieve_storage_save_context *sctx, + const char *scriptname, struct istream *input); + int (*save_continue)(struct sieve_storage_save_context *sctx); + int (*save_finish)(struct sieve_storage_save_context *sctx); + struct sieve_script *(*save_get_tempscript)( + struct sieve_storage_save_context *sctx); + void (*save_cancel)(struct sieve_storage_save_context *sctx); + int (*save_commit)(struct sieve_storage_save_context *sctx); + int (*save_as)(struct sieve_storage *storage, struct istream *input, + const char *name); + int (*save_as_active)(struct sieve_storage *storage, + struct istream *input, time_t mtime); + + /* checking quota */ + int (*quota_havespace)(struct sieve_storage *storage, + const char *scriptname, size_t size, + enum sieve_storage_quota *quota_r, + uint64_t *limit_r); +}; + +struct sieve_storage { + pool_t pool; + unsigned int refcount; + struct sieve_instance *svinst; + struct event *event; + + const char *driver_name; + unsigned int version; + + const struct sieve_storage *storage_class; + struct sieve_storage_vfuncs v; + + uint64_t max_scripts; + uint64_t max_storage; + + char *error; + enum sieve_error error_code; + + const char *data; + const char *location; + const char *script_name; + const char *bin_dir; + + const char *default_name; + const char *default_location; + struct sieve_storage *default_for; + + struct mail_namespace *sync_inbox_ns; + + enum sieve_storage_flags flags; + + /* this is the main personal storage */ + bool main_storage:1; + bool allows_synchronization:1; + bool is_default:1; +}; + +struct event * +sieve_storage_event_create(struct sieve_instance *svinst, + const struct sieve_storage *storage_class); +struct sieve_storage * +sieve_storage_alloc(struct sieve_instance *svinst, struct event *event, + const struct sieve_storage *storage_class, const char *data, + enum sieve_storage_flags flags, bool main) ATTR_NULL(2, 4); + +int sieve_storage_setup_bindir(struct sieve_storage *storage, mode_t mode); + +/* + * Active script + */ + +int sieve_storage_active_script_is_default(struct sieve_storage *storage); + +/* + * Listing scripts + */ + +struct sieve_storage_list_context { + struct sieve_storage *storage; + + bool seen_active:1; // Just present for assertions + bool seen_default:1; +}; + +/* + * Script sequence + */ + +struct sieve_script_sequence { + struct sieve_storage *storage; +}; + +/* + * Saving scripts + */ + +struct sieve_storage_save_context { + pool_t pool; + struct sieve_storage *storage; + struct event *event; + + const char *scriptname, *active_scriptname; + struct sieve_script *scriptobject; + + struct istream *input; + + time_t mtime; + + bool failed:1; + bool finished:1; +}; + +/* + * Storage class + */ + +struct sieve_storage_class_registry; + +void sieve_storages_init(struct sieve_instance *svinst); +void sieve_storages_deinit(struct sieve_instance *svinst); + +void sieve_storage_class_register(struct sieve_instance *svinst, + const struct sieve_storage *storage_class); +void sieve_storage_class_unregister(struct sieve_instance *svinst, + const struct sieve_storage *storage_class); +const struct sieve_storage * +sieve_storage_find_class(struct sieve_instance *svinst, const char *name); + +/* + * Built-in storage drivers + */ + +/* data (currently only for internal use) */ + +#define SIEVE_DATA_STORAGE_DRIVER_NAME "data" + +extern const struct sieve_storage sieve_data_storage; + +/* file */ + +#define SIEVE_FILE_STORAGE_DRIVER_NAME "file" + +extern const struct sieve_storage sieve_file_storage; + +struct sieve_storage * +sieve_file_storage_init_legacy(struct sieve_instance *svinst, + const char *active_path, + const char *storage_path, + enum sieve_storage_flags flags, + enum sieve_error *error_r) ATTR_NULL(6); + +/* dict */ + +#define SIEVE_DICT_STORAGE_DRIVER_NAME "dict" + +extern const struct sieve_storage sieve_dict_storage; + +/* ldap */ + +#define SIEVE_LDAP_STORAGE_DRIVER_NAME "ldap" + +extern const struct sieve_storage sieve_ldap_storage; + +/* + * Error handling + */ + +void sieve_storage_set_internal_error(struct sieve_storage *storage); + +void sieve_storage_copy_error(struct sieve_storage *storage, + const struct sieve_storage *source); + +/* + * Synchronization + */ + +int sieve_storage_sync_init(struct sieve_storage *storage, + struct mail_user *user); +void sieve_storage_sync_deinit(struct sieve_storage *storage); + +int sieve_storage_sync_script_save(struct sieve_storage *storage, + const char *name); +int sieve_storage_sync_script_rename(struct sieve_storage *storage, + const char *oldname, const char *newname); +int sieve_storage_sync_script_delete(struct sieve_storage *storage, + const char *name); + +int sieve_storage_sync_script_activate(struct sieve_storage *storage); +int sieve_storage_sync_deactivate(struct sieve_storage *storage); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-storage-sync.c b/pigeonhole/src/lib-sieve/sieve-storage-sync.c new file mode 100644 index 0000000..b1abfcc --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-storage-sync.c @@ -0,0 +1,195 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "str-sanitize.h" +#include "home-expand.h" +#include "eacces-error.h" +#include "mkdir-parents.h" +#include "ioloop.h" +#include "mail-storage-private.h" + +#include "sieve-common.h" +#include "sieve-settings.h" +#include "sieve-error-private.h" + +#include "sieve-script-private.h" +#include "sieve-storage-private.h" + +/* + * Synchronization + */ + +int sieve_storage_sync_init +(struct sieve_storage *storage, struct mail_user *user) +{ + enum sieve_storage_flags sflags = storage->flags; + + if ( (sflags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0 && + (sflags & SIEVE_STORAGE_FLAG_READWRITE) == 0 ) + return 0; + + if ( !storage->allows_synchronization ) { + if ( (sflags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) != 0 ) + return -1; + return 0; + } + + e_debug(storage->event, "sync: Synchronization active"); + + storage->sync_inbox_ns = mail_namespace_find_inbox(user->namespaces); + return 0; +} + +void sieve_storage_sync_deinit +(struct sieve_storage *storage ATTR_UNUSED) +{ + /* nothing */ +} + +/* + * Sync attributes + */ + +static int sieve_storage_sync_transaction_begin +(struct sieve_storage *storage, struct mailbox_transaction_context **trans_r) +{ + enum mailbox_flags mflags = MAILBOX_FLAG_IGNORE_ACLS; + struct mail_namespace *ns = storage->sync_inbox_ns; + struct mailbox *inbox; + enum mail_error error; + + if (ns == NULL) + return 0; + + inbox = mailbox_alloc(ns->list, "INBOX", mflags); + if (mailbox_open(inbox) < 0) { + e_warning(storage->event, "sync: " + "Failed to open user INBOX for attribute modifications: %s", + mailbox_get_last_internal_error(inbox, &error)); + mailbox_free(&inbox); + return -1; + } + + *trans_r = mailbox_transaction_begin(inbox, + MAILBOX_TRANSACTION_FLAG_EXTERNAL, + __func__); + return 1; +} + +static int sieve_storage_sync_transaction_finish +(struct sieve_storage *storage, struct mailbox_transaction_context **trans) +{ + struct mailbox *inbox; + int ret; + + inbox = mailbox_transaction_get_mailbox(*trans); + + if ((ret=mailbox_transaction_commit(trans)) < 0) { + enum mail_error error; + + e_warning(storage->event, "sync: " + "Failed to update INBOX attributes: %s", + mail_storage_get_last_error( + mailbox_get_storage(inbox), &error)); + } + + mailbox_free(&inbox); + return ret; +} + +int sieve_storage_sync_script_save +(struct sieve_storage *storage, const char *name) +{ + struct mailbox_transaction_context *trans; + const char *key; + int ret; + + if ((ret=sieve_storage_sync_transaction_begin + (storage, &trans)) <= 0) + return ret; + + key = t_strconcat + (MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES, name, NULL); + + mail_index_attribute_set(trans->itrans, TRUE, key, ioloop_time, 0); + + return sieve_storage_sync_transaction_finish(storage, &trans); +} + +int sieve_storage_sync_script_rename +(struct sieve_storage *storage, const char *oldname, + const char *newname) +{ + struct mailbox_transaction_context *trans; + const char *oldkey, *newkey; + int ret; + + if ((ret=sieve_storage_sync_transaction_begin + (storage, &trans)) <= 0) + return ret; + + oldkey = t_strconcat + (MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES, oldname, NULL); + newkey = t_strconcat + (MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES, newname, NULL); + + mail_index_attribute_unset(trans->itrans, TRUE, oldkey, ioloop_time); + mail_index_attribute_set(trans->itrans, TRUE, newkey, ioloop_time, 0); + + return sieve_storage_sync_transaction_finish(storage, &trans); +} + +int sieve_storage_sync_script_delete +(struct sieve_storage *storage, const char *name) +{ + struct mailbox_transaction_context *trans; + const char *key; + int ret; + + if ((ret=sieve_storage_sync_transaction_begin + (storage, &trans)) <= 0) + return ret; + + key = t_strconcat + (MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES, name, NULL); + + mail_index_attribute_unset(trans->itrans, TRUE, key, ioloop_time); + + return sieve_storage_sync_transaction_finish(storage, &trans); +} + +int sieve_storage_sync_script_activate +(struct sieve_storage *storage) +{ + struct mailbox_transaction_context *trans; + int ret; + + if ((ret=sieve_storage_sync_transaction_begin + (storage, &trans)) <= 0) + return ret; + + mail_index_attribute_set(trans->itrans, + TRUE, MAILBOX_ATTRIBUTE_SIEVE_DEFAULT, ioloop_time, 0); + + return sieve_storage_sync_transaction_finish(storage, &trans); +} + +int sieve_storage_sync_deactivate +(struct sieve_storage *storage) +{ + struct mailbox_transaction_context *trans; + int ret; + + if ((ret=sieve_storage_sync_transaction_begin + (storage, &trans)) <= 0) + return ret; + + mail_index_attribute_unset(trans->itrans, + TRUE, MAILBOX_ATTRIBUTE_SIEVE_DEFAULT, ioloop_time); + + return sieve_storage_sync_transaction_finish(storage, &trans); +} + + diff --git a/pigeonhole/src/lib-sieve/sieve-storage.c b/pigeonhole/src/lib-sieve/sieve-storage.c new file mode 100644 index 0000000..1e2aa34 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-storage.c @@ -0,0 +1,1590 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "str-sanitize.h" +#include "home-expand.h" +#include "eacces-error.h" +#include "mkdir-parents.h" +#include "ioloop.h" + +#include "sieve-common.h" +#include "sieve-settings.h" +#include "sieve-error-private.h" + +#include "sieve-script-private.h" +#include "sieve-storage-private.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <time.h> +#include <utime.h> + +#define CRITICAL_MSG \ + "Internal error occurred. Refer to server log for more information." +#define CRITICAL_MSG_STAMP CRITICAL_MSG " [%Y-%m-%d %H:%M:%S]" + +struct event_category event_category_sieve_storage = { + .parent = &event_category_sieve, + .name = "sieve-storage", +}; + +/* + * Storage class + */ + +struct sieve_storage_class_registry { + ARRAY_TYPE(sieve_storage_class) storage_classes; +}; + +void sieve_storages_init(struct sieve_instance *svinst) +{ + svinst->storage_reg = p_new(svinst->pool, + struct sieve_storage_class_registry, 1); + p_array_init(&svinst->storage_reg->storage_classes, svinst->pool, 8); + + sieve_storage_class_register(svinst, &sieve_file_storage); + sieve_storage_class_register(svinst, &sieve_dict_storage); + sieve_storage_class_register(svinst, &sieve_ldap_storage); +} + +void sieve_storages_deinit(struct sieve_instance *svinst ATTR_UNUSED) +{ + /* nothing yet */ +} + +void sieve_storage_class_register(struct sieve_instance *svinst, + const struct sieve_storage *storage_class) +{ + struct sieve_storage_class_registry *reg = svinst->storage_reg; + const struct sieve_storage *old_class; + + old_class = sieve_storage_find_class(svinst, + storage_class->driver_name); + if (old_class != NULL) { + if (old_class->v.alloc == NULL) { + /* replacing a "support not compiled in" storage class + */ + sieve_storage_class_unregister(svinst, old_class); + } else { + i_panic("sieve_storage_class_register(%s): " + "Already registered", + storage_class->driver_name); + } + } + + array_append(®->storage_classes, &storage_class, 1); +} + +void sieve_storage_class_unregister(struct sieve_instance *svinst, + const struct sieve_storage *storage_class) +{ + struct sieve_storage_class_registry *reg = svinst->storage_reg; + const struct sieve_storage *const *classes; + unsigned int i, count; + + classes = array_get(®->storage_classes, &count); + for (i = 0; i < count; i++) { + if (classes[i] == storage_class) { + array_delete(®->storage_classes, i, 1); + break; + } + } +} + +const struct sieve_storage * +sieve_storage_find_class(struct sieve_instance *svinst, const char *name) +{ + struct sieve_storage_class_registry *reg = svinst->storage_reg; + const struct sieve_storage *const *classes; + unsigned int i, count; + + i_assert(name != NULL); + + classes = array_get(®->storage_classes, &count); + for (i = 0; i < count; i++) { + if (strcasecmp(classes[i]->driver_name, name) == 0) + return classes[i]; + } + return NULL; +} + +/* + * Storage instance + */ + +static const char *split_next_arg(const char *const **_args) +{ + const char *const *args = *_args; + const char *str = args[0]; + + /* join arguments for escaped ";" separator */ + + args++; + while (*args != NULL && **args == '\0') { + args++; + if (*args == NULL) { + /* string ends with ";", just ignore it. */ + break; + } + str = t_strconcat(str, ";", *args, NULL); + args++; + } + *_args = args; + return str; +} + +static int +sieve_storage_driver_parse(struct sieve_instance *svinst, const char **data, + const struct sieve_storage **driver_r) +{ + const struct sieve_storage *storage_class = NULL; + const char *p; + + p = strchr(*data, ':'); + if (p == NULL) + return 0; + + /* Lookup storage driver */ + T_BEGIN { + const char *driver; + + driver = t_strdup_until(*data, p); + *data = p+1; + + storage_class = sieve_storage_find_class(svinst, driver); + if (storage_class == NULL) { + e_error(svinst->event, + "Unknown storage driver module `%s'", + driver); + } else if (storage_class->v.alloc == NULL) { + e_error(svinst->event, + "Support not compiled in for storage driver `%s'", + driver); + storage_class = NULL; + } + } T_END; + + *driver_r = storage_class; + return (storage_class == NULL ? -1 : 1); +} + +static int +sieve_storage_data_parse(struct sieve_storage *storage, const char *data, + const char **location_r, const char *const **options_r) +{ + ARRAY_TYPE(const_string) options; + const char *const *tmp; + + if (*data == '\0') { + *options_r = NULL; + *location_r = data; + return 0; + } + + /* <location> */ + tmp = t_strsplit(data, ";"); + *location_r = split_next_arg(&tmp); + + if (options_r != NULL) { + t_array_init(&options, 8); + + /* [<option> *(';' <option>)] */ + while (*tmp != NULL) { + const char *option = split_next_arg(&tmp); + + if (strncasecmp(option, "name=", 5) == 0) { + if (option[5] == '\0') { + e_error(storage->event, + "Failed to parse storage location: " + "Empty name not allowed"); + return -1; + } + + if (storage->script_name == NULL) { + if (!sieve_script_name_is_valid(option+5)) { + e_error(storage->event, + "Failed to parse storage location: " + "Invalid script name `%s'.", + str_sanitize(option+5, 80)); + return -1; + } + storage->script_name = p_strdup(storage->pool, option+5); + } + + } else if (strncasecmp(option, "bindir=", 7) == 0) { + const char *bin_dir = option+7; + + if (bin_dir[0] == '\0') { + e_error(storage->event, + "Failed to parse storage location: " + "Empty bindir not allowed"); + return -1; + } + + if (bin_dir[0] == '~') { + /* home-relative path. change to absolute. */ + const char *home = sieve_environment_get_homedir(storage->svinst); + + if (home != NULL) { + bin_dir = home_expand_tilde(bin_dir, home); + } else if (bin_dir[1] == '/' || bin_dir[1] == '\0') { + e_error(storage->event, + "Failed to parse storage location: " + "bindir is relative to home directory (~/), " + "but home directory cannot be determined"); + return -1; + } + } + + storage->bin_dir = p_strdup(storage->pool, bin_dir); + } else { + array_append(&options, &option, 1); + } + } + + (void)array_append_space(&options); + *options_r = array_idx(&options, 0); + } + + return 0; +} + +struct event * +sieve_storage_event_create(struct sieve_instance *svinst, + const struct sieve_storage *storage_class) +{ + struct event *event; + + event = event_create(svinst->event); + event_add_category(event, &event_category_sieve_storage); + event_add_str(event, "driver", storage_class->driver_name); + event_set_append_log_prefix( + event, t_strdup_printf("%s storage: ", + storage_class->driver_name)); + + return event; +} + +struct sieve_storage * +sieve_storage_alloc(struct sieve_instance *svinst, struct event *event, + const struct sieve_storage *storage_class, const char *data, + enum sieve_storage_flags flags, bool main) +{ + struct sieve_storage *storage; + + i_assert(storage_class->v.alloc != NULL); + storage = storage_class->v.alloc(); + + storage->storage_class = storage_class; + storage->refcount = 1; + storage->svinst = svinst; + storage->flags = flags; + storage->data = p_strdup_empty(storage->pool, data); + storage->main_storage = main; + + if (event != NULL) { + storage->event = event; + event_ref(storage->event); + } else { + storage->event = + sieve_storage_event_create(svinst, storage_class); + } + + return storage; +} + +static struct sieve_storage * +sieve_storage_init(struct sieve_instance *svinst, + const struct sieve_storage *storage_class, const char *data, + enum sieve_storage_flags flags, bool main, + enum sieve_error *error_r) +{ + struct sieve_storage *storage; + const char *const *options; + const char *location; + struct event *event; + enum sieve_error error; + + if (error_r != NULL) + *error_r = SIEVE_ERROR_NONE; + else + error_r = &error; + + i_assert(storage_class->v.init != NULL); + + event = sieve_storage_event_create(svinst, storage_class); + + if ((flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) != 0 && + !storage_class->allows_synchronization) { + e_debug(event, "Storage does not support synchronization"); + *error_r = SIEVE_ERROR_NOT_POSSIBLE; + event_unref(&event); + return NULL; + } + + if ((flags & SIEVE_STORAGE_FLAG_READWRITE) != 0 && + storage_class->v.save_init == NULL) { + e_error(event, "Storage does not support write access"); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + event_unref(&event); + return NULL; + } + + T_BEGIN { + storage = sieve_storage_alloc(svinst, event, storage_class, + data, flags, main); + + if (sieve_storage_data_parse(storage, data, + &location, &options) < 0) { + *error_r = SIEVE_ERROR_TEMP_FAILURE; + sieve_storage_unref(&storage); + storage = NULL; + } else { + storage->location = p_strdup(storage->pool, location); + + event_add_str(event, "script_location", + storage->location); + + if (storage_class->v.init(storage, options, + error_r) < 0) { + sieve_storage_unref(&storage); + storage = NULL; + } + } + } T_END; + + event_unref(&event); + return storage; +} + +struct sieve_storage * +sieve_storage_create(struct sieve_instance *svinst, const char *location, + enum sieve_storage_flags flags, enum sieve_error *error_r) +{ + const struct sieve_storage *storage_class; + enum sieve_error error; + const char *data; + int ret; + + /* Dont use this function for creating a synchronizing storage */ + i_assert((flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0); + + if (error_r != NULL) + *error_r = SIEVE_ERROR_NONE; + else + error_r = &error; + + data = location; + if ((ret = sieve_storage_driver_parse(svinst, &data, + &storage_class)) < 0) { + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return NULL; + } + + if (ret == 0) + storage_class = &sieve_file_storage; + + return sieve_storage_init(svinst, storage_class, data, flags, + FALSE, error_r); +} + +static struct sieve_storage * +sieve_storage_do_create_main(struct sieve_instance *svinst, + struct mail_user *user, + enum sieve_storage_flags flags, + enum sieve_error *error_r) +{ + struct sieve_storage *storage = NULL; + const struct sieve_storage + *sieve_class = NULL, + *sieve_dir_class = NULL; + const char *set_sieve, *set_sieve_dir; + const char *data, *storage_path; + unsigned long long int uint_setting; + size_t size_setting; + int ret; + + /* Sieve storage location */ + + set_sieve = sieve_setting_get(svinst, "sieve"); + + if (set_sieve != NULL) { + if (*set_sieve == '\0') { + /* disabled */ + e_debug(svinst->event, "storage: " + "Personal storage is disabled (sieve=\"\")"); + *error_r = SIEVE_ERROR_NOT_FOUND; + return NULL; + } + + data = set_sieve; + if ((ret = sieve_storage_driver_parse(svinst, &data, + &sieve_class)) < 0) { + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return NULL; + } + + if (ret > 0) { + /* The normal case: explicit driver name */ + storage = sieve_storage_init(svinst, sieve_class, data, + flags, TRUE, error_r); + if (storage == NULL) + return NULL; + } + + /* No driver name */ + } + + if (storage == NULL) { + /* Script storage directory configuration (deprecated) */ + + set_sieve_dir = sieve_setting_get(svinst, "sieve_dir"); + if (set_sieve_dir == NULL) { + set_sieve_dir = sieve_setting_get(svinst, + "sieve_storage"); + } + + if (set_sieve_dir == NULL || *set_sieve_dir == '\0') { + storage_path = ""; + } else { + const char *p; + + /* Parse and check driver */ + storage_path = set_sieve_dir; + if ((ret = sieve_storage_driver_parse( + svinst, &storage_path, &sieve_dir_class)) < 0) { + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return NULL; + } + + if (ret > 0 && sieve_dir_class != &sieve_file_storage) { + e_error(svinst->event, "storage: " + "Cannot use deprecated sieve_dir= setting " + "with `%s' driver for main Sieve storage", + sieve_dir_class->driver_name); + } + + /* Ignore any options */ + p = strchr(storage_path, ';'); + if (p != NULL) + storage_path = t_strdup_until(storage_path, p); + } + + storage = sieve_file_storage_init_legacy(svinst, set_sieve, + storage_path, flags, + error_r); + } + + if (storage == NULL) + return NULL; + + (void)sieve_storage_sync_init(storage, user); + + /* Get quota settings if storage driver provides none */ + + if (storage->max_storage == 0 && + sieve_setting_get_size_value(svinst, "sieve_quota_max_storage", + &size_setting)) { + storage->max_storage = size_setting; + } + + if (storage->max_scripts == 0 && + sieve_setting_get_uint_value(svinst, "sieve_quota_max_scripts", + &uint_setting)) { + storage->max_scripts = uint_setting; + } + + if (storage->max_storage > 0) { + e_debug(storage->event, "quota: " + "Storage limit: %llu bytes", + (unsigned long long int) storage->max_storage); + } + if (storage->max_scripts > 0) { + e_debug(storage->event, "quota: " + "Script count limit: %llu scripts", + (unsigned long long int) storage->max_scripts); + } + return storage; +} + +struct sieve_storage * +sieve_storage_create_main(struct sieve_instance *svinst, struct mail_user *user, + enum sieve_storage_flags flags, + enum sieve_error *error_r) +{ + struct sieve_storage *storage; + const char *set_enabled, *set_default, *set_default_name; + enum sieve_error error; + + if (error_r != NULL) + *error_r = SIEVE_ERROR_NONE; + else + error_r = &error; + + /* Check whether Sieve is disabled for this user */ + if ((set_enabled = sieve_setting_get(svinst, "sieve_enabled")) != NULL && + strcasecmp(set_enabled, "no") == 0) { + e_debug(svinst->event, + "Sieve is disabled for this user"); + *error_r = SIEVE_ERROR_NOT_POSSIBLE; + return NULL; + } + + /* Determine location for default script */ + set_default = sieve_setting_get(svinst, "sieve_default"); + if (set_default == NULL) { + /* For backwards compatibility */ + set_default = sieve_setting_get(svinst, "sieve_global_path"); + } + + /* Attempt to locate user's main storage */ + storage = sieve_storage_do_create_main(svinst, user, flags, error_r); + if (storage != NULL) { + /* Success; record default script location for later use */ + storage->default_location = + p_strdup_empty(storage->pool, set_default); + + set_default_name = + sieve_setting_get(svinst, "sieve_default_name"); + if (set_default_name != NULL && *set_default_name != '\0' && + !sieve_script_name_is_valid(set_default_name)) { + e_error(storage->event, + "Invalid script name `%s' for `sieve_default_name' setting.", + str_sanitize(set_default_name, 80)); + set_default_name = NULL; + } + storage->default_name = + p_strdup_empty(storage->pool, set_default_name); + + if (storage->default_location != NULL && + storage->default_name != NULL) { + e_debug(storage->event, + "Default script at `%s' is visible by name `%s'", + storage->default_location, storage->default_name); + } + } else if (*error_r != SIEVE_ERROR_TEMP_FAILURE && + (flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0 && + (flags & SIEVE_STORAGE_FLAG_READWRITE) == 0) { + + /* Failed; try using default script location + (not for temporary failures, read/write access, or dsync) */ + if (set_default == NULL) { + e_debug(svinst->event, "storage: " + "No default script location configured"); + } else { + e_debug(svinst->event, "storage: " + "Trying default script location `%s'", + set_default); + + storage = sieve_storage_create(svinst, set_default, 0, + error_r); + if (storage == NULL) { + switch (*error_r) { + case SIEVE_ERROR_NOT_FOUND: + e_debug(svinst->event, "storage: " + "Default script location `%s' not found", + set_default); + break; + case SIEVE_ERROR_TEMP_FAILURE: + e_error(svinst->event, "storage: " + "Failed to access default script location `%s' " + "(temporary failure)", + set_default); + break; + default: + e_error(svinst->event, "storage: " + "Failed to access default script location `%s'", + set_default); + break; + } + } + } + if (storage != NULL) + storage->is_default = TRUE; + } + return storage; +} + +void sieve_storage_ref(struct sieve_storage *storage) +{ + storage->refcount++; +} + +void sieve_storage_unref(struct sieve_storage **_storage) +{ + struct sieve_storage *storage = *_storage; + + i_assert(storage->refcount > 0); + + if (--storage->refcount != 0) + return; + + if (storage->default_for != NULL) { + i_assert(storage->is_default); + sieve_storage_unref(&storage->default_for); + } + + sieve_storage_sync_deinit(storage); + + if (storage->v.destroy != NULL) + storage->v.destroy(storage); + + i_free(storage->error); + event_unref(&storage->event); + pool_unref(&storage->pool); + *_storage = NULL; +} + +int sieve_storage_setup_bindir(struct sieve_storage *storage, mode_t mode) +{ + const char *bin_dir = storage->bin_dir; + struct stat st; + + if (bin_dir == NULL) + return -1; + + if (stat(bin_dir, &st) == 0) + return 0; + + if (errno == EACCES) { + e_error(storage->event, + "Failed to setup directory for binaries: " + "%s", eacces_error_get("stat", bin_dir)); + return -1; + } else if (errno != ENOENT) { + e_error(storage->event, + "Failed to setup directory for binaries: " + "stat(%s) failed: %m", + bin_dir); + return -1; + } + + if (mkdir_parents(bin_dir, mode) == 0) { + e_debug(storage->event, + "Created directory for binaries: %s", bin_dir); + return 1; + } + + switch (errno) { + case EEXIST: + return 0; + case ENOENT: + e_error(storage->event, + "Directory for binaries was deleted while it was being created"); + break; + case EACCES: + e_error(storage->event, + "%s", eacces_error_get_creating("mkdir_parents_chgrp", bin_dir)); + break; + default: + e_error(storage->event, + "mkdir_parents_chgrp(%s) failed: %m", bin_dir); + break; + } + + return -1; +} + +int sieve_storage_is_singular(struct sieve_storage *storage) +{ + if (storage->v.is_singular == NULL) + return 1; + return storage->v.is_singular(storage); +} + +int sieve_storage_get_last_change(struct sieve_storage *storage, + time_t *last_change_r) +{ + i_assert(storage->v.get_last_change != NULL); + return storage->v.get_last_change(storage, last_change_r); +} + +void sieve_storage_set_modified(struct sieve_storage *storage, time_t mtime) +{ + if (storage->v.set_modified == NULL) + return; + + storage->v.set_modified(storage, mtime); +} + +/* + * Script access + */ + +static struct sieve_script * +sieve_storage_get_script_direct(struct sieve_storage *storage, const char *name, + enum sieve_error *error_r) +{ + struct sieve_script *script; + + if (error_r != NULL) + *error_r = SIEVE_ERROR_NONE; + sieve_storage_clear_error(storage); + + /* Validate script name */ + if (name != NULL && !sieve_script_name_is_valid(name)) { + sieve_storage_set_error(storage, + SIEVE_ERROR_BAD_PARAMS, + "Invalid script name `%s'.", + str_sanitize(name, 80)); + if (error_r != NULL) + *error_r = storage->error_code; + return NULL; + } + + i_assert(storage->v.get_script != NULL); + script = storage->v.get_script(storage, name); + return script; +} + +struct sieve_script * +sieve_storage_get_script(struct sieve_storage *storage, const char *name, + enum sieve_error *error_r) +{ + struct sieve_instance *svinst = storage->svinst; + struct sieve_script *script; + + script = sieve_storage_get_script_direct(storage, name, error_r); + if (script == NULL) { + /* Error */ + if (storage->error_code == SIEVE_ERROR_NOT_FOUND && + (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0 && + storage->default_name != NULL && + storage->default_location != NULL && + strcmp(storage->default_name, name) == 0) { + /* Not found; if this name maps to the default script, + try to access that instead */ + i_assert(*storage->default_location != '\0'); + + e_debug(storage->event, + "Trying default script instead"); + + script = sieve_script_create( + svinst, storage->default_location, NULL, + error_r); + if (script != NULL) { + script->storage->is_default = TRUE; + script->storage->default_for = storage; + sieve_storage_ref(storage); + } + + } else if (error_r != NULL) { + *error_r = storage->error_code; + } + } + return script; +} + +struct sieve_script * +sieve_storage_open_script(struct sieve_storage *storage, const char *name, + enum sieve_error *error_r) +{ + struct sieve_instance *svinst = storage->svinst; + struct sieve_script *script; + + script = sieve_storage_get_script(storage, name, error_r); + if (script == NULL) + return NULL; + + if (sieve_script_open(script, error_r) >= 0) + return script; + + /* Error */ + sieve_script_unref(&script); + script = NULL; + + if (storage->error_code == SIEVE_ERROR_NOT_FOUND && + (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0 && + storage->default_name != NULL && + storage->default_location != NULL && + strcmp(storage->default_name, name) == 0) { + /* Not found; if this name maps to the default script, + try to open that instead */ + i_assert(*storage->default_location != '\0'); + + e_debug(storage->event, "Trying default script instead"); + + script = sieve_script_create_open( + svinst, storage->default_location, NULL, error_r); + if (script != NULL) { + script->storage->is_default = TRUE; + script->storage->default_for = storage; + sieve_storage_ref(storage); + } + } + return script; +} + +static int +sieve_storage_check_script_direct(struct sieve_storage *storage, + const char *name, enum sieve_error *error_r) + ATTR_NULL(3) +{ + struct sieve_script *script; + enum sieve_error error; + int ret; + + if (error_r == NULL) + error_r = &error; + + script = sieve_storage_get_script_direct(storage, name, error_r); + if (script == NULL) + return (*error_r == SIEVE_ERROR_NOT_FOUND ? 0 : -1); + + ret = sieve_script_open(script, error_r); + sieve_script_unref(&script); + return (ret >= 0 ? 1 : (*error_r == SIEVE_ERROR_NOT_FOUND ? 0 : -1)); +} + +int sieve_storage_check_script(struct sieve_storage *storage, const char *name, + enum sieve_error *error_r) +{ + struct sieve_script *script; + enum sieve_error error; + + if (error_r == NULL) + error_r = &error; + + script = sieve_storage_open_script(storage, name, error_r); + if (script == NULL) + return (*error_r == SIEVE_ERROR_NOT_FOUND ? 0 : -1); + + sieve_script_unref(&script); + return 1; +} + +/* + * Script sequence + */ + +struct sieve_script_sequence * +sieve_storage_get_script_sequence(struct sieve_storage *storage, + enum sieve_error *error_r) +{ + enum sieve_error error; + + if (error_r != NULL) + *error_r = SIEVE_ERROR_NONE; + else + error_r = &error; + + i_assert(storage->v.get_script_sequence != NULL); + return storage->v.get_script_sequence(storage, error_r); +} + +/* + * Active script + */ + +static int +sieve_storage_active_script_do_get_name(struct sieve_storage *storage, + const char **name_r, bool *default_r) + ATTR_NULL(3) +{ + struct sieve_instance *svinst = storage->svinst; + enum sieve_error error; + int ret; + + if (default_r != NULL) + *default_r = FALSE; + + i_assert(storage->v.active_script_get_name != NULL); + ret = storage->v.active_script_get_name(storage, name_r); + + if (ret != 0 || + (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) != 0 || + storage->default_location == NULL || + storage->default_name == NULL) { + return ret; + } + + *name_r = storage->default_name; + + ret = sieve_script_check(svinst, storage->default_location, + NULL, &error); + if (ret <= 0) + return ret; + + if (default_r != NULL) + *default_r = TRUE; + return 1; +} + +int sieve_storage_active_script_get_name(struct sieve_storage *storage, + const char **name_r) +{ + return sieve_storage_active_script_do_get_name(storage, name_r, NULL); +} + +int sieve_storage_active_script_is_default(struct sieve_storage *storage) +{ + const char *name; + bool is_default = FALSE; + int ret; + + ret = sieve_storage_active_script_do_get_name(storage, &name, + &is_default); + return (ret < 0 ? -1 : (is_default ? 1 : 0)); +} + +struct sieve_script * +sieve_storage_active_script_open(struct sieve_storage *storage, + enum sieve_error *error_r) +{ + struct sieve_instance *svinst = storage->svinst; + struct sieve_script *script; + + i_assert(storage->v.active_script_open != NULL); + script = storage->v.active_script_open(storage); + + if (script != NULL || + (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) != 0 || + storage->default_location == NULL) { + if (error_r != NULL) + *error_r = storage->error_code; + return script; + } + + /* Try default script location */ + script = sieve_script_create_open(svinst, storage->default_location, + NULL, error_r); + if (script != NULL) { + script->storage->is_default = TRUE; + script->storage->default_for = storage; + sieve_storage_ref(storage); + } + return script; +} + +int sieve_storage_deactivate(struct sieve_storage *storage, time_t mtime) +{ + int ret; + + i_assert((storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0); + + i_assert(storage->v.deactivate != NULL); + ret = storage->v.deactivate(storage); + + if (ret >= 0) { + struct event_passthrough *e = + event_create_passthrough(storage->event)-> + set_name("sieve_storage_deactivated"); + e_debug(e->event(), "Storage activated"); + + sieve_storage_set_modified(storage, mtime); + (void)sieve_storage_sync_deactivate(storage); + } else { + struct event_passthrough *e = + event_create_passthrough(storage->event)-> + add_str("error", storage->error)-> + set_name("sieve_storage_deactivated"); + e_debug(e->event(), "Failed to deactivate storage: %s", + storage->error); + } + + return ret; +} + +int sieve_storage_active_script_get_last_change(struct sieve_storage *storage, + time_t *last_change_r) +{ + i_assert(storage->v.active_script_get_last_change != NULL); + + return storage->v.active_script_get_last_change(storage, last_change_r); +} + +/* + * Listing scripts + */ + +struct sieve_storage_list_context * +sieve_storage_list_init(struct sieve_storage *storage) +{ + struct sieve_storage_list_context *lctx; + + i_assert(storage->v.list_init != NULL); + lctx = storage->v.list_init(storage); + + if (lctx != NULL) + lctx->storage = storage; + + return lctx; +} + +const char * +sieve_storage_list_next(struct sieve_storage_list_context *lctx, bool *active_r) +{ + struct sieve_storage *storage = lctx->storage; + struct sieve_instance *svinst = storage->svinst; + const char *scriptname; + bool have_default, script_active = FALSE; + + have_default = (storage->default_name != NULL && + storage->default_location != NULL && + (storage->flags & + SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0); + + i_assert(storage->v.list_next != NULL); + scriptname = storage->v.list_next(lctx, &script_active); + + i_assert(!script_active || !lctx->seen_active); + if (script_active) + lctx->seen_active = TRUE; + + if (scriptname != NULL) { + /* Remember when we see that the storage has its own script for + default */ + if (have_default && + strcmp(scriptname, storage->default_name) == 0) + lctx->seen_default = TRUE; + + } else if (have_default && !lctx->seen_default && + sieve_script_check(svinst, storage->default_location, + NULL, NULL) > 0) { + + /* Return default script at the end if it was not listed + thus far (storage backend has no script under default + name) */ + scriptname = storage->default_name; + lctx->seen_default = TRUE; + + /* Mark default as active if no normal script is active */ + if (!lctx->seen_active) { + script_active = TRUE; + lctx->seen_active = TRUE; + } + } + + if (active_r != NULL) + *active_r = script_active; + return scriptname; +} + +int sieve_storage_list_deinit(struct sieve_storage_list_context **_lctx) +{ + struct sieve_storage_list_context *lctx = *_lctx; + struct sieve_storage *storage = lctx->storage; + int ret; + + i_assert(storage->v.list_deinit != NULL); + ret = storage->v.list_deinit(lctx); + + *_lctx = NULL; + return ret; +} + +/* + * Saving scripts + */ + +static struct event * +sieve_storage_save_create_event(struct sieve_storage *storage, + const char *scriptname) ATTR_NULL(2) +{ + struct event *event; + + event = event_create(storage->event); + event_add_str(event, "script_name", scriptname); + if (scriptname == NULL) { + event_set_append_log_prefix(event, "save: "); + } else { + event_set_append_log_prefix( + event, t_strdup_printf("script `%s': save: ", + scriptname)); + } + + return event; +} + +static void sieve_storage_save_cleanup(struct sieve_storage_save_context *sctx) +{ + if (sctx->scriptobject != NULL) + sieve_script_unref(&sctx->scriptobject); +} + +static void sieve_storage_save_deinit(struct sieve_storage_save_context **_sctx) +{ + struct sieve_storage_save_context *sctx = *_sctx; + + *_sctx = NULL; + if (sctx == NULL) + return; + + sieve_storage_save_cleanup(sctx); + event_unref(&sctx->event); + pool_unref(&sctx->pool); +} + +struct sieve_storage_save_context * +sieve_storage_save_init(struct sieve_storage *storage, const char *scriptname, + struct istream *input) +{ + struct sieve_storage_save_context *sctx; + + if (scriptname != NULL) { + /* Validate script name */ + if (!sieve_script_name_is_valid(scriptname)) { + sieve_storage_set_error(storage, + SIEVE_ERROR_BAD_PARAMS, + "Invalid Sieve script name `%s'.", + str_sanitize(scriptname, 80)); + return NULL; + } + } + + i_assert((storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0); + + i_assert(storage->v.save_alloc != NULL); + sctx = storage->v.save_alloc(storage); + sctx->storage = storage; + + sctx->event = sieve_storage_save_create_event(storage, scriptname); + + struct event_passthrough *e = + event_create_passthrough(sctx->event)-> + set_name("sieve_storage_save_started"); + e_debug(e->event(), "Started saving script"); + + i_assert(storage->v.save_init != NULL); + if ((storage->v.save_init(sctx, scriptname, input)) < 0) { + struct event_passthrough *e = + event_create_passthrough(sctx->event)-> + add_str("error", storage->error)-> + set_name("sieve_storage_save_finished"); + e_debug(e->event(), "Failed to save script: %s", + storage->error); + + sieve_storage_save_deinit(&sctx); + return NULL; + } + + sctx->mtime = (time_t)-1; + + i_assert(sctx->input != NULL); + + return sctx; +} + +int sieve_storage_save_continue(struct sieve_storage_save_context *sctx) +{ + struct sieve_storage *storage = sctx->storage; + int ret; + + i_assert(storage->v.save_continue != NULL); + ret = storage->v.save_continue(sctx); + if (ret < 0) + sctx->failed = TRUE; + return ret; +} + +int sieve_storage_save_finish(struct sieve_storage_save_context *sctx) +{ + struct sieve_storage *storage = sctx->storage; + int ret; + + i_assert(!sctx->finished); + sctx->finished = TRUE; + + i_assert(storage->v.save_finish != NULL); + ret = storage->v.save_finish(sctx); + if (ret < 0) { + struct event_passthrough *e = + event_create_passthrough(sctx->event)-> + add_str("error", storage->error)-> + set_name("sieve_storage_save_finished"); + e_debug(e->event(), "Failed to upload script: %s", + storage->error); + + sctx->failed = TRUE; + } + return ret; +} + +void sieve_storage_save_set_mtime(struct sieve_storage_save_context *sctx, + time_t mtime) +{ + sctx->mtime = mtime; +} + +struct sieve_script * +sieve_storage_save_get_tempscript(struct sieve_storage_save_context *sctx) +{ + struct sieve_storage *storage = sctx->storage; + + if (sctx->failed) + return NULL; + + if (sctx->scriptobject != NULL) + return sctx->scriptobject; + + i_assert(storage->v.save_get_tempscript != NULL); + sctx->scriptobject = storage->v.save_get_tempscript(sctx); + + i_assert(sctx->scriptobject != NULL || + storage->error_code != SIEVE_ERROR_NONE); + return sctx->scriptobject; +} + +bool sieve_storage_save_will_activate(struct sieve_storage_save_context *sctx) +{ + if (sctx->scriptname == NULL) + return FALSE; + + if (sctx->active_scriptname == NULL) { + const char *scriptname; + + if (sieve_storage_active_script_get_name(sctx->storage, + &scriptname) > 0) { + sctx->active_scriptname = + p_strdup(sctx->pool, scriptname); + } + } + + /* Is the requested script active? */ + return (sctx->active_scriptname != NULL && + strcmp(sctx->scriptname, sctx->active_scriptname) == 0); +} + +int sieve_storage_save_commit(struct sieve_storage_save_context **_sctx) +{ + struct sieve_storage_save_context *sctx = *_sctx; + struct sieve_storage *storage; + const char *scriptname; + bool default_activate = FALSE; + int ret; + + *_sctx = NULL; + if (sctx == NULL) + return 0; + + storage = sctx->storage; + scriptname = sctx->scriptname; + + i_assert(!sctx->failed); + i_assert(sctx->finished); + i_assert(sctx->scriptname != NULL); + + /* Check whether we're replacing the default active script */ + if (storage->default_name != NULL && + storage->default_location != NULL && + (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0 && + strcmp(sctx->scriptname, storage->default_name) == 0 && + sieve_storage_save_will_activate(sctx) && + sieve_storage_check_script_direct(storage, storage->default_name, + NULL) <= 0) + default_activate = TRUE; + + sieve_storage_save_cleanup(sctx); + + i_assert(storage->v.save_commit != NULL); + ret = storage->v.save_commit(sctx); + + /* Implicitly activate it when we're replacing the default + active script */ + if (ret >= 0 && default_activate) { + struct sieve_script *script; + enum sieve_error error; + + script = sieve_storage_open_script(storage, scriptname, &error); + if (script == NULL) { + /* Somehow not actually saved */ + ret = (error == SIEVE_ERROR_NOT_FOUND ? 0 : -1); + } else if (sieve_script_activate(script, (time_t)-1) < 0) { + /* Failed to activate; roll back */ + ret = -1; + (void)sieve_script_delete(script, TRUE); + } + if (script != NULL) + sieve_script_unref(&script); + + if (ret < 0) { + e_error(sctx->event, + "Failed to implicitly activate script `%s' " + "while replacing the default active script", + scriptname); + } + } + + if (ret >= 0) { + struct event_passthrough *e = + event_create_passthrough(sctx->event)-> + set_name("sieve_storage_save_finished"); + e_debug(e->event(), "Finished saving script"); + + /* set INBOX mailbox attribute */ + (void)sieve_storage_sync_script_save(storage, scriptname); + } else { + struct event_passthrough *e = + event_create_passthrough(sctx->event)-> + add_str("error", storage->error)-> + set_name("sieve_storage_save_finished"); + + e_debug(e->event(), "Failed to save script: %s", + storage->error); + } + + sieve_storage_save_deinit(&sctx); + return ret; +} + +void sieve_storage_save_cancel(struct sieve_storage_save_context **_sctx) +{ + struct sieve_storage_save_context *sctx = *_sctx; + struct sieve_storage *storage; + + *_sctx = NULL; + if (sctx == NULL) + return; + + storage = sctx->storage; + + sctx->failed = TRUE; + + sieve_storage_save_cleanup(sctx); + + if (!sctx->finished) + (void)sieve_storage_save_finish(sctx); + + struct event_passthrough *e = + event_create_passthrough(sctx->event)-> + add_str("error", "Canceled")-> + set_name("sieve_storage_save_finished"); + e_debug(e->event(), "Canceled saving script"); + + i_assert(storage->v.save_cancel != NULL); + storage->v.save_cancel(sctx); + + sieve_storage_save_deinit(&sctx); +} + +int sieve_storage_save_as_active(struct sieve_storage *storage, + struct istream *input, time_t mtime) +{ + struct event *event; + int ret; + + event = event_create(storage->event); + event_set_append_log_prefix(event, "active script: save: "); + + struct event_passthrough *e = + event_create_passthrough(event)-> + set_name("sieve_storage_save_started"); + e_debug(e->event(), "Started saving active script"); + + i_assert(storage->v.save_as_active != NULL); + ret = storage->v.save_as_active(storage, input, mtime); + + if (ret >= 0) { + struct event_passthrough *e = + event_create_passthrough(event)-> + set_name("sieve_storage_save_finished"); + e_debug(e->event(), "Finished saving active script"); + } else { + struct event_passthrough *e = + event_create_passthrough(event)-> + add_str("error", storage->error)-> + set_name("sieve_storage_save_finished"); + e_debug(e->event(), "Failed to save active script: %s", + storage->error); + } + + event_unref(&event); + return ret; +} + +int sieve_storage_save_as(struct sieve_storage *storage, struct istream *input, + const char *name) +{ + struct event *event; + int ret; + + event = sieve_storage_save_create_event(storage, name); + + struct event_passthrough *e = + event_create_passthrough(event)-> + set_name("sieve_storage_save_started"); + e_debug(e->event(), "Started saving script"); + + i_assert(storage->v.save_as != NULL); + ret = storage->v.save_as(storage, input, name); + + if (ret >= 0) { + struct event_passthrough *e = + event_create_passthrough(event)-> + set_name("sieve_storage_save_finished"); + e_debug(e->event(), "Finished saving sieve script"); + } else { + struct event_passthrough *e = + event_create_passthrough(event)-> + add_str("error", storage->error)-> + set_name("sieve_storage_save_finished"); + e_debug(e->event(), "Failed to save script: %s", + storage->error); + } + + event_unref(&event); + return ret; +} + +/* + * Checking quota + */ + +bool sieve_storage_quota_validsize(struct sieve_storage *storage, size_t size, + uint64_t *limit_r) +{ + uint64_t max_size; + + max_size = sieve_max_script_size(storage->svinst); + if (max_size > 0 && size > max_size) { + *limit_r = max_size; + return FALSE; + } + + return TRUE; +} + +uint64_t sieve_storage_quota_max_script_size(struct sieve_storage *storage) +{ + return sieve_max_script_size(storage->svinst); +} + +int sieve_storage_quota_havespace(struct sieve_storage *storage, + const char *scriptname, size_t size, + enum sieve_storage_quota *quota_r, + uint64_t *limit_r) +{ + *quota_r = SIEVE_STORAGE_QUOTA_NONE; + *limit_r = 0; + + /* Check the script size */ + if (!sieve_storage_quota_validsize(storage, size, limit_r)) { + *quota_r = SIEVE_STORAGE_QUOTA_MAXSIZE; + return 0; + } + + /* Do we need to scan the storage (quota enabled) ? */ + if (storage->max_scripts == 0 && storage->max_storage == 0) + return 1; + + if (storage->v.quota_havespace == NULL) + return 1; + + return storage->v.quota_havespace(storage, scriptname, size, + quota_r, limit_r); +} + +/* + * Properties + */ + +const char *sieve_storage_location(const struct sieve_storage *storage) +{ + return storage->location; +} + +bool sieve_storage_is_default(const struct sieve_storage *storage) +{ + return storage->is_default; +} + +/* + * Error handling + */ + +void sieve_storage_clear_error(struct sieve_storage *storage) +{ + i_free(storage->error); + storage->error_code = SIEVE_ERROR_NONE; + storage->error = NULL; +} + +void sieve_storage_set_error(struct sieve_storage *storage, + enum sieve_error error, const char *fmt, ...) +{ + va_list va; + + sieve_storage_clear_error(storage); + + if (fmt != NULL) { + va_start(va, fmt); + storage->error = i_strdup_vprintf(fmt, va); + va_end(va); + } + + storage->error_code = error; +} + +void sieve_storage_copy_error(struct sieve_storage *storage, + const struct sieve_storage *source) +{ + sieve_storage_clear_error(storage); + storage->error = i_strdup(source->error); + storage->error_code = source->error_code; +} + +void sieve_storage_set_internal_error(struct sieve_storage *storage) +{ + struct tm *tm; + char str[256]; + + sieve_storage_clear_error(storage); + + /* critical errors may contain sensitive data, so let user + see only "Internal error" with a timestamp to make it + easier to look from log files the actual error message. */ + tm = localtime(&ioloop_time); + + storage->error = + (strftime(str, sizeof(str), CRITICAL_MSG_STAMP, tm) > 0 ? + i_strdup(str) : i_strdup(CRITICAL_MSG)); + + storage->error_code = SIEVE_ERROR_TEMP_FAILURE; +} + +void sieve_storage_set_critical(struct sieve_storage *storage, + const char *fmt, ...) +{ + va_list va; + + if (fmt != NULL) { + if ((storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0) { + va_start(va, fmt); + e_error(storage->svinst->event, "%s storage: %s", + storage->driver_name, + t_strdup_vprintf(fmt, va)); + va_end(va); + + sieve_storage_set_internal_error(storage); + + } else { + sieve_storage_clear_error(storage); + + /* no user is involved while synchronizing, so do it the + normal way */ + va_start(va, fmt); + storage->error = i_strdup_vprintf(fmt, va); + va_end(va); + + storage->error_code = SIEVE_ERROR_TEMP_FAILURE; + } + } +} + +const char * +sieve_storage_get_last_error(struct sieve_storage *storage, + enum sieve_error *error_r) +{ + /* We get here only in error situations, so we have to return some + error. If storage->error is NULL, it means we forgot to set it at + some point.. + */ + + if (error_r != NULL) + *error_r = storage->error_code; + + return storage->error != NULL ? storage->error : "Unknown error"; +} diff --git a/pigeonhole/src/lib-sieve/sieve-storage.h b/pigeonhole/src/lib-sieve/sieve-storage.h new file mode 100644 index 0000000..125a86e --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-storage.h @@ -0,0 +1,187 @@ +#ifndef SIEVE_STORAGE_H +#define SIEVE_STORAGE_H + +#define MAILBOX_ATTRIBUTE_PREFIX_SIEVE \ + MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER"sieve/" +#define MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES \ + MAILBOX_ATTRIBUTE_PREFIX_SIEVE"files/" +#define MAILBOX_ATTRIBUTE_SIEVE_DEFAULT \ + MAILBOX_ATTRIBUTE_PREFIX_SIEVE"default" + +#define MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_LINK 'L' +#define MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_SCRIPT 'S' + +/* + * Storage object + */ + +enum sieve_storage_flags { + /* Storage is opened for read/write access (e.g. ManageSieve) */ + SIEVE_STORAGE_FLAG_READWRITE = 0x01, + /* This storage is used for synchronization (and not normal ManageSieve) + */ + SIEVE_STORAGE_FLAG_SYNCHRONIZING = 0x02 +}; + +struct sieve_storage; + +struct sieve_storage * +sieve_storage_create(struct sieve_instance *svinst, const char *location, + enum sieve_storage_flags flags, enum sieve_error *error_r) + ATTR_NULL(4); +struct sieve_storage * +sieve_storage_create_main(struct sieve_instance *svinst, struct mail_user *user, + enum sieve_storage_flags flags, + enum sieve_error *error_r) ATTR_NULL(4); + +void sieve_storage_ref(struct sieve_storage *storage); +void sieve_storage_unref(struct sieve_storage **_storage); + +/* + * Script access + */ + +struct sieve_script * +sieve_storage_get_script(struct sieve_storage *storage, const char *name, + enum sieve_error *error_r) ATTR_NULL(3); +struct sieve_script * +sieve_storage_open_script(struct sieve_storage *storage, const char *name, + enum sieve_error *error_r) ATTR_NULL(3); +int sieve_storage_check_script(struct sieve_storage *storage, const char *name, + enum sieve_error *error_r) ATTR_NULL(3); + +/* + * Script sequence + */ + +struct sieve_script_sequence * +sieve_storage_get_script_sequence(struct sieve_storage *storage, + enum sieve_error *error_r); + +/* + * Active script + */ + +int sieve_storage_active_script_get_name(struct sieve_storage *storage, + const char **name_r); + +struct sieve_script * +sieve_storage_active_script_open(struct sieve_storage *storage, + enum sieve_error *error_r) ATTR_NULL(2); + +int sieve_storage_active_script_get_last_change(struct sieve_storage *storage, + time_t *last_change_r); + +/* + * Listing scripts in storage + */ + +struct sieve_storage_list_context; + +/* Create a context for listing the scripts in the storage */ +struct sieve_storage_list_context * +sieve_storage_list_init(struct sieve_storage *storage); +/* Get the next script in the storage. */ +const char *sieve_storage_list_next(struct sieve_storage_list_context *lctx, + bool *active_r) ATTR_NULL(2); +/* Destroy the listing context */ +int sieve_storage_list_deinit(struct sieve_storage_list_context **lctx); + +/* + * Saving scripts in storage + */ + +struct sieve_storage_save_context; + +struct sieve_storage_save_context * +sieve_storage_save_init(struct sieve_storage *storage, const char *scriptname, + struct istream *input); + +int sieve_storage_save_continue(struct sieve_storage_save_context *sctx); + +int sieve_storage_save_finish(struct sieve_storage_save_context *sctx); + +struct sieve_script * +sieve_storage_save_get_tempscript(struct sieve_storage_save_context *sctx); + +bool sieve_storage_save_will_activate(struct sieve_storage_save_context *sctx); + +void sieve_storage_save_set_mtime(struct sieve_storage_save_context *sctx, + time_t mtime); + +void sieve_storage_save_cancel(struct sieve_storage_save_context **sctx); + +int sieve_storage_save_commit(struct sieve_storage_save_context **sctx); + +int sieve_storage_save_as(struct sieve_storage *storage, struct istream *input, + const char *name); + +/* Saves input directly as a regular file at the active script path. + * This is needed for the doveadm-sieve plugin. + */ +int sieve_storage_save_as_active(struct sieve_storage *storage, + struct istream *input, time_t mtime); + +/* + * Management + */ + +int sieve_storage_deactivate(struct sieve_storage *storage, time_t mtime); + +/* + * Storage quota + */ + +enum sieve_storage_quota { + SIEVE_STORAGE_QUOTA_NONE, + SIEVE_STORAGE_QUOTA_MAXSIZE, + SIEVE_STORAGE_QUOTA_MAXSCRIPTS, + SIEVE_STORAGE_QUOTA_MAXSTORAGE +}; + +bool sieve_storage_quota_validsize(struct sieve_storage *storage, size_t size, + uint64_t *limit_r); + +uint64_t sieve_storage_quota_max_script_size(struct sieve_storage *storage); + +int sieve_storage_quota_havespace(struct sieve_storage *storage, + const char *scriptname, size_t size, + enum sieve_storage_quota *quota_r, + uint64_t *limit_r); + +/* + * Properties + */ + +const char *sieve_storage_location(const struct sieve_storage *storage) + ATTR_PURE; +bool sieve_storage_is_default(const struct sieve_storage *storage) ATTR_PURE; + +int sieve_storage_is_singular(struct sieve_storage *storage); + +/* + * Error handling + */ + +void sieve_storage_clear_error(struct sieve_storage *storage); + +void sieve_storage_set_error(struct sieve_storage *storage, + enum sieve_error error, const char *fmt, ...) + ATTR_FORMAT(3, 4); +void sieve_storage_set_critical(struct sieve_storage *storage, + const char *fmt, ...) ATTR_FORMAT(2, 3); + +const char *sieve_storage_get_last_error(struct sieve_storage *storage, + enum sieve_error *error_r) + ATTR_NULL(2); + +/* + * + */ + +int sieve_storage_get_last_change(struct sieve_storage *storage, + time_t *last_change_r); +void sieve_storage_set_modified(struct sieve_storage *storage, + time_t mtime); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-stringlist.c b/pigeonhole/src/lib-sieve/sieve-stringlist.c new file mode 100644 index 0000000..17b7d5c --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-stringlist.c @@ -0,0 +1,276 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "str.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" + +/* + * Default implementation + */ + +int sieve_stringlist_read_all +(struct sieve_stringlist *strlist, pool_t pool, + const char * const **list_r) +{ + if ( strlist->read_all == NULL ) { + ARRAY(const char *) items; + string_t *item; + int ret; + + sieve_stringlist_reset(strlist); + + p_array_init(&items, pool, 4); + + item = NULL; + while ( (ret=sieve_stringlist_next_item(strlist, &item)) > 0 ) { + const char *stritem = p_strdup(pool, str_c(item)); + + array_append(&items, &stritem, 1); + } + + (void)array_append_space(&items); + *list_r = array_idx(&items, 0); + + return ( ret < 0 ? -1 : 1 ); + } + + return strlist->read_all(strlist, pool, list_r); +} + +int sieve_stringlist_get_length +(struct sieve_stringlist *strlist) +{ + if ( strlist->get_length == NULL ) { + string_t *item; + int count = 0; + int ret; + + sieve_stringlist_reset(strlist); + while ( (ret=sieve_stringlist_next_item(strlist, &item)) > 0 ) { + count++; + } + sieve_stringlist_reset(strlist); + + return ( ret < 0 ? -1 : count ); + } + + return strlist->get_length(strlist); +} + +/* + * Single Stringlist + */ + +/* Object */ + +static int sieve_single_stringlist_next_item + (struct sieve_stringlist *_strlist, string_t **str_r); +static void sieve_single_stringlist_reset + (struct sieve_stringlist *_strlist); +static int sieve_single_stringlist_get_length + (struct sieve_stringlist *_strlist); + +struct sieve_single_stringlist { + struct sieve_stringlist strlist; + + string_t *value; + + bool end:1; + bool count_empty:1; +}; + +struct sieve_stringlist *sieve_single_stringlist_create +(const struct sieve_runtime_env *renv, string_t *str, bool count_empty) +{ + struct sieve_single_stringlist *strlist; + + strlist = t_new(struct sieve_single_stringlist, 1); + strlist->strlist.runenv = renv; + strlist->strlist.exec_status = SIEVE_EXEC_OK; + strlist->strlist.next_item = sieve_single_stringlist_next_item; + strlist->strlist.reset = sieve_single_stringlist_reset; + strlist->strlist.get_length = sieve_single_stringlist_get_length; + strlist->count_empty = count_empty; + strlist->value = str; + + return &strlist->strlist; +} + +struct sieve_stringlist *sieve_single_stringlist_create_cstr +(const struct sieve_runtime_env *renv, const char *cstr, bool count_empty) +{ + string_t *str = t_str_new_const(cstr, strlen(cstr)); + + return sieve_single_stringlist_create(renv, str, count_empty); +} + +/* Implementation */ + +static int sieve_single_stringlist_next_item +(struct sieve_stringlist *_strlist, string_t **str_r) +{ + struct sieve_single_stringlist *strlist = + (struct sieve_single_stringlist *)_strlist; + + if ( strlist->end ) { + *str_r = NULL; + return 0; + } + + *str_r = strlist->value; + strlist->end = TRUE; + return 1; +} + +static void sieve_single_stringlist_reset +(struct sieve_stringlist *_strlist) +{ + struct sieve_single_stringlist *strlist = + (struct sieve_single_stringlist *)_strlist; + + strlist->end = FALSE; +} + +static int sieve_single_stringlist_get_length +(struct sieve_stringlist *_strlist) +{ + struct sieve_single_stringlist *strlist = + (struct sieve_single_stringlist *)_strlist; + + return ( strlist->count_empty || str_len(strlist->value) > 0 ? 1 : 0 ); +} + +/* + * Index Stringlist + */ + +/* Object */ + +static int sieve_index_stringlist_next_item + (struct sieve_stringlist *_strlist, string_t **str_r); +static void sieve_index_stringlist_reset + (struct sieve_stringlist *_strlist); +static int sieve_index_stringlist_get_length + (struct sieve_stringlist *_strlist); +static void sieve_index_stringlist_set_trace + (struct sieve_stringlist *strlist, bool trace); + +struct sieve_index_stringlist { + struct sieve_stringlist strlist; + + struct sieve_stringlist *source; + + int index; + bool end:1; +}; + +struct sieve_stringlist *sieve_index_stringlist_create +(const struct sieve_runtime_env *renv, struct sieve_stringlist *source, + int index) +{ + struct sieve_index_stringlist *strlist; + + strlist = t_new(struct sieve_index_stringlist, 1); + strlist->strlist.runenv = renv; + strlist->strlist.exec_status = SIEVE_EXEC_OK; + strlist->strlist.next_item = sieve_index_stringlist_next_item; + strlist->strlist.reset = sieve_index_stringlist_reset; + strlist->strlist.get_length = sieve_index_stringlist_get_length; + strlist->strlist.set_trace = sieve_index_stringlist_set_trace; + strlist->source = source; + strlist->index = index; + + return &strlist->strlist; +} + +/* Implementation */ + +static int sieve_index_stringlist_next_item +(struct sieve_stringlist *_strlist, string_t **str_r) +{ + struct sieve_index_stringlist *strlist = + (struct sieve_index_stringlist *)_strlist; + int index, ret; + + if ( strlist->end ) { + *str_r = NULL; + return 0; + } + + if ( strlist->index < 0 ) { + int len = sieve_stringlist_get_length(strlist->source); + if (len < 0) { + _strlist->exec_status = strlist->source->exec_status; + return -1; + } + + if (len < -strlist->index) { + *str_r = NULL; + strlist->end = TRUE; + return 0; + } + index = len + 1 + strlist->index; + } else { + index = strlist->index; + } + + i_assert(index > 0); + while ( index > 0 ) { + if ( (ret=sieve_stringlist_next_item(strlist->source, str_r)) <= 0 ) { + if (ret < 0) + _strlist->exec_status = strlist->source->exec_status; + return ret; + } + + index--; + } + + strlist->end = TRUE; + return 1; +} + +static void sieve_index_stringlist_reset +(struct sieve_stringlist *_strlist) +{ + struct sieve_index_stringlist *strlist = + (struct sieve_index_stringlist *)_strlist; + + sieve_stringlist_reset(strlist->source); + strlist->end = FALSE; +} + +static int sieve_index_stringlist_get_length +(struct sieve_stringlist *_strlist) +{ + struct sieve_index_stringlist *strlist = + (struct sieve_index_stringlist *)_strlist; + int len; + + len = sieve_stringlist_get_length(strlist->source); + if (len < 0) { + _strlist->exec_status = strlist->source->exec_status; + return -1; + } + + if ( strlist->index < 0 ) { + if ( -strlist->index >= len ) + return 0; + } else if ( strlist->index >= len ) { + return 0; + } + + return 1; +} + +static void sieve_index_stringlist_set_trace +(struct sieve_stringlist *_strlist, bool trace) +{ + struct sieve_index_stringlist *strlist = + (struct sieve_index_stringlist *)_strlist; + + sieve_stringlist_set_trace(strlist->source, trace); +} diff --git a/pigeonhole/src/lib-sieve/sieve-stringlist.h b/pigeonhole/src/lib-sieve/sieve-stringlist.h new file mode 100644 index 0000000..1909b7a --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-stringlist.h @@ -0,0 +1,74 @@ +#ifndef SIEVE_STRINGLIST_H +#define SIEVE_STRINGLIST_H + +/* + * Stringlist API + */ + +struct sieve_stringlist { + int (*next_item) + (struct sieve_stringlist *strlist, string_t **str_r); + void (*reset) + (struct sieve_stringlist *strlist); + int (*get_length) + (struct sieve_stringlist *strlist); + + int (*read_all) + (struct sieve_stringlist *strlist, pool_t pool, + const char * const **list_r); + + void (*set_trace) + (struct sieve_stringlist *strlist, bool trace); + + const struct sieve_runtime_env *runenv; + int exec_status; + + bool trace:1; +}; + +static inline void sieve_stringlist_set_trace +(struct sieve_stringlist *strlist, bool trace) +{ + strlist->trace = trace; + + if ( strlist->set_trace != NULL ) + strlist->set_trace(strlist, trace); +} + +static inline int sieve_stringlist_next_item +(struct sieve_stringlist *strlist, string_t **str_r) +{ + return strlist->next_item(strlist, str_r); +} + +static inline void sieve_stringlist_reset +(struct sieve_stringlist *strlist) +{ + strlist->reset(strlist); +} + +int sieve_stringlist_get_length + (struct sieve_stringlist *strlist); + +int sieve_stringlist_read_all + (struct sieve_stringlist *strlist, pool_t pool, + const char * const **list_r); + +/* + * Single Stringlist + */ + +struct sieve_stringlist *sieve_single_stringlist_create + (const struct sieve_runtime_env *renv, string_t *str, bool count_empty); +struct sieve_stringlist *sieve_single_stringlist_create_cstr +(const struct sieve_runtime_env *renv, const char *cstr, bool count_empty); + +/* + * Index Stringlist + */ + +struct sieve_stringlist *sieve_index_stringlist_create + (const struct sieve_runtime_env *renv, struct sieve_stringlist *source, + int index); + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-types.h b/pigeonhole/src/lib-sieve/sieve-types.h new file mode 100644 index 0000000..439b26e --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-types.h @@ -0,0 +1,316 @@ +#ifndef SIEVE_TYPES_H +#define SIEVE_TYPES_H + +#include "lib.h" +#include "smtp-address.h" + +#include <stdio.h> + +/* + * Forward declarations + */ + +struct smtp_params_mail; +struct smtp_params_rcpt; + +struct sieve_instance; +struct sieve_callbacks; + +struct sieve_script; +struct sieve_binary; + +struct sieve_message_data; +struct sieve_script_env; +struct sieve_exec_status; +struct sieve_trace_log; + +/* + * System environment + */ + +enum sieve_flag { + /* Relative paths are resolved to HOME */ + SIEVE_FLAG_HOME_RELATIVE = (1 << 0) +}; + +/* Sieve evaluation can be performed at various different points as messages + are processed. */ +enum sieve_env_location { + /* Unknown */ + SIEVE_ENV_LOCATION_UNKNOWN = 0, + /* "MDA" - evaluation is being performed by a Mail Delivery Agent */ + SIEVE_ENV_LOCATION_MDA, + /* "MTA" - the Sieve script is being evaluated by a Message Transfer Agent */ + SIEVE_ENV_LOCATION_MTA, + /* "MS" - evaluation is being performed by a Message Store */ + SIEVE_ENV_LOCATION_MS +}; + +/* The point relative to final delivery where the Sieve script is being + evaluated. */ +enum sieve_delivery_phase { + SIEVE_DELIVERY_PHASE_UNKNOWN = 0, + SIEVE_DELIVERY_PHASE_PRE, + SIEVE_DELIVERY_PHASE_DURING, + SIEVE_DELIVERY_PHASE_POST, +}; + +struct sieve_environment { + const char *hostname; + const char *domainname; + + const char *base_dir; + const char *username; + const char *home_dir; + const char *temp_dir; + + struct event *event_parent; + + enum sieve_flag flags; + enum sieve_env_location location; + enum sieve_delivery_phase delivery_phase; +}; + +/* + * Callbacks + */ + +struct sieve_callbacks { + const char *(*get_homedir)(void *context); + const char *(*get_setting)(void *context, const char *identifier); +}; + +/* + * Errors + */ + +enum sieve_error { + SIEVE_ERROR_NONE = 0, + + /* Temporary internal error */ + SIEVE_ERROR_TEMP_FAILURE, + /* It's not possible to do the wanted operation */ + SIEVE_ERROR_NOT_POSSIBLE, + /* Invalid parameters (eg. script name not valid) */ + SIEVE_ERROR_BAD_PARAMS, + /* No permission to do the request */ + SIEVE_ERROR_NO_PERMISSION, + /* Out of disk space */ + SIEVE_ERROR_NO_QUOTA, + /* Item (e.g. script or binary) cannot be found */ + SIEVE_ERROR_NOT_FOUND, + /* Item (e.g. script or binary) already exists */ + SIEVE_ERROR_EXISTS, + /* Referenced item (e.g. script or binary) is not valid or currupt */ + SIEVE_ERROR_NOT_VALID, + /* Not allowed to perform the operation because the item is in active use */ + SIEVE_ERROR_ACTIVE, + /* Operation exceeds resource limit */ + SIEVE_ERROR_RESOURCE_LIMIT, +}; + +/* + * Compile flags + */ + +enum sieve_compile_flags { + /* No global extensions are allowed + * (as marked by sieve_global_extensions setting) + */ + SIEVE_COMPILE_FLAG_NOGLOBAL = (1<<0), + /* Script is being uploaded (usually through ManageSieve) */ + SIEVE_COMPILE_FLAG_UPLOADED = (1<<1), + /* Script is being activated (usually through ManageSieve) */ + SIEVE_COMPILE_FLAG_ACTIVATED = (1<<2), + /* Compiled for environment with no access to envelope */ + SIEVE_COMPILE_FLAG_NO_ENVELOPE = (1<<3) +}; + +/* + * Message data + * + * - The mail message + envelope data + */ + +struct sieve_message_data { + struct mail *mail; + + const char *auth_user; + const char *id; + + struct { + const struct smtp_address *mail_from; + const struct smtp_params_mail *mail_params; + + const struct smtp_address *rcpt_to; + const struct smtp_params_rcpt *rcpt_params; + } envelope; +}; + +/* + * Runtime flags + */ + +enum sieve_execute_flags { + /* No global extensions are allowed + * (as marked by sieve_global_extensions setting) + */ + SIEVE_EXECUTE_FLAG_NOGLOBAL = (1<<0), + /* Do not execute (implicit keep) at the end */ + SIEVE_EXECUTE_FLAG_DEFER_KEEP = (1<<1), + /* There is no envelope */ + SIEVE_EXECUTE_FLAG_NO_ENVELOPE = (1<<2), + /* Skip sending responses */ + SIEVE_EXECUTE_FLAG_SKIP_RESPONSES = (1<<3), + /* Log result as info (when absent, only debug logging is performed) */ + SIEVE_EXECUTE_FLAG_LOG_RESULT = (1<<4), +}; + +/* + * Runtime trace settings + */ + +typedef enum { + SIEVE_TRLVL_NONE = 0, + SIEVE_TRLVL_ACTIONS, + SIEVE_TRLVL_COMMANDS, + SIEVE_TRLVL_TESTS, + SIEVE_TRLVL_MATCHING +} sieve_trace_level_t; + +enum { + SIEVE_TRFLG_DEBUG = (1 << 0), + SIEVE_TRFLG_ADDRESSES = (1 << 1) +}; + +struct sieve_trace_config { + sieve_trace_level_t level; + unsigned int flags; +}; + +/* + * Duplicate checking + */ + +enum sieve_duplicate_check_result { + SIEVE_DUPLICATE_CHECK_RESULT_EXISTS = 1, + SIEVE_DUPLICATE_CHECK_RESULT_NOT_FOUND = 0, + SIEVE_DUPLICATE_CHECK_RESULT_FAILURE = -1, + SIEVE_DUPLICATE_CHECK_RESULT_TEMP_FAILURE = -2, +}; + +/* + * Script environment + * + * - Environment for currently executing script + */ + +struct sieve_script_env { + /* Mail-related */ + struct mail_user *user; + const struct message_address *postmaster_address; + const char *default_mailbox; + bool mailbox_autocreate; + bool mailbox_autosubscribe; + + /* External context data */ + + void *script_context; + + /* Callbacks */ + + /* Interface for sending mail */ + void *(*smtp_start) + (const struct sieve_script_env *senv, + const struct smtp_address *mail_from); + /* Add a new recipient */ + void (*smtp_add_rcpt) + (const struct sieve_script_env *senv, void *handle, + const struct smtp_address *rcpt_to); + /* Get an output stream where the message can be written to. The recipients + must already be added before calling this. */ + struct ostream *(*smtp_send) + (const struct sieve_script_env *senv, void *handle); + /* Abort the SMTP transaction after smtp_send() is already issued */ + void (*smtp_abort) + (const struct sieve_script_env *senv, void *handle); + /* Returns 1 on success, 0 on permanent failure, -1 on temporary failure. */ + int (*smtp_finish) + (const struct sieve_script_env *senv, void *handle, + const char **error_r); + + /* Interface for marking and checking duplicates */ + void *(*duplicate_transaction_begin)( + const struct sieve_script_env *senv); + void (*duplicate_transaction_commit)(void **_dup_trans); + void (*duplicate_transaction_rollback)(void **_dup_trans); + + enum sieve_duplicate_check_result + (*duplicate_check)(void *dup_trans, const struct sieve_script_env *senv, + const void *id, size_t id_size); + void (*duplicate_mark)(void *dup_trans, + const struct sieve_script_env *senv, + const void *id, size_t id_size, time_t time); + + /* Interface for rejecting mail */ + int (*reject_mail)(const struct sieve_script_env *senv, + const struct smtp_address *recipient, const char *reason); + + /* Interface for amending result messages */ + const char * + (*result_amend_log_message)(const struct sieve_script_env *senv, + enum log_type log_type, + const char *message); + + /* Execution status record */ + struct sieve_exec_status *exec_status; + + /* Runtime trace*/ + struct sieve_trace_log *trace_log; + struct sieve_trace_config trace_config; +}; + +#define SIEVE_SCRIPT_DEFAULT_MAILBOX(senv) \ + (senv->default_mailbox == NULL ? "INBOX" : senv->default_mailbox ) + +/* + * Resource usage + */ + +struct sieve_resource_usage { + /* The total amount of system + user CPU time consumed while executing + the Sieve script. */ + unsigned int cpu_time_msecs; +}; + +/* + * Script execution status + */ + +struct sieve_exec_status { + struct mail_storage *last_storage; + + struct sieve_resource_usage resource_usage; + + bool message_saved:1; + bool message_forwarded:1; + bool tried_default_save:1; + bool keep_original:1; + bool store_failed:1; + bool significant_action_executed:1; +}; + +/* + * Execution exit codes + */ + +enum sieve_execution_exitcode { + SIEVE_EXEC_OK = 1, + SIEVE_EXEC_FAILURE = 0, + SIEVE_EXEC_TEMP_FAILURE = -1, + SIEVE_EXEC_BIN_CORRUPT = -2, + SIEVE_EXEC_KEEP_FAILED = -3, + SIEVE_EXEC_RESOURCE_LIMIT = -4, +}; + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve-validator.c b/pigeonhole/src/lib-sieve/sieve-validator.c new file mode 100644 index 0000000..bef4a7d --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-validator.c @@ -0,0 +1,1706 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" +#include "array.h" +#include "buffer.h" +#include "mempool.h" +#include "hash.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-script.h" +#include "sieve-ast.h" +#include "sieve-commands.h" +#include "sieve-validator.h" + +#include "sieve-comparators.h" +#include "sieve-address-parts.h" + +/* + * Forward declarations + */ + +static void +sieve_validator_register_core_commands(struct sieve_validator *valdtr); +static void +sieve_validator_register_core_tests(struct sieve_validator *valdtr); + +/* + * Types + */ + +/* Tag registration */ + +struct sieve_tag_registration { + const struct sieve_argument_def *tag_def; + const struct sieve_extension *ext; + + const char *identifier; + int id_code; +}; + +/* Command registration */ + +struct sieve_command_registration { + const struct sieve_command_def *cmd_def; + const struct sieve_extension *ext; + + ARRAY(struct sieve_tag_registration *) normal_tags; + ARRAY(struct sieve_tag_registration *) instanced_tags; + ARRAY(struct sieve_tag_registration *) persistent_tags; +}; + +/* Default (literal) arguments */ + +struct sieve_default_argument { + const struct sieve_argument_def *arg_def; + const struct sieve_extension *ext; + + struct sieve_default_argument *overrides; +}; + +/* + * Validator extension + */ + +struct sieve_validator_extension_reg { + const struct sieve_validator_extension *valext; + const struct sieve_extension *ext; + struct sieve_ast_argument *arg; + void *context; + + bool loaded:1; + bool required:1; +}; + +/* + * Validator + */ + +struct sieve_validator { + pool_t pool; + + struct sieve_instance *svinst; + struct sieve_ast *ast; + struct sieve_script *script; + enum sieve_compile_flags flags; + + struct sieve_error_handler *ehandler; + + bool finished_require; + + /* Registries */ + + HASH_TABLE(const char *, struct sieve_command_registration *) commands; + + ARRAY(struct sieve_validator_extension_reg) extensions; + + /* This is currently a wee bit ugly and needs more thought */ + struct sieve_default_argument default_arguments[SAT_COUNT]; + + /* Default argument processing state (FIXME: ugly) */ + struct sieve_default_argument *current_defarg; + enum sieve_argument_type current_defarg_type; + bool current_defarg_constant; +}; + +/* + * Validator object + */ + +struct sieve_validator * +sieve_validator_create(struct sieve_ast *ast, + struct sieve_error_handler *ehandler, + enum sieve_compile_flags flags) +{ + pool_t pool; + struct sieve_validator *valdtr; + const struct sieve_extension *const *ext_preloaded; + unsigned int i, ext_count; + + pool = pool_alloconly_create("sieve_validator", 16384); + valdtr = p_new(pool, struct sieve_validator, 1); + valdtr->pool = pool; + + valdtr->ehandler = ehandler; + sieve_error_handler_ref(ehandler); + + valdtr->ast = ast; + sieve_ast_ref(ast); + + valdtr->script = sieve_ast_script(ast); + valdtr->svinst = sieve_script_svinst(valdtr->script); + valdtr->flags = flags; + + /* Setup default arguments */ + valdtr->default_arguments[SAT_NUMBER].arg_def = &number_argument; + valdtr->default_arguments[SAT_NUMBER].ext = NULL; + valdtr->default_arguments[SAT_VAR_STRING].arg_def = &string_argument; + valdtr->default_arguments[SAT_VAR_STRING].ext = NULL; + valdtr->default_arguments[SAT_CONST_STRING].arg_def = &string_argument; + valdtr->default_arguments[SAT_CONST_STRING].ext = NULL; + valdtr->default_arguments[SAT_STRING_LIST].arg_def = &string_list_argument; + valdtr->default_arguments[SAT_STRING_LIST].ext = NULL; + + /* Setup storage for extension contexts */ + p_array_init(&valdtr->extensions, pool, + sieve_extensions_get_count(valdtr->svinst)); + + /* Setup command registry */ + hash_table_create(&valdtr->commands, pool, 0, strcase_hash, strcasecmp); + sieve_validator_register_core_commands(valdtr); + sieve_validator_register_core_tests(valdtr); + + /* Pre-load core language features implemented as 'extensions' */ + ext_preloaded = + sieve_extensions_get_preloaded(valdtr->svinst, &ext_count); + for (i = 0; i < ext_count; i++) { + const struct sieve_extension_def *ext_def = + ext_preloaded[i]->def; + + if (ext_def != NULL && ext_def->validator_load != NULL) + (void)ext_def->validator_load(ext_preloaded[i], valdtr); + } + + return valdtr; +} + +void sieve_validator_free(struct sieve_validator **valdtr) +{ + const struct sieve_validator_extension_reg *extrs; + unsigned int ext_count, i; + + hash_table_destroy(&(*valdtr)->commands); + sieve_ast_unref(&(*valdtr)->ast); + + sieve_error_handler_unref(&(*valdtr)->ehandler); + + /* Signal registered extensions that the validator is being destroyed */ + extrs = array_get(&(*valdtr)->extensions, &ext_count); + for (i = 0; i < ext_count; i++) { + if (extrs[i].valext != NULL && extrs[i].valext->free != NULL) + extrs[i].valext->free(extrs[i].ext, *valdtr, + extrs[i].context); + } + + pool_unref(&(*valdtr)->pool); + + *valdtr = NULL; +} + +/* + * Accessors + */ + +// FIXME: build validate environment + +pool_t sieve_validator_pool(struct sieve_validator *valdtr) +{ + return valdtr->pool; +} + +struct sieve_error_handler * +sieve_validator_error_handler(struct sieve_validator *valdtr) +{ + return valdtr->ehandler; +} + +struct sieve_ast *sieve_validator_ast(struct sieve_validator *valdtr) +{ + return valdtr->ast; +} + +struct sieve_script *sieve_validator_script(struct sieve_validator *valdtr) +{ + return valdtr->script; +} + +struct sieve_instance *sieve_validator_svinst(struct sieve_validator *valdtr) +{ + return valdtr->svinst; +} + +enum sieve_compile_flags +sieve_validator_compile_flags(struct sieve_validator *valdtr) +{ + return valdtr->flags; +} + +/* + * Command registry + */ + +/* Dummy command object to mark unknown commands in the registry */ + +static bool _cmd_unknown_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *cmd ATTR_UNUSED) +{ + i_unreached(); + return FALSE; +} + +static const struct sieve_command_def unknown_command = { + .identifier = "", + .type = SCT_NONE, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = _cmd_unknown_validate +}; + +/* Registration of the core commands of the language */ + +static void +sieve_validator_register_core_tests(struct sieve_validator *valdtr) +{ + unsigned int i; + + for (i = 0; i < sieve_core_tests_count; i++) { + sieve_validator_register_command(valdtr, NULL, + sieve_core_tests[i]); + } +} + +static void +sieve_validator_register_core_commands(struct sieve_validator *valdtr) +{ + unsigned int i; + + for (i = 0; i < sieve_core_commands_count; i++) { + sieve_validator_register_command(valdtr, NULL, + sieve_core_commands[i]); + } +} + +/* Registry functions */ + +static struct sieve_command_registration * +sieve_validator_find_command_registration(struct sieve_validator *valdtr, + const char *command) +{ + return hash_table_lookup(valdtr->commands, command); +} + +static struct sieve_command_registration * +_sieve_validator_register_command(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + const struct sieve_command_def *cmd_def, + const char *identifier) +{ + struct sieve_command_registration *cmd_reg = + p_new(valdtr->pool, struct sieve_command_registration, 1); + + cmd_reg->cmd_def = cmd_def; + cmd_reg->ext = ext; + + hash_table_insert(valdtr->commands, identifier, cmd_reg); + + return cmd_reg; +} + +void sieve_validator_register_command(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + const struct sieve_command_def *cmd_def) +{ + struct sieve_command_registration *cmd_reg = + sieve_validator_find_command_registration( + valdtr, cmd_def->identifier); + + if (cmd_reg == NULL) { + cmd_reg = _sieve_validator_register_command( + valdtr, ext, cmd_def, cmd_def->identifier); + } else { + cmd_reg->cmd_def = cmd_def; + cmd_reg->ext = ext; + } + + if (cmd_def->registered != NULL) + cmd_def->registered(valdtr, ext, cmd_reg); +} + +static void +sieve_validator_register_unknown_command(struct sieve_validator *valdtr, + const char *command) +{ + struct sieve_command_registration *cmd_reg = + sieve_validator_find_command_registration(valdtr, command); + + if (cmd_reg == NULL) { + (void)_sieve_validator_register_command( + valdtr, NULL, &unknown_command, command); + } else { + i_assert(cmd_reg->cmd_def == NULL); + cmd_reg->cmd_def = &unknown_command; + } +} + +/*const struct sieve_command *sieve_validator_find_command +(struct sieve_validator *valdtr, const char *command) +{ + struct sieve_command_registration *cmd_reg = + sieve_validator_find_command_registration(valdtr, command); + + return ( record == NULL ? NULL : record->command ); +}*/ + +/* + * Per-command tagged argument registry + */ + +/* Dummy argument object to mark unknown arguments in the registry */ + +static bool +_unknown_tag_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_ast_argument **arg ATTR_UNUSED, + struct sieve_command *tst ATTR_UNUSED) +{ + i_unreached(); + return FALSE; +} + +static const struct sieve_argument_def _unknown_tag = { + .identifier = "", + .validate = _unknown_tag_validate, +}; + +static inline bool +_tag_registration_is_unknown(struct sieve_tag_registration *tag_reg) +{ + return (tag_reg != NULL && tag_reg->tag_def == &_unknown_tag); +} + +/* Registry functions */ + +static void +_sieve_validator_register_tag(struct sieve_validator *valdtr, + struct sieve_command_registration *cmd_reg, + const struct sieve_extension *ext, + const struct sieve_argument_def *tag_def, + const char *identifier, int id_code) +{ + struct sieve_tag_registration *reg; + + reg = p_new(valdtr->pool, struct sieve_tag_registration, 1); + reg->ext = ext; + reg->tag_def = tag_def; + reg->id_code = id_code; + if (identifier == NULL) + reg->identifier = tag_def->identifier; + else + reg->identifier = p_strdup(valdtr->pool, identifier); + + if (!array_is_created(&cmd_reg->normal_tags)) + p_array_init(&cmd_reg->normal_tags, valdtr->pool, 4); + + array_append(&cmd_reg->normal_tags, ®, 1); +} + +void sieve_validator_register_persistent_tag( + struct sieve_validator *valdtr, const char *command, + const struct sieve_extension *ext, + const struct sieve_argument_def *tag_def) +{ + /* Add the tag to the persistent tags list if necessary */ + if (tag_def->validate_persistent != NULL) { + struct sieve_command_registration *cmd_reg = + sieve_validator_find_command_registration( + valdtr, command); + + if (cmd_reg == NULL) { + cmd_reg = _sieve_validator_register_command( + valdtr, NULL, NULL, command); + } + + struct sieve_tag_registration *reg; + + if (!array_is_created(&cmd_reg->persistent_tags)) { + p_array_init(&cmd_reg->persistent_tags, + valdtr->pool, 4); + } else { + struct sieve_tag_registration *reg_idx; + + /* Avoid dupplicate registration */ + array_foreach_elem(&cmd_reg->persistent_tags, reg_idx) { + if (reg_idx->tag_def == tag_def) + return; + } + } + + reg = p_new(valdtr->pool, struct sieve_tag_registration, 1); + reg->ext = ext; + reg->tag_def = tag_def; + reg->id_code = -1; + + array_append(&cmd_reg->persistent_tags, ®, 1); + } +} + +void sieve_validator_register_external_tag( + struct sieve_validator *valdtr, const char *command, + const struct sieve_extension *ext, + const struct sieve_argument_def *tag_def, int id_code) +{ + struct sieve_command_registration *cmd_reg = + sieve_validator_find_command_registration(valdtr, command); + + if (cmd_reg == NULL) { + cmd_reg = _sieve_validator_register_command( + valdtr, NULL, NULL, command); + } + + _sieve_validator_register_tag(valdtr, cmd_reg, ext, tag_def, + NULL, id_code); +} + +void sieve_validator_register_tag( + struct sieve_validator *valdtr, + struct sieve_command_registration *cmd_reg, + const struct sieve_extension *ext, + const struct sieve_argument_def *tag_def, int id_code) +{ + if (tag_def->is_instance_of == NULL) { + _sieve_validator_register_tag(valdtr, cmd_reg, ext, tag_def, + NULL, id_code); + } else { + struct sieve_tag_registration *reg = + p_new(valdtr->pool, struct sieve_tag_registration, 1); + reg->ext = ext; + reg->tag_def = tag_def; + reg->id_code = id_code; + + if (!array_is_created(&cmd_reg->instanced_tags)) + p_array_init(&cmd_reg->instanced_tags, valdtr->pool, 4); + + array_append(&cmd_reg->instanced_tags, ®, 1); + } +} + +static void +sieve_validator_register_unknown_tag(struct sieve_validator *valdtr, + struct sieve_command_registration *cmd_reg, + const char *tag) +{ + _sieve_validator_register_tag(valdtr, cmd_reg, NULL, + &_unknown_tag, tag, 0); +} + +static struct sieve_tag_registration * +_sieve_validator_command_tag_get(struct sieve_validator *valdtr, + struct sieve_command *cmd, + const char *tag, void **data) +{ + struct sieve_command_registration *cmd_reg = cmd->reg; + struct sieve_tag_registration * const *regs; + unsigned int i, reg_count; + + /* First check normal tags */ + if (array_is_created(&cmd_reg->normal_tags)) { + regs = array_get(&cmd_reg->normal_tags, ®_count); + + for (i = 0; i < reg_count; i++) { + if (regs[i]->tag_def != NULL && + strcasecmp(regs[i]->identifier, tag) == 0) { + + return regs[i]; + } + } + } + + /* Not found so far, try the instanced tags */ + if (array_is_created(&cmd_reg->instanced_tags)) { + regs = array_get(&cmd_reg->instanced_tags, ®_count); + + for (i = 0; i < reg_count; i++) { + if (regs[i]->tag_def != NULL) { + if (regs[i]->tag_def->is_instance_of( + valdtr, cmd, regs[i]->ext, tag, data)) + return regs[i]; + } + } + } + + return NULL; +} + +static bool +sieve_validator_command_tag_exists(struct sieve_validator *valdtr, + struct sieve_command *cmd, const char *tag) +{ + return (_sieve_validator_command_tag_get(valdtr, cmd, + tag, NULL) != NULL); +} + +static struct sieve_tag_registration * +sieve_validator_command_tag_get(struct sieve_validator *valdtr, + struct sieve_command *cmd, + struct sieve_ast_argument *arg, void **data) +{ + const char *tag = sieve_ast_argument_tag(arg); + + return _sieve_validator_command_tag_get(valdtr, cmd, tag, data); +} + +/* + * Extension support + */ + +static bool +sieve_validator_extensions_check_conficts(struct sieve_validator *valdtr, + struct sieve_ast_argument *ext_arg, + const struct sieve_extension *ext) +{ + struct sieve_validator_extension_reg *ext_reg; + struct sieve_validator_extension_reg *regs; + unsigned int count, i; + + if (ext->id < 0) + return TRUE; + + ext_reg = array_idx_get_space(&valdtr->extensions, + (unsigned int) ext->id); + + regs = array_get_modifiable(&valdtr->extensions, &count); + for (i = 0; i < count; i++) { + bool required = ext_reg->required && regs[i].required; + + if (regs[i].ext == NULL) + continue; + if (regs[i].ext == ext) + continue; + if (!regs[i].loaded) + continue; + + /* Check this extension vs other extension */ + if (ext_reg->valext != NULL && + ext_reg->valext->check_conflict != NULL) { + struct sieve_ast_argument *this_ext_arg = + (ext_arg == NULL ? regs[i].arg : ext_arg); + + if (!ext_reg->valext->check_conflict( + ext, valdtr, ext_reg->context, this_ext_arg, + regs[i].ext, required)) + return FALSE; + } + + /* Check other extension vs this extension */ + if (regs[i].valext != NULL && + regs[i].valext->check_conflict != NULL) { + if (!regs[i].valext->check_conflict( + regs[i].ext, valdtr, regs[i].context, + regs[i].arg, ext, required)) + return FALSE; + } + } + return TRUE; +} + +bool sieve_validator_extension_load(struct sieve_validator *valdtr, + struct sieve_command *cmd, + struct sieve_ast_argument *ext_arg, + const struct sieve_extension *ext, + bool required) +{ + const struct sieve_extension_def *extdef = ext->def; + struct sieve_validator_extension_reg *reg = NULL; + + if (ext->global && + (valdtr->flags & SIEVE_COMPILE_FLAG_NOGLOBAL) != 0) { + const char *cmd_prefix = (cmd == NULL ? "" : + t_strdup_printf("%s %s: ", + sieve_command_identifier(cmd), + sieve_command_type_name(cmd))); + sieve_argument_validate_error( + valdtr, ext_arg, + "%sfailed to load Sieve capability `%s': " + "its use is restricted to global scripts", + cmd_prefix, sieve_extension_name(ext)); + return FALSE; + } + + /* Register extension no matter what and store the + * AST argument registering it */ + if (ext->id >= 0) { + reg = array_idx_get_space(&valdtr->extensions, + (unsigned int)ext->id); + i_assert(reg->ext == NULL || reg->ext == ext); + reg->ext = ext; + reg->required = reg->required || required; + if (reg->arg == NULL) + reg->arg = ext_arg; + } + + if (extdef->validator_load != NULL && + !extdef->validator_load(ext, valdtr)) { + const char *cmd_prefix = (cmd == NULL ? "" : + t_strdup_printf("%s %s: ", + sieve_command_identifier(cmd), + sieve_command_type_name(cmd))); + sieve_argument_validate_error( + valdtr, ext_arg, + "%sfailed to load Sieve capability `%s'", + cmd_prefix, sieve_extension_name(ext)); + return FALSE; + } + + /* Check conflicts with other extensions */ + if (!sieve_validator_extensions_check_conficts(valdtr, ext_arg, ext)) + return FALSE; + + /* Link extension to AST for use at code generation */ + if (reg != NULL) { + sieve_ast_extension_link(valdtr->ast, ext, reg->required); + reg->loaded = TRUE; + } + + return TRUE; +} + +const struct sieve_extension * +sieve_validator_extension_load_by_name(struct sieve_validator *valdtr, + struct sieve_command *cmd, + struct sieve_ast_argument *ext_arg, + const char *ext_name) +{ + const struct sieve_extension *ext; + + ext = sieve_extension_get_by_name(valdtr->svinst, ext_name); + + if (ext == NULL || ext->def == NULL || !ext->enabled) { + unsigned int i; + bool core_test = FALSE; + bool core_command = FALSE; + + for (i = 0; !core_command && i < sieve_core_commands_count; + i++) { + if (strcasecmp(sieve_core_commands[i]->identifier, + ext_name) == 0) + core_command = TRUE; + } + + for (i = 0; !core_test && i < sieve_core_tests_count; i++) { + if (strcasecmp(sieve_core_tests[i]->identifier, + ext_name) == 0) + core_test = TRUE; + } + + if (core_test || core_command) { + sieve_argument_validate_error( + valdtr, ext_arg, + "%s %s: `%s' is not known as a Sieve capability, " + "but it is known as a Sieve %s that is always available", + sieve_command_identifier(cmd), + sieve_command_type_name(cmd), + str_sanitize(ext_name, 128), + (core_test ? "test" : "command")); + } else { + sieve_argument_validate_error( + valdtr, ext_arg, + "%s %s: unknown Sieve capability `%s'", + sieve_command_identifier(cmd), + sieve_command_type_name(cmd), + str_sanitize(ext_name, 128)); + } + return NULL; + } + + if (!sieve_validator_extension_load(valdtr, cmd, ext_arg, ext, TRUE)) + return NULL; + + return ext; +} + +const struct sieve_extension * +sieve_validator_extension_load_implicit(struct sieve_validator *valdtr, + const char *ext_name) +{ + const struct sieve_extension *ext; + + ext = sieve_extension_get_by_name(valdtr->svinst, ext_name); + + if (ext == NULL || ext->def == NULL) + return NULL; + + if (!sieve_validator_extension_load(valdtr, NULL, NULL, ext, TRUE)) + return NULL; + + return ext; +} + +void sieve_validator_extension_register( + struct sieve_validator *valdtr, const struct sieve_extension *ext, + const struct sieve_validator_extension *valext, void *context) +{ + struct sieve_validator_extension_reg *reg; + + if (ext->id < 0) + return; + + reg = array_idx_get_space(&valdtr->extensions, (unsigned int) ext->id); + i_assert(reg->ext == NULL || reg->ext == ext); + reg->ext = ext; + reg->valext = valext; + reg->context = context; +} + +bool sieve_validator_extension_loaded(struct sieve_validator *valdtr, + const struct sieve_extension *ext) +{ + const struct sieve_validator_extension_reg *reg; + + if (ext->id < 0 || ext->id >= (int) array_count(&valdtr->extensions)) + return FALSE; + + reg = array_idx(&valdtr->extensions, (unsigned int) ext->id); + + return (reg->loaded); +} + +void sieve_validator_extension_set_context(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + void *context) +{ + struct sieve_validator_extension_reg *reg; + + if (ext->id < 0) + return; + + reg = array_idx_get_space(&valdtr->extensions, (unsigned int) ext->id); + reg->context = context; +} + +void *sieve_validator_extension_get_context(struct sieve_validator *valdtr, + const struct sieve_extension *ext) +{ + const struct sieve_validator_extension_reg *reg; + + if (ext->id < 0 || ext->id >= (int) array_count(&valdtr->extensions)) + return NULL; + + reg = array_idx(&valdtr->extensions, (unsigned int) ext->id); + + return reg->context; +} + +/* + * Overriding the default literal arguments + */ + +void sieve_validator_argument_override(struct sieve_validator *valdtr, + enum sieve_argument_type type, + const struct sieve_extension *ext, + const struct sieve_argument_def *arg_def) +{ + struct sieve_default_argument *arg; + + if (valdtr->default_arguments[type].arg_def != NULL) { + arg = p_new(valdtr->pool, struct sieve_default_argument, 1); + *arg = valdtr->default_arguments[type]; + + valdtr->default_arguments[type].overrides = arg; + } + + valdtr->default_arguments[type].arg_def = arg_def; + valdtr->default_arguments[type].ext = ext; +} + +static bool +sieve_validator_argument_default_activate(struct sieve_validator *valdtr, + struct sieve_command *cmd, + struct sieve_default_argument *defarg, + struct sieve_ast_argument *arg) +{ + bool result = TRUE; + struct sieve_default_argument *prev_defarg; + + prev_defarg = valdtr->current_defarg; + valdtr->current_defarg = defarg; + + if (arg->argument == NULL) { + arg->argument = sieve_argument_create(arg->ast, defarg->arg_def, + defarg->ext, 0); + } else { + arg->argument->def = defarg->arg_def; + arg->argument->ext = defarg->ext; + } + + if (defarg->arg_def != NULL && defarg->arg_def->validate != NULL) + result = defarg->arg_def->validate(valdtr, &arg, cmd); + + valdtr->current_defarg = prev_defarg; + + return result; +} + +bool sieve_validator_argument_activate_super(struct sieve_validator *valdtr, + struct sieve_command *cmd, + struct sieve_ast_argument *arg, + bool constant ATTR_UNUSED) +{ + struct sieve_default_argument *defarg; + + if (valdtr->current_defarg == NULL || + valdtr->current_defarg->overrides == NULL) + return FALSE; + + if (valdtr->current_defarg->overrides->arg_def == &string_argument) { + switch (valdtr->current_defarg_type) { + case SAT_CONST_STRING: + if (!valdtr->current_defarg_constant) { + valdtr->current_defarg_type = SAT_VAR_STRING; + defarg = &valdtr->default_arguments[SAT_VAR_STRING]; + } else { + defarg = valdtr->current_defarg->overrides; + } + break; + case SAT_VAR_STRING: + defarg = valdtr->current_defarg->overrides; + break; + default: + return FALSE; + } + } else { + defarg = valdtr->current_defarg->overrides; + } + + return sieve_validator_argument_default_activate(valdtr, cmd, + defarg, arg); +} + +/* + * Argument Validation API + */ + +bool sieve_validator_argument_activate(struct sieve_validator *valdtr, + struct sieve_command *cmd, + struct sieve_ast_argument *arg, + bool constant) +{ + struct sieve_default_argument *defarg; + + switch (sieve_ast_argument_type(arg)) { + case SAAT_NUMBER: + valdtr->current_defarg_type = SAT_NUMBER; + break; + case SAAT_STRING: + valdtr->current_defarg_type = SAT_CONST_STRING; + break; + case SAAT_STRING_LIST: + valdtr->current_defarg_type = SAT_STRING_LIST; + break; + default: + return FALSE; + } + + valdtr->current_defarg_constant = constant; + defarg = &valdtr->default_arguments[valdtr->current_defarg_type]; + + if (!constant && defarg->arg_def == &string_argument) { + valdtr->current_defarg_type = SAT_VAR_STRING; + defarg = &valdtr->default_arguments[SAT_VAR_STRING]; + } + + return sieve_validator_argument_default_activate(valdtr, cmd, + defarg, arg); +} + +bool sieve_validate_positional_argument(struct sieve_validator *valdtr, + struct sieve_command *cmd, + struct sieve_ast_argument *arg, + const char *arg_name, + unsigned int arg_pos, + enum sieve_ast_argument_type req_type) +{ + i_assert(arg != NULL); + + if (sieve_ast_argument_type(arg) != req_type && + (sieve_ast_argument_type(arg) != SAAT_STRING || + req_type != SAAT_STRING_LIST)) + { + sieve_argument_validate_error( + valdtr, arg, + "the %s %s expects %s as argument %d (%s), " + "but %s was found", + sieve_command_identifier(cmd), + sieve_command_type_name(cmd), + sieve_ast_argument_type_name(req_type), + arg_pos, arg_name, sieve_ast_argument_name(arg)); + return FALSE; + } + + return TRUE; +} + +bool sieve_validate_tag_parameter(struct sieve_validator *valdtr, + struct sieve_command *cmd, + struct sieve_ast_argument *tag, + struct sieve_ast_argument *param, + const char *arg_name, unsigned int arg_pos, + enum sieve_ast_argument_type req_type, + bool constant) +{ + i_assert(tag != NULL); + + if (param == NULL) { + const char *position = (arg_pos == 0 ? "" : + t_strdup_printf(" %d (%s)", arg_pos, arg_name)); + + sieve_argument_validate_error( + valdtr, tag, + "the :%s tag for the %s %s requires %s as parameter%s, " + "but no parameters were found", + sieve_ast_argument_tag(tag), + sieve_command_identifier(cmd), + sieve_command_type_name(cmd), + sieve_ast_argument_type_name(req_type), position); + return FALSE; + } + + if (sieve_ast_argument_type(param) != req_type && + (sieve_ast_argument_type(param) != SAAT_STRING || + req_type != SAAT_STRING_LIST)) + { + const char *position = (arg_pos == 0 ? "" : + t_strdup_printf(" %d (%s)", arg_pos, arg_name)); + + sieve_argument_validate_error( + valdtr, param, + "the :%s tag for the %s %s requires %s as parameter%s, " + "but %s was found", + sieve_ast_argument_tag(tag), + sieve_command_identifier(cmd), + sieve_command_type_name(cmd), + sieve_ast_argument_type_name(req_type), position, + sieve_ast_argument_name(param)); + return FALSE; + } + + if (!sieve_validator_argument_activate(valdtr, cmd, param, constant)) + return FALSE; + + param->argument->id_code = tag->argument->id_code; + + return TRUE; +} + +/* + * Command argument validation + */ + +static bool +sieve_validate_command_arguments(struct sieve_validator *valdtr, + struct sieve_command *cmd) +{ + int arg_count = cmd->def->positional_args; + int real_count = 0; + struct sieve_ast_argument *arg; + struct sieve_command_registration *cmd_reg = cmd->reg; + + /* Resolve tagged arguments */ + arg = sieve_ast_argument_first(cmd->ast_node); + while (arg != NULL) { + void *arg_data = NULL; + struct sieve_tag_registration *tag_reg; + const struct sieve_argument_def *tag_def; + + if (sieve_ast_argument_type(arg) != SAAT_TAG) { + arg = sieve_ast_argument_next(arg); + continue; + } + + tag_reg = sieve_validator_command_tag_get(valdtr, cmd, + arg, &arg_data); + + if (tag_reg == NULL) { + sieve_argument_validate_error( + valdtr, arg, + "unknown tagged argument ':%s' for the %s %s " + "(reported only once at first occurrence)", + sieve_ast_argument_tag(arg), + sieve_command_identifier(cmd), + sieve_command_type_name(cmd)); + sieve_validator_register_unknown_tag( + valdtr, cmd_reg, sieve_ast_argument_tag(arg)); + return FALSE; + } + + /* Check whether previously tagged as unknown */ + if (_tag_registration_is_unknown(tag_reg)) + return FALSE; + + tag_def = tag_reg->tag_def; + + /* Assign the tagged argument type to the ast for later + reference */ + arg->argument = sieve_argument_create( + arg->ast, tag_def, tag_reg->ext, tag_reg->id_code); + arg->argument->data = arg_data; + + arg = sieve_ast_argument_next(arg); + } + + /* Validate tagged arguments */ + arg = sieve_ast_argument_first(cmd->ast_node); + while (arg != NULL && sieve_ast_argument_type(arg) == SAAT_TAG) { + const struct sieve_argument_def *tag_def = arg->argument->def; + struct sieve_ast_argument *parg; + + /* Scan backwards for any duplicates */ + if ((tag_def->flags & SIEVE_ARGUMENT_FLAG_MULTIPLE) == 0) { + parg = sieve_ast_argument_prev(arg); + while (parg != NULL) { + if ((sieve_ast_argument_type(parg) == SAAT_TAG && + parg->argument->def == tag_def) || + (arg->argument->id_code > 0 && + parg->argument != NULL && + parg->argument->id_code == arg->argument->id_code)) + { + const char *tag_id = sieve_ast_argument_tag(arg); + const char *tag_desc = + strcmp(tag_def->identifier, tag_id) != 0 ? + t_strdup_printf("%s argument (:%s)", + tag_def->identifier, tag_id) : + t_strdup_printf(":%s argument", + tag_def->identifier); + + sieve_argument_validate_error( + valdtr, arg, + "encountered duplicate %s for the %s %s", + tag_desc, sieve_command_identifier(cmd), + sieve_command_type_name(cmd)); + + return FALSE; + } + + parg = sieve_ast_argument_prev(parg); + } + } + + /* Call the validation function for the tag (if present) + Fail if the validation fails: + Let's not whine multiple times about a single command + having multiple bad arguments... + */ + if (tag_def->validate != NULL) { + if (!tag_def->validate(valdtr, &arg, cmd)) + return FALSE; + } else { + arg = sieve_ast_argument_next(arg); + } + } + + /* Remaining arguments should be positional (tags are not allowed + here) */ + cmd->first_positional = arg; + + while (arg != NULL) { + if (sieve_ast_argument_type(arg) == SAAT_TAG) { + sieve_argument_validate_error( + valdtr, arg, + "encountered an unexpected tagged argument ':%s' " + "while validating positional arguments for the %s %s", + sieve_ast_argument_tag(arg), + sieve_command_identifier(cmd), + sieve_command_type_name(cmd)); + return FALSE; + } + + real_count++; + + arg = sieve_ast_argument_next(arg); + } + + /* Check the required count versus the real number of arguments */ + if (arg_count >= 0 && real_count != arg_count) { + sieve_command_validate_error( + valdtr, cmd, + "the %s %s requires %d positional argument(s), " + "but %d is/are specified", + sieve_command_identifier(cmd), + sieve_command_type_name(cmd), + arg_count, real_count); + return FALSE; + } + + /* Call initial validation for persistent arguments */ + if (array_is_created(&cmd_reg->persistent_tags)) { + struct sieve_tag_registration * const *regs; + unsigned int i, reg_count; + + regs = array_get(&cmd_reg->persistent_tags, ®_count); + for (i = 0; i < reg_count; i++) { + const struct sieve_argument_def *tag_def = + regs[i]->tag_def; + + if (tag_def != NULL && + tag_def->validate_persistent != NULL) { + /* To be sure */ + if (!tag_def->validate_persistent( + valdtr, cmd, regs[i]->ext)) + return FALSE; + } + } + } + + return TRUE; +} + +static bool +sieve_validate_arguments_context(struct sieve_validator *valdtr, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = + sieve_command_first_argument(cmd); + + while (arg != NULL) { + const struct sieve_argument *argument = arg->argument; + + if (argument != NULL && argument->def != NULL && + argument->def->validate_context != NULL) { + + if (!argument->def->validate_context(valdtr, arg, cmd)) + return FALSE; + } + + arg = sieve_ast_argument_next(arg); + } + + return TRUE; +} + +/* + * Command Validation API + */ + +static bool +sieve_validate_command_subtests(struct sieve_validator *valdtr, + struct sieve_command *cmd, + const unsigned int count) +{ + switch (count) { + case 0: + if (sieve_ast_test_count(cmd->ast_node) > 0) { + /* Unexpected command specified */ + enum sieve_command_type ctype = SCT_NONE; + struct sieve_command_registration *cmd_reg; + struct sieve_ast_node *test = + sieve_ast_test_first(cmd->ast_node); + + cmd_reg = sieve_validator_find_command_registration( + valdtr, test->identifier); + + /* First check what we are dealing with */ + if (cmd_reg != NULL && cmd_reg->cmd_def != NULL) + ctype = cmd_reg->cmd_def->type; + + switch (ctype) { + case SCT_TEST: /* Spurious test */ + case SCT_HYBRID: + sieve_command_validate_error( + valdtr, cmd, + "the %s %s accepts no sub-tests, " + "but tests are specified", + sieve_command_identifier(cmd), + sieve_command_type_name(cmd)); + break; + case SCT_NONE: /* Unknown command */ + /* Is it perhaps a tag for which the ':' was + omitted ? */ + if (sieve_validator_command_tag_exists( + valdtr, cmd, test->identifier)) { + sieve_command_validate_error( + valdtr, cmd, + "missing colon ':' before ':%s' tag in %s %s", + test->identifier, + sieve_command_identifier(cmd), + sieve_command_type_name(cmd)); + break; + } + /* Fall through */ + case SCT_COMMAND: + sieve_command_validate_error( + valdtr, cmd, + "missing semicolon ';' after %s %s", + sieve_command_identifier(cmd), + sieve_command_type_name(cmd)); + break; + } + return FALSE; + } + break; + case 1: + if (sieve_ast_test_count(cmd->ast_node) == 0) { + sieve_command_validate_error( + valdtr, cmd, + "the %s %s requires one sub-test, " + "but none is specified", + sieve_command_identifier(cmd), + sieve_command_type_name(cmd)); + return FALSE; + + } else if (sieve_ast_test_count(cmd->ast_node) > 1 || + cmd->ast_node->test_list) { + sieve_command_validate_error( + valdtr, cmd, + "the %s %s requires one sub-test, " + "but a list of tests is specified", + sieve_command_identifier(cmd), + sieve_command_type_name(cmd)); + return FALSE; + } + break; + default: + if (sieve_ast_test_count(cmd->ast_node) == 0) { + sieve_command_validate_error( + valdtr, cmd, + "the %s %s requires a list of sub-tests, " + "but none is specified", + sieve_command_identifier(cmd), + sieve_command_type_name(cmd)); + return FALSE; + } else if (sieve_ast_test_count(cmd->ast_node) == 1 && + !cmd->ast_node->test_list) { + sieve_command_validate_error( + valdtr, cmd, + "the %s %s requires a list of sub-tests, " + "but a single test is specified", + sieve_command_identifier(cmd), + sieve_command_type_name(cmd)); + return FALSE; + } + break; + } + + return TRUE; +} + +static bool +sieve_validate_command_block(struct sieve_validator *valdtr, + struct sieve_command *cmd, bool block_allowed, + bool block_required) +{ + i_assert(cmd->ast_node->type == SAT_COMMAND); + + if (block_required) { + if (!cmd->ast_node->block) { + sieve_command_validate_error( + valdtr, cmd, + "the %s command requires a command block, " + "but it is missing", + sieve_command_identifier(cmd)); + return FALSE; + } + } else if (!block_allowed && cmd->ast_node->block) { + sieve_command_validate_error( + valdtr, cmd, + "the %s command does not accept a command block, " + "but one is specified anyway", + sieve_command_identifier(cmd)); + return FALSE; + } + + return TRUE; +} + +/* + * AST Validation + */ + +static bool +sieve_validate_test_list(struct sieve_validator *valdtr, + struct sieve_ast_node *test_list, int *const_r); +static bool +sieve_validate_block(struct sieve_validator *valdtr, + struct sieve_ast_node *block); +static bool +sieve_validate_command(struct sieve_validator *valdtr, + struct sieve_ast_node *cmd_node, int *const_r); + +static bool +sieve_validate_command_context(struct sieve_validator *valdtr, + struct sieve_ast_node *cmd_node) +{ + enum sieve_ast_type ast_type = sieve_ast_node_type(cmd_node); + struct sieve_command_registration *cmd_reg; + + i_assert(ast_type == SAT_TEST || ast_type == SAT_COMMAND); + + /* Verify the command specified by this node */ + cmd_reg = sieve_validator_find_command_registration( + valdtr, cmd_node->identifier); + + if (cmd_reg != NULL && cmd_reg->cmd_def != NULL) { + const struct sieve_command_def *cmd_def = cmd_reg->cmd_def; + + /* Identifier = "" when the command was previously marked as + unknown */ + if (*(cmd_def->identifier) != '\0') { + if ((cmd_def->type == SCT_COMMAND && ast_type == SAT_TEST) || + (cmd_def->type == SCT_TEST && ast_type == SAT_COMMAND)) { + sieve_validator_error( + valdtr, cmd_node->source_line, + "attempted to use %s '%s' as %s", + sieve_command_def_type_name(cmd_def), + cmd_node->identifier, + sieve_ast_type_name(ast_type)); + return FALSE; + } + + cmd_node->command = sieve_command_create( + cmd_node, cmd_reg->ext, cmd_def, cmd_reg); + } else { + return FALSE; + } + } else { + sieve_validator_error( + valdtr, cmd_node->source_line, + "unknown %s '%s' (only reported once at first occurrence)", + sieve_ast_type_name(ast_type), cmd_node->identifier); + + sieve_validator_register_unknown_command( + valdtr, cmd_node->identifier); + return FALSE; + } + + return TRUE; +} + +static bool +sieve_validate_command(struct sieve_validator *valdtr, + struct sieve_ast_node *cmd_node, int *const_r) +{ + enum sieve_ast_type ast_type = sieve_ast_node_type(cmd_node); + struct sieve_command *cmd = + (cmd_node == NULL ? NULL : cmd_node->command); + const struct sieve_command_def *cmd_def = + (cmd != NULL ? cmd->def : NULL); + bool result = TRUE; + + i_assert(ast_type == SAT_TEST || ast_type == SAT_COMMAND); + + if (cmd_def != NULL && *(cmd_def->identifier) != '\0') { + if (cmd_def->pre_validate == NULL || + cmd_def->pre_validate(valdtr, cmd)) { + /* Check argument syntax */ + if (!sieve_validate_command_arguments(valdtr, cmd)) { + result = FALSE; + + /* A missing ':' causes a tag to become a test. + This can be the cause of the arguments + validation failing. Therefore we must produce + an error for the sub-tests as well if + appropriate. */ + (void)sieve_validate_command_subtests( + valdtr, cmd, cmd_def->subtests); + } else if (!sieve_validate_command_subtests( + valdtr, cmd, cmd_def->subtests) || + (ast_type == SAT_COMMAND && + !sieve_validate_command_block( + valdtr, cmd, cmd_def->block_allowed, + cmd_def->block_required))) { + result = FALSE; + } else { + /* Call command validation function if specified + */ + if (cmd_def->validate != NULL) { + result = cmd_def->validate(valdtr, cmd) && + result; + } + } + } else { + /* If pre-validation fails, don't bother to validate + further as context might be missing and doing so is + not very useful for further error reporting anyway */ + return FALSE; + } + + result = result && sieve_validate_arguments_context(valdtr, cmd); + } + + /* + * Descend further into the AST + */ + + if (cmd_def != NULL) { + /* Tests */ + if (cmd_def->subtests > 0) { + if (result || + sieve_errors_more_allowed(valdtr->ehandler)) { + result = sieve_validate_test_list( + valdtr, cmd_node, const_r) && result; + } + } else if (result) { + if (cmd_def->validate_const != NULL) { + (void)cmd_def->validate_const( + valdtr, cmd, const_r, -1); + } else { + *const_r = -1; + } + } + + /* Skip block if result of test is const FALSE */ + if (result && *const_r == 0) + return TRUE; + + /* Command block */ + if (cmd_def->block_allowed && ast_type == SAT_COMMAND && + (result || sieve_errors_more_allowed(valdtr->ehandler))) { + result = sieve_validate_block(valdtr, cmd_node) && + result; + } + } + + return result; +} + +static bool +sieve_validate_test_list(struct sieve_validator *valdtr, + struct sieve_ast_node *test_node, int *const_r) +{ + struct sieve_command *tst = test_node->command; + const struct sieve_command_def *tst_def = + (tst != NULL ? tst->def : NULL); + struct sieve_ast_node *test; + bool result = TRUE; + + if (tst_def != NULL && tst_def->validate_const != NULL) { + if (!tst_def->validate_const(valdtr, tst, const_r, -2)) + return TRUE; + } + + test = sieve_ast_test_first(test_node); + while (test != NULL && + (result || sieve_errors_more_allowed(valdtr->ehandler))) { + int const_value = -2; + + result = sieve_validate_command_context(valdtr, test) && + sieve_validate_command(valdtr, test, &const_value) && + result; + + if (result) { + if (tst_def != NULL && + tst_def->validate_const != NULL) { + if (!tst_def->validate_const( + valdtr, tst, const_r, const_value)) + return TRUE; + } else { + *const_r = -1; + } + } + + if (result && const_value >= 0) + test = sieve_ast_node_detach(test); + else + test = sieve_ast_test_next(test); + } + + return result; +} + +static bool +sieve_validate_block(struct sieve_validator *valdtr, + struct sieve_ast_node *block) +{ + bool result = TRUE, fatal = FALSE; + struct sieve_ast_node *cmd_node, *next; + + T_BEGIN { + cmd_node = sieve_ast_command_first(block); + while (!fatal && cmd_node != NULL && + (result || + sieve_errors_more_allowed(valdtr->ehandler))) { + bool command_success; + int const_value = -2; + + next = sieve_ast_command_next(cmd_node); + + /* Check if this is the first non-require command */ + if (sieve_ast_node_type(block) == SAT_ROOT && + !valdtr->finished_require && + strcasecmp(cmd_node->identifier, + cmd_require.identifier) != 0) { + const struct sieve_validator_extension_reg *extrs; + const struct sieve_extension *const *exts; + unsigned int ext_count, i; + + valdtr->finished_require = TRUE; + + /* Load implicit extensions */ + exts = sieve_extensions_get_all(valdtr->svinst, &ext_count); + for (i = 0; i < ext_count; i++) { + if (exts[i]->implicit) { + (void)sieve_validator_extension_load( + valdtr, NULL, NULL, exts[i], TRUE); + } + } + + /* Validate all 'require'd extensions */ + extrs = array_get(&valdtr->extensions, &ext_count); + for (i = 0; i < ext_count; i++) { + if (extrs[i].loaded && extrs[i].valext != NULL && + extrs[i].valext->validate != NULL) { + if (!extrs[i].valext->validate( + extrs[i].ext, valdtr, + extrs[i].context, extrs[i].arg, + extrs[i].required)) { + fatal = TRUE; + break; + } + } + } + } + + command_success = + sieve_validate_command_context(valdtr, cmd_node); + result = command_success && result; + + result = !fatal && + sieve_validate_command(valdtr, cmd_node, + &const_value) && result; + + cmd_node = next; + } + } T_END; + + return result && !fatal; +} + +bool sieve_validator_run(struct sieve_validator *valdtr) +{ + return sieve_validate_block(valdtr, sieve_ast_root(valdtr->ast)); +} + +/* + * Validator object registry + */ + +struct sieve_validator_object_reg { + const struct sieve_object_def *obj_def; + const struct sieve_extension *ext; +}; + +struct sieve_validator_object_registry { + struct sieve_validator *valdtr; + ARRAY(struct sieve_validator_object_reg) registrations; +}; + +struct sieve_validator_object_registry * +sieve_validator_object_registry_get(struct sieve_validator *valdtr, + const struct sieve_extension *ext) +{ + return (struct sieve_validator_object_registry *) + sieve_validator_extension_get_context(valdtr, ext); +} + +void sieve_validator_object_registry_add( + struct sieve_validator_object_registry *regs, + const struct sieve_extension *ext, + const struct sieve_object_def *obj_def) +{ + struct sieve_validator_object_reg *reg; + + reg = array_append_space(®s->registrations); + reg->ext = ext; + reg->obj_def = obj_def; +} + +bool sieve_validator_object_registry_find( + struct sieve_validator_object_registry *regs, const char *identifier, + struct sieve_object *obj) +{ + unsigned int i; + + for (i = 0; i < array_count(®s->registrations); i++) { + const struct sieve_validator_object_reg *reg = + array_idx(®s->registrations, i); + + if (strcasecmp(reg->obj_def->identifier, identifier) == 0) { + if (obj != NULL) { + obj->def = reg->obj_def; + obj->ext = reg->ext; + } + return TRUE; + } + } + + return FALSE; +} + +struct sieve_validator_object_registry * +sieve_validator_object_registry_create(struct sieve_validator *valdtr) +{ + pool_t pool = valdtr->pool; + struct sieve_validator_object_registry *regs = + p_new(pool, struct sieve_validator_object_registry, 1); + + /* Setup registry */ + p_array_init(®s->registrations, valdtr->pool, 4); + + regs->valdtr = valdtr; + + return regs; +} + +struct sieve_validator_object_registry * +sieve_validator_object_registry_init(struct sieve_validator *valdtr, + const struct sieve_extension *ext) +{ + struct sieve_validator_object_registry *regs = + sieve_validator_object_registry_create(valdtr); + + sieve_validator_extension_set_context(valdtr, ext, regs); + return regs; +} + +/* + * Error handling + */ + +#undef sieve_validator_error +void sieve_validator_error(struct sieve_validator *valdtr, + const char *csrc_filename, unsigned int csrc_linenum, + unsigned int source_line, const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_ERROR, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + }; + va_list args; + + params.location = + sieve_error_script_location(valdtr->script, source_line); + + va_start(args, fmt); + sieve_logv(valdtr->ehandler, ¶ms, fmt, args); + va_end(args); +} + +#undef sieve_validator_warning +void sieve_validator_warning(struct sieve_validator *valdtr, + const char *csrc_filename, + unsigned int csrc_linenum, + unsigned int source_line, const char *fmt, ...) +{ + struct sieve_error_params params = { + .log_type = LOG_TYPE_WARNING, + .csrc = { + .filename = csrc_filename, + .linenum = csrc_linenum, + }, + }; + va_list args; + + params.location = + sieve_error_script_location(valdtr->script, source_line); + + va_start(args, fmt); + sieve_logv(valdtr->ehandler, ¶ms, fmt, args); + va_end(args); + +} diff --git a/pigeonhole/src/lib-sieve/sieve-validator.h b/pigeonhole/src/lib-sieve/sieve-validator.h new file mode 100644 index 0000000..21b41cc --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-validator.h @@ -0,0 +1,197 @@ +#ifndef SIEVE_VALIDATOR_H +#define SIEVE_VALIDATOR_H + +#include "lib.h" + +#include "sieve-common.h" + +/* + * Types + */ + +enum sieve_argument_type { + SAT_NUMBER, + SAT_CONST_STRING, + SAT_VAR_STRING, + SAT_STRING_LIST, + + SAT_COUNT +}; + +struct sieve_command_registration; + +/* + * Validator + */ + +struct sieve_validator; + +struct sieve_validator * +sieve_validator_create(struct sieve_ast *ast, + struct sieve_error_handler *ehandler, + enum sieve_compile_flags flags); +void sieve_validator_free(struct sieve_validator **valdtr); +pool_t sieve_validator_pool(struct sieve_validator *valdtr); + +bool sieve_validator_run(struct sieve_validator *valdtr); + +/* + * Accessors + */ + +struct sieve_error_handler * +sieve_validator_error_handler(struct sieve_validator *valdtr); +struct sieve_ast *sieve_validator_ast(struct sieve_validator *valdtr); +struct sieve_script *sieve_validator_script(struct sieve_validator *valdtr); +struct sieve_instance *sieve_validator_svinst(struct sieve_validator *valdtr); +enum sieve_compile_flags +sieve_validator_compile_flags(struct sieve_validator *valdtr); + +/* + * Command/Test registry + */ + +void sieve_validator_register_command(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + const struct sieve_command_def *command); + +/* + * Per-command tagged argument registry + */ + +void sieve_validator_register_tag(struct sieve_validator *valdtr, + struct sieve_command_registration *cmd_reg, + const struct sieve_extension *ext, + const struct sieve_argument_def *tag_def, + int id_code); +void sieve_validator_register_external_tag( + struct sieve_validator *valdtr, const char *command, + const struct sieve_extension *ext, + const struct sieve_argument_def *tag_def, int id_code); +void sieve_validator_register_persistent_tag( + struct sieve_validator *valdtr, const char *command, + const struct sieve_extension *ext, + const struct sieve_argument_def *tag_def); + +/* + * Overriding the default literal arguments + */ + +void sieve_validator_argument_override( + struct sieve_validator *valdtr, enum sieve_argument_type type, + const struct sieve_extension *ext, + const struct sieve_argument_def *arg_def); +bool sieve_validator_argument_activate_super( + struct sieve_validator *valdtr, struct sieve_command *cmd, + struct sieve_ast_argument *arg, bool constant); + +/* + * Argument validation API + */ + +bool sieve_validate_positional_argument(struct sieve_validator *valdtr, + struct sieve_command *cmd, + struct sieve_ast_argument *arg, + const char *arg_name, + unsigned int arg_pos, + enum sieve_ast_argument_type req_type); +bool sieve_validator_argument_activate(struct sieve_validator *valdtr, + struct sieve_command *cmd, + struct sieve_ast_argument *arg, + bool constant); + +bool sieve_validate_tag_parameter(struct sieve_validator *valdtr, + struct sieve_command *cmd, + struct sieve_ast_argument *tag, + struct sieve_ast_argument *param, + const char *arg_name, unsigned int arg_pos, + enum sieve_ast_argument_type req_type, + bool constant); + +/* + * Extension support + */ + +struct sieve_validator_extension { + const struct sieve_extension_def *ext; + + bool (*check_conflict)(const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + const struct sieve_extension *ext_other, + bool required); + bool (*validate)(const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, bool required); + + void (*free)(const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context); +}; + +bool sieve_validator_extension_load(struct sieve_validator *valdtr, + struct sieve_command *cmd, + struct sieve_ast_argument *ext_arg, + const struct sieve_extension *ext, + bool required) ATTR_NULL(2, 3); +const struct sieve_extension * +sieve_validator_extension_load_by_name(struct sieve_validator *valdtr, + struct sieve_command *cmd, + struct sieve_ast_argument *ext_arg, + const char *ext_name); +const struct sieve_extension * +sieve_validator_extension_load_implicit(struct sieve_validator *valdtr, + const char *ext_name); + +void sieve_validator_extension_register( + struct sieve_validator *valdtr, const struct sieve_extension *ext, + const struct sieve_validator_extension *valext, void *context); +bool sieve_validator_extension_loaded(struct sieve_validator *valdtr, + const struct sieve_extension *ext); + +void sieve_validator_extension_set_context(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + void *context); +void *sieve_validator_extension_get_context(struct sieve_validator *valdtr, + const struct sieve_extension *ext); + +/* + * Validator object registry + */ + +struct sieve_validator_object_registry; + +struct sieve_validator_object_registry * +sieve_validator_object_registry_get(struct sieve_validator *valdtr, + const struct sieve_extension *ext); +void sieve_validator_object_registry_add( + struct sieve_validator_object_registry *regs, + const struct sieve_extension *ext, + const struct sieve_object_def *obj_def); +bool sieve_validator_object_registry_find( + struct sieve_validator_object_registry *regs, const char *identifier, + struct sieve_object *obj); +struct sieve_validator_object_registry * +sieve_validator_object_registry_create(struct sieve_validator *valdtr); +struct sieve_validator_object_registry * +sieve_validator_object_registry_init(struct sieve_validator *valdtr, + const struct sieve_extension *ext); + +/* + * Error handling + */ + +void sieve_validator_error(struct sieve_validator *valdtr, + const char *csrc_filename, unsigned int csrc_linenum, + unsigned int source_line, const char *fmt, ...) + ATTR_FORMAT(5, 6); +#define sieve_validator_error(valdtr, ...) \ + sieve_validator_error(valdtr, __FILE__, __LINE__, __VA_ARGS__) +void sieve_validator_warning(struct sieve_validator *valdtr, + const char *csrc_filename, + unsigned int csrc_linenum, + unsigned int source_line, const char *fmt, ...) + ATTR_FORMAT(5, 6); +#define sieve_validator_warning(valdtr, ...) \ + sieve_validator_warning(valdtr, __FILE__, __LINE__, __VA_ARGS__) + +#endif diff --git a/pigeonhole/src/lib-sieve/sieve.c b/pigeonhole/src/lib-sieve/sieve.c new file mode 100644 index 0000000..69827a9 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve.c @@ -0,0 +1,1303 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "istream.h" +#include "ostream.h" +#include "buffer.h" +#include "time-util.h" +#include "eacces-error.h" +#include "home-expand.h" +#include "hostpid.h" +#include "message-address.h" +#include "mail-user.h" + +#include "sieve-settings.h" +#include "sieve-extensions.h" +#include "sieve-plugins.h" + +#include "sieve-address.h" +#include "sieve-script.h" +#include "sieve-storage-private.h" +#include "sieve-ast.h" +#include "sieve-binary.h" +#include "sieve-actions.h" +#include "sieve-result.h" + +#include "sieve-parser.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-binary-dumper.h" + +#include "sieve.h" +#include "sieve-common.h" +#include "sieve-limits.h" +#include "sieve-error-private.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <dirent.h> + +struct event_category event_category_sieve = { + .name = "sieve", +}; + +/* + * Main Sieve library interface + */ + +struct sieve_instance * +sieve_init(const struct sieve_environment *env, + const struct sieve_callbacks *callbacks, void *context, bool debug) +{ + struct sieve_instance *svinst; + const char *domain; + pool_t pool; + + /* Create Sieve engine instance */ + pool = pool_alloconly_create("sieve", 8192); + svinst = p_new(pool, struct sieve_instance, 1); + svinst->pool = pool; + svinst->callbacks = callbacks; + svinst->context = context; + svinst->debug = debug; + svinst->base_dir = p_strdup_empty(pool, env->base_dir); + svinst->username = p_strdup_empty(pool, env->username); + svinst->home_dir = p_strdup_empty(pool, env->home_dir); + svinst->temp_dir = p_strdup_empty(pool, env->temp_dir); + svinst->flags = env->flags; + svinst->env_location = env->location; + svinst->delivery_phase = env->delivery_phase; + + svinst->event = event_create(env->event_parent); + event_add_category(svinst->event, &event_category_sieve); + event_set_forced_debug(svinst->event, debug); + event_set_append_log_prefix(svinst->event, "sieve: "); + event_add_str(svinst->event, "user", env->username); + + /* Determine domain */ + if (env->domainname != NULL && *(env->domainname) != '\0') + domain = env->domainname; + else { + /* Fall back to parsing username localpart@domain */ + domain = svinst->username == NULL ? NULL : + strchr(svinst->username, '@'); + if (domain == NULL || *(domain+1) == '\0') { + /* Fall back to parsing hostname host.domain */ + domain = (env->hostname != NULL ? + strchr(env->hostname, '.') : NULL); + if (domain == NULL || *(domain+1) == '\0' || + strchr(domain+1, '.') == NULL) { + /* Fall back to bare hostname */ + domain = env->hostname; + } else { + domain++; + } + } else { + domain++; + } + } + svinst->hostname = p_strdup_empty(pool, env->hostname); + svinst->domainname = p_strdup(pool, domain); + + sieve_errors_init(svinst); + + e_debug(svinst->event, "%s version %s initializing", + PIGEONHOLE_NAME, PIGEONHOLE_VERSION_FULL); + + /* Read configuration */ + + sieve_settings_load(svinst); + + /* Initialize extensions */ + if (!sieve_extensions_init(svinst)) { + sieve_deinit(&svinst); + return NULL; + } + + /* Initialize storage classes */ + sieve_storages_init(svinst); + + /* Initialize plugins */ + sieve_plugins_load(svinst, NULL, NULL); + + /* Configure extensions */ + sieve_extensions_configure(svinst); + + return svinst; +} + +void sieve_deinit(struct sieve_instance **_svinst) +{ + struct sieve_instance *svinst = *_svinst; + + sieve_plugins_unload(svinst); + sieve_storages_deinit(svinst); + sieve_extensions_deinit(svinst); + sieve_errors_deinit(svinst); + + event_unref(&svinst->event); + + pool_unref(&(svinst)->pool); + *_svinst = NULL; +} + +void sieve_set_extensions(struct sieve_instance *svinst, const char *extensions) +{ + sieve_extensions_set_string(svinst, extensions, FALSE, FALSE); +} + +const char * +sieve_get_capabilities(struct sieve_instance *svinst, const char *name) +{ + if (name == NULL || *name == '\0') + return sieve_extensions_get_string(svinst); + + return sieve_extension_capabilities_get_string(svinst, name); +} + +struct event *sieve_get_event(struct sieve_instance *svinst) +{ + return svinst->event; +} + +/* + * Low-level compiler functions + */ + +struct sieve_ast * +sieve_parse(struct sieve_script *script, struct sieve_error_handler *ehandler, + enum sieve_error *error_r) +{ + struct sieve_parser *parser; + struct sieve_ast *ast = NULL; + + /* Parse */ + parser = sieve_parser_create(script, ehandler, error_r); + if (parser == NULL) + return NULL; + + if (!sieve_parser_run(parser, &ast)) + ast = NULL; + else + sieve_ast_ref(ast); + + sieve_parser_free(&parser); + + if (error_r != NULL) { + if (ast == NULL) + *error_r = SIEVE_ERROR_NOT_VALID; + else + *error_r = SIEVE_ERROR_NONE; + } + return ast; +} + +bool sieve_validate(struct sieve_ast *ast, struct sieve_error_handler *ehandler, + enum sieve_compile_flags flags, enum sieve_error *error_r) +{ + bool result = TRUE; + struct sieve_validator *validator = + sieve_validator_create(ast, ehandler, flags); + + if (!sieve_validator_run(validator)) + result = FALSE; + + sieve_validator_free(&validator); + + if (error_r != NULL) { + if (!result) + *error_r = SIEVE_ERROR_NOT_VALID; + else + *error_r = SIEVE_ERROR_NONE; + } + return result; +} + +static struct sieve_binary * +sieve_generate(struct sieve_ast *ast, struct sieve_error_handler *ehandler, + enum sieve_compile_flags flags, enum sieve_error *error_r) +{ + struct sieve_generator *generator = + sieve_generator_create(ast, ehandler, flags); + struct sieve_binary *sbin = NULL; + + sbin = sieve_generator_run(generator, NULL); + + sieve_generator_free(&generator); + + if (error_r != NULL) { + if (sbin == NULL) + *error_r = SIEVE_ERROR_NOT_VALID; + else + *error_r = SIEVE_ERROR_NONE; + } + return sbin; +} + +/* + * Sieve compilation + */ + +struct sieve_binary * +sieve_compile_script(struct sieve_script *script, + struct sieve_error_handler *ehandler, + enum sieve_compile_flags flags, + enum sieve_error *error_r) +{ + struct sieve_ast *ast; + struct sieve_binary *sbin; + enum sieve_error error, *errorp; + + if (error_r != NULL) + errorp = error_r; + else + errorp = &error; + *errorp = SIEVE_ERROR_NONE; + + /* Parse */ + ast = sieve_parse(script, ehandler, errorp); + if (ast == NULL) { + switch (*errorp) { + case SIEVE_ERROR_NOT_FOUND: + if (error_r == NULL) { + sieve_error(ehandler, sieve_script_name(script), + "script not found"); + } + break; + default: + sieve_error(ehandler, sieve_script_name(script), + "parse failed"); + } + return NULL; + } + + /* Validate */ + if (!sieve_validate(ast, ehandler, flags, errorp)) { + sieve_error(ehandler, sieve_script_name(script), + "validation failed"); + + sieve_ast_unref(&ast); + return NULL; + } + + /* Generate */ + sbin = sieve_generate(ast, ehandler, flags, errorp); + if (sbin == NULL) { + sieve_error(ehandler, sieve_script_name(script), + "code generation failed"); + sieve_ast_unref(&ast); + return NULL; + } + + /* Cleanup */ + sieve_ast_unref(&ast); + return sbin; +} + +struct sieve_binary * +sieve_compile(struct sieve_instance *svinst, const char *script_location, + const char *script_name, struct sieve_error_handler *ehandler, + enum sieve_compile_flags flags, enum sieve_error *error_r) +{ + struct sieve_script *script; + struct sieve_binary *sbin; + enum sieve_error error; + + script = sieve_script_create_open(svinst, script_location, + script_name, &error); + if (script == NULL) { + if (error_r != NULL) + *error_r = error; + switch (error) { + case SIEVE_ERROR_NOT_FOUND: + sieve_error(ehandler, script_name, "script not found"); + break; + default: + sieve_internal_error(ehandler, script_name, + "failed to open script"); + } + return NULL; + } + + sbin = sieve_compile_script(script, ehandler, flags, error_r); + if (sbin != NULL) { + e_debug(svinst->event, + "Script `%s' from %s successfully compiled", + sieve_script_name(script), + sieve_script_location(script)); + } + + sieve_script_unref(&script); + return sbin; +} + +/* + * Sieve runtime + */ + +static int +sieve_run(struct sieve_binary *sbin, struct sieve_result *result, + struct sieve_execute_env *eenv, struct sieve_error_handler *ehandler) +{ + struct sieve_interpreter *interp; + int ret = 0; + + /* Create the interpreter */ + interp = sieve_interpreter_create(sbin, NULL, eenv, ehandler); + if (interp == NULL) + return SIEVE_EXEC_BIN_CORRUPT; + + /* Run the interpreter */ + ret = sieve_interpreter_run(interp, result); + + /* Free the interpreter */ + sieve_interpreter_free(&interp); + + return ret; +} + +/* + * Reading/writing sieve binaries + */ + +struct sieve_binary * +sieve_load(struct sieve_instance *svinst, const char *bin_path, + enum sieve_error *error_r) +{ + return sieve_binary_open(svinst, bin_path, NULL, error_r); +} + +static struct sieve_binary * +sieve_open_script_real(struct sieve_script *script, + struct sieve_error_handler *ehandler, + enum sieve_compile_flags flags, + enum sieve_error *error_r) +{ + struct sieve_instance *svinst = sieve_script_svinst(script); + struct sieve_resource_usage rusage; + struct sieve_binary *sbin; + enum sieve_error error; + const char *errorstr = NULL; + int ret; + + if (error_r == NULL) + error_r = &error; + + sieve_resource_usage_init(&rusage); + + /* Try to open the matching binary */ + sbin = sieve_script_binary_load(script, error_r); + if (sbin != NULL) { + sieve_binary_get_resource_usage(sbin, &rusage); + + /* Ok, it exists; now let's see if it is up to date */ + if (!sieve_resource_usage_is_excessive(svinst, &rusage) && + !sieve_binary_up_to_date(sbin, flags)) { + /* Not up to date */ + e_debug(svinst->event, + "Script binary %s is not up-to-date", + sieve_binary_path(sbin)); + sieve_binary_close(&sbin); + } + } + + /* If the binary does not exist or is not up-to-date, we need + * to (re-)compile. + */ + if (sbin != NULL) { + e_debug(svinst->event, + "Script binary %s successfully loaded", + sieve_binary_path(sbin)); + } else { + sbin = sieve_compile_script(script, ehandler, flags, error_r); + if (sbin == NULL) + return NULL; + + e_debug(svinst->event, + "Script `%s' from %s successfully compiled", + sieve_script_name(script), + sieve_script_location(script)); + + sieve_binary_set_resource_usage(sbin, &rusage); + } + + /* Check whether binary can be executed. */ + ret = sieve_binary_check_executable(sbin, error_r, &errorstr); + if (ret <= 0) { + const char *path = sieve_binary_path(sbin); + + if (path != NULL) { + e_debug(svinst->event, + "Script binary %s cannot be executed", + path); + } else { + e_debug(svinst->event, + "Script binary from %s cannot be executed", + sieve_binary_source(sbin)); + } + if (ret < 0) { + sieve_internal_error(ehandler, + sieve_script_name(script), + "failed to open script"); + } else { + sieve_error(ehandler, sieve_script_name(script), + "%s", errorstr); + } + sieve_binary_close(&sbin); + } + + return sbin; +} + +struct sieve_binary * +sieve_open_script(struct sieve_script *script, + struct sieve_error_handler *ehandler, + enum sieve_compile_flags flags, enum sieve_error *error_r) +{ + struct sieve_binary *sbin; + + T_BEGIN { + sbin = sieve_open_script_real(script, ehandler, flags, error_r); + } T_END; + + return sbin; +} + +struct sieve_binary * +sieve_open(struct sieve_instance *svinst, const char *script_location, + const char *script_name, struct sieve_error_handler *ehandler, + enum sieve_compile_flags flags, enum sieve_error *error_r) +{ + struct sieve_script *script; + struct sieve_binary *sbin; + enum sieve_error error; + + /* First open the scriptfile itself */ + script = sieve_script_create_open(svinst, script_location, + script_name, &error); + if (script == NULL) { + /* Failed */ + if (error_r != NULL) + *error_r = error; + switch (error) { + case SIEVE_ERROR_NOT_FOUND: + sieve_error(ehandler, script_name, "script not found"); + break; + default: + sieve_internal_error(ehandler, script_name, + "failed to open script"); + } + return NULL; + } + + sbin = sieve_open_script(script, ehandler, flags, error_r); + + /* Drop script reference, if sbin != NULL it holds a reference of its own. + * Otherwise the script object is freed here. + */ + sieve_script_unref(&script); + + return sbin; +} + +const char *sieve_get_source(struct sieve_binary *sbin) +{ + return sieve_binary_source(sbin); +} + +bool sieve_is_loaded(struct sieve_binary *sbin) +{ + return sieve_binary_loaded(sbin); +} + +int sieve_save_as(struct sieve_binary *sbin, const char *bin_path, bool update, + mode_t save_mode, enum sieve_error *error_r) +{ + if (bin_path == NULL) + return sieve_save(sbin, update, error_r); + + return sieve_binary_save(sbin, bin_path, update, save_mode, error_r); +} + +int sieve_save(struct sieve_binary *sbin, bool update, + enum sieve_error *error_r) +{ + struct sieve_script *script = sieve_binary_script(sbin); + + if (script == NULL) + return sieve_binary_save(sbin, NULL, update, 0600, error_r); + + return sieve_script_binary_save(script, sbin, update, error_r); +} + +bool sieve_record_resource_usage(struct sieve_binary *sbin, + const struct sieve_resource_usage *rusage) +{ + return sieve_binary_record_resource_usage(sbin, rusage); +} + +int sieve_check_executable(struct sieve_binary *sbin, + enum sieve_error *error_r, + const char **client_error_r) +{ + return sieve_binary_check_executable(sbin, error_r, client_error_r); +} + +void sieve_close(struct sieve_binary **_sbin) +{ + sieve_binary_close(_sbin); +} + +/* + * Debugging + */ + +void sieve_dump(struct sieve_binary *sbin, struct ostream *stream, bool verbose) +{ + struct sieve_binary_dumper *dumpr = sieve_binary_dumper_create(sbin); + + sieve_binary_dumper_run(dumpr, stream, verbose); + + sieve_binary_dumper_free(&dumpr); +} + +void sieve_hexdump(struct sieve_binary *sbin, struct ostream *stream) +{ + struct sieve_binary_dumper *dumpr = sieve_binary_dumper_create(sbin); + + sieve_binary_dumper_hexdump(dumpr, stream); + + sieve_binary_dumper_free(&dumpr); +} + +int sieve_test(struct sieve_binary *sbin, + const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv, + struct sieve_error_handler *ehandler, struct ostream *stream, + enum sieve_execute_flags flags) +{ + struct sieve_instance *svinst = sieve_binary_svinst(sbin); + struct sieve_result *result; + struct sieve_execute_env eenv; + pool_t pool; + int ret; + + pool = pool_alloconly_create("sieve execution", 4096); + sieve_execute_init(&eenv, svinst, pool, msgdata, senv, flags); + + /* Create result object */ + result = sieve_result_create(svinst, pool, &eenv); + + /* Run the script */ + ret = sieve_run(sbin, result, &eenv, ehandler); + + /* Print result if successful */ + if (ret > 0) { + ret = (sieve_result_print(result, senv, stream, NULL) ? + SIEVE_EXEC_OK : SIEVE_EXEC_FAILURE); + } + + /* Cleanup */ + if (result != NULL) + sieve_result_unref(&result); + sieve_execute_deinit(&eenv); + pool_unref(&pool); + + return ret; +} + +/* + * Script execution + */ + +int sieve_script_env_init(struct sieve_script_env *senv, struct mail_user *user, + const char **error_r) +{ + const struct message_address *postmaster; + const char *error; + + if (!mail_user_get_postmaster_address(user, &postmaster, &error)) { + *error_r = t_strdup_printf( + "Invalid postmaster_address: %s", error); + return -1; + } + + i_zero(senv); + senv->user = user; + senv->postmaster_address = postmaster; + return 0; +} + +int sieve_execute(struct sieve_binary *sbin, + const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv, + struct sieve_error_handler *exec_ehandler, + struct sieve_error_handler *action_ehandler, + enum sieve_execute_flags flags) +{ + struct sieve_instance *svinst = sieve_binary_svinst(sbin); + struct sieve_result *result = NULL; + struct sieve_result_execution *rexec; + struct sieve_execute_env eenv; + pool_t pool; + int ret; + + pool = pool_alloconly_create("sieve execution", 4096); + sieve_execute_init(&eenv, svinst, pool, msgdata, senv, flags); + + /* Create result object */ + result = sieve_result_create(svinst, pool, &eenv); + + /* Run the script */ + ret = sieve_run(sbin, result, &eenv, exec_ehandler); + + rexec = sieve_result_execution_create(result, pool); + + /* Evaluate status and execute the result: + Strange situations, e.g. currupt binaries, must be handled by the + caller. In that case no implicit keep is attempted, because the + situation may be resolved. + */ + ret = sieve_result_execute(rexec, ret, TRUE, action_ehandler, NULL); + + sieve_result_execution_destroy(&rexec); + + /* Cleanup */ + if (result != NULL) + sieve_result_unref(&result); + sieve_execute_finish(&eenv, ret); + sieve_execute_deinit(&eenv); + pool_unref(&pool); + + return ret; +} + +/* + * Multiscript support + */ + +struct sieve_multiscript { + pool_t pool; + struct sieve_execute_env exec_env; + struct sieve_result *result; + struct sieve_result_execution *rexec; + struct event *event; + + int status; + bool keep; + + struct ostream *teststream; + + bool active:1; + bool discard_handled:1; +}; + +struct sieve_multiscript * +sieve_multiscript_start_execute(struct sieve_instance *svinst, + const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv) +{ + pool_t pool; + struct sieve_result *result; + struct sieve_multiscript *mscript; + + pool = pool_alloconly_create("sieve execution", 4096); + mscript = p_new(pool, struct sieve_multiscript, 1); + mscript->pool = pool; + sieve_execute_init(&mscript->exec_env, svinst, pool, msgdata, senv, 0); + + mscript->event = event_create(mscript->exec_env.event); + event_set_append_log_prefix(mscript->event, "multi-script: "); + + result = sieve_result_create(svinst, pool, &mscript->exec_env); + sieve_result_set_keep_action(result, NULL, NULL); + mscript->result = result; + + mscript->rexec = sieve_result_execution_create(result, pool); + + mscript->status = SIEVE_EXEC_OK; + mscript->active = TRUE; + mscript->keep = TRUE; + + e_debug(mscript->event, "Start execute sequence"); + + return mscript; +} + +static void sieve_multiscript_destroy(struct sieve_multiscript **_mscript) +{ + struct sieve_multiscript *mscript = *_mscript; + + if (mscript == NULL) + return; + *_mscript = NULL; + + e_debug(mscript->event, "Destroy"); + + event_unref(&mscript->event); + + sieve_result_execution_destroy(&mscript->rexec); + sieve_result_unref(&mscript->result); + sieve_execute_deinit(&mscript->exec_env); + pool_unref(&mscript->pool); +} + +struct sieve_multiscript * +sieve_multiscript_start_test(struct sieve_instance *svinst, + const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv, + struct ostream *stream) +{ + struct sieve_multiscript *mscript = + sieve_multiscript_start_execute(svinst, msgdata, senv); + + mscript->teststream = stream; + + return mscript; +} + +static void +sieve_multiscript_test(struct sieve_multiscript *mscript) +{ + const struct sieve_script_env *senv = mscript->exec_env.scriptenv; + + e_debug(mscript->event, "Test result"); + + if (mscript->status > 0) { + mscript->status = + (sieve_result_print(mscript->result, senv, + mscript->teststream, + &mscript->keep) ? + SIEVE_EXEC_OK : SIEVE_EXEC_FAILURE); + } else { + mscript->keep = TRUE; + } + + sieve_result_mark_executed(mscript->result); +} + +static void +sieve_multiscript_execute(struct sieve_multiscript *mscript, + struct sieve_error_handler *ehandler, + enum sieve_execute_flags flags) +{ + e_debug(mscript->event, "Execute result"); + + mscript->exec_env.flags = flags; + + if (mscript->status > 0) { + mscript->status = sieve_result_execute(mscript->rexec, + SIEVE_EXEC_OK, FALSE, + ehandler, + &mscript->keep); + } +} + +bool sieve_multiscript_run(struct sieve_multiscript *mscript, + struct sieve_binary *sbin, + struct sieve_error_handler *exec_ehandler, + struct sieve_error_handler *action_ehandler, + enum sieve_execute_flags flags) +{ + if (!mscript->active) { + e_debug(mscript->event, "Sequence ended"); + return FALSE; + } + + e_debug(mscript->event, "Run script `%s'", sieve_binary_source(sbin)); + + /* Run the script */ + mscript->exec_env.flags = flags; + mscript->status = sieve_run(sbin, mscript->result, &mscript->exec_env, + exec_ehandler); + + if (mscript->status >= 0) { + mscript->keep = FALSE; + + if (mscript->teststream != NULL) + sieve_multiscript_test(mscript); + else { + sieve_multiscript_execute(mscript, action_ehandler, + flags); + } + if (!mscript->keep) + mscript->active = FALSE; + } + + if (!mscript->active || mscript->status <= 0) { + e_debug(mscript->event, "Sequence ended"); + mscript->active = FALSE; + return FALSE; + } + + e_debug(mscript->event, "Sequence active"); + return TRUE; +} + +bool sieve_multiscript_will_discard(struct sieve_multiscript *mscript) +{ + return (!mscript->active && mscript->status == SIEVE_EXEC_OK && + !sieve_result_executed_delivery(mscript->rexec)); +} + +void sieve_multiscript_run_discard(struct sieve_multiscript *mscript, + struct sieve_binary *sbin, + struct sieve_error_handler *exec_ehandler, + struct sieve_error_handler *action_ehandler, + enum sieve_execute_flags flags) +{ + if (!sieve_multiscript_will_discard(mscript)) { + e_debug(mscript->event, "Not running discard script"); + return; + } + i_assert(!mscript->discard_handled); + + e_debug(mscript->event, "Run discard script `%s'", + sieve_binary_source(sbin)); + + sieve_result_set_keep_action(mscript->result, NULL, &act_store); + + /* Run the discard script */ + flags |= SIEVE_EXECUTE_FLAG_DEFER_KEEP; + mscript->exec_env.flags = flags; + mscript->status = sieve_run(sbin, mscript->result, &mscript->exec_env, + exec_ehandler); + + if (mscript->status >= 0) { + mscript->keep = FALSE; + + if (mscript->teststream != NULL) + sieve_multiscript_test(mscript); + else { + sieve_multiscript_execute(mscript, action_ehandler, + flags); + } + if (mscript->status == SIEVE_EXEC_FAILURE) + mscript->status = SIEVE_EXEC_KEEP_FAILED; + mscript->active = FALSE; + } + + mscript->discard_handled = TRUE; +} + +int sieve_multiscript_status(struct sieve_multiscript *mscript) +{ + return mscript->status; +} + +int sieve_multiscript_finish(struct sieve_multiscript **_mscript, + struct sieve_error_handler *action_ehandler, + enum sieve_execute_flags flags, int status) +{ + struct sieve_multiscript *mscript = *_mscript; + + if (mscript == NULL) + return SIEVE_EXEC_OK; + *_mscript = NULL; + + switch (status) { + case SIEVE_EXEC_OK: + status = mscript->status; + break; + case SIEVE_EXEC_TEMP_FAILURE: + break; + case SIEVE_EXEC_BIN_CORRUPT: + case SIEVE_EXEC_FAILURE: + case SIEVE_EXEC_KEEP_FAILED: + case SIEVE_EXEC_RESOURCE_LIMIT: + if (mscript->status == SIEVE_EXEC_TEMP_FAILURE) + status = mscript->status; + break; + } + + e_debug(mscript->event, "Finishing sequence (status=%s)", + sieve_execution_exitcode_to_str(status)); + + mscript->exec_env.flags = flags; + sieve_result_set_keep_action(mscript->result, NULL, &act_store); + + mscript->keep = FALSE; + if (mscript->teststream != NULL) + mscript->keep = TRUE; + else { + status = sieve_result_execute( + mscript->rexec, status, TRUE, action_ehandler, + &mscript->keep); + } + + e_debug(mscript->event, "Sequence finished (status=%s, keep=%s)", + sieve_execution_exitcode_to_str(status), + (mscript->keep ? "yes" : "no")); + + sieve_execute_finish(&mscript->exec_env, status); + + /* Cleanup */ + sieve_multiscript_destroy(&mscript); + + return status; +} + +/* + * Configured Limits + */ + +unsigned int sieve_max_redirects(struct sieve_instance *svinst) +{ + return svinst->max_redirects; +} + +unsigned int sieve_max_actions(struct sieve_instance *svinst) +{ + return svinst->max_actions; +} + +size_t sieve_max_script_size(struct sieve_instance *svinst) +{ + return svinst->max_script_size; +} + +/* + * User log + */ + +const char * +sieve_user_get_log_path(struct sieve_instance *svinst, + struct sieve_script *user_script) +{ + const char *log_path = NULL; + + /* Determine user log file path */ + log_path = sieve_setting_get(svinst, "sieve_user_log"); + if (log_path == NULL) { + const char *path; + + if (user_script == NULL || + (path = sieve_file_script_get_path(user_script)) == NULL) { + /* Default */ + if (svinst->home_dir != NULL) { + log_path = t_strconcat( + svinst->home_dir, "/.dovecot.sieve.log", + NULL); + } + } else { + /* Use script file as a base (legacy behavior) */ + log_path = t_strconcat(path, ".log", NULL); + } + } else if (svinst->home_dir != NULL) { + /* Expand home dir if necessary */ + if (log_path[0] == '~') { + log_path = home_expand_tilde(log_path, + svinst->home_dir); + } else if (log_path[0] != '/') { + log_path = t_strconcat(svinst->home_dir, "/", + log_path, NULL); + } + } + return log_path; +} + +/* + * Script trace log + */ + +struct sieve_trace_log { + struct ostream *output; +}; + +int sieve_trace_log_create(struct sieve_instance *svinst, const char *path, + struct sieve_trace_log **trace_log_r) +{ + struct sieve_trace_log *trace_log; + struct ostream *output; + int fd; + + *trace_log_r = NULL; + + if (path == NULL) + output = o_stream_create_fd(1, 0); + else { + fd = open(path, O_CREAT | O_APPEND | O_WRONLY, 0600); + if (fd == -1) { + e_error(svinst->event, "trace: " + "creat(%s) failed: %m", path); + return -1; + } + output = o_stream_create_fd_autoclose(&fd, 0); + o_stream_set_name(output, path); + } + + trace_log = i_new(struct sieve_trace_log, 1); + trace_log->output = output; + + *trace_log_r = trace_log; + return 0; +} + +int sieve_trace_log_create_dir(struct sieve_instance *svinst, const char *dir, + struct sieve_trace_log **trace_log_r) +{ + static unsigned int counter = 0; + const char *timestamp, *prefix; + struct stat st; + + *trace_log_r = NULL; + + if (stat(dir, &st) < 0) { + if (errno != ENOENT && errno != EACCES) { + e_error(svinst->event, "trace: " + "stat(%s) failed: %m", dir); + } + return -1; + } + + timestamp = t_strflocaltime("%Y%m%d-%H%M%S", ioloop_time); + + counter++; + + prefix = t_strdup_printf("%s/%s.%s.%u.trace", + dir, timestamp, my_pid, counter); + return sieve_trace_log_create(svinst, prefix, trace_log_r); +} + +int sieve_trace_log_open(struct sieve_instance *svinst, + struct sieve_trace_log **trace_log_r) +{ + const char *trace_dir = + sieve_setting_get(svinst, "sieve_trace_dir"); + + *trace_log_r = NULL; + if (trace_dir == NULL) + return -1; + + if (svinst->home_dir != NULL) { + /* Expand home dir if necessary */ + if (trace_dir[0] == '~') { + trace_dir = home_expand_tilde(trace_dir, + svinst->home_dir); + } else if (trace_dir[0] != '/') { + trace_dir = t_strconcat(svinst->home_dir, "/", + trace_dir, NULL); + } + } + + return sieve_trace_log_create_dir(svinst, trace_dir, trace_log_r); +} + +void sieve_trace_log_write_line(struct sieve_trace_log *trace_log, + const string_t *line) +{ + struct const_iovec iov[2]; + + if (line == NULL) { + o_stream_nsend_str(trace_log->output, "\n"); + return; + } + + memset(iov, 0, sizeof(iov)); + iov[0].iov_base = str_data(line); + iov[0].iov_len = str_len(line); + iov[1].iov_base = "\n"; + iov[1].iov_len = 1; + o_stream_nsendv(trace_log->output, iov, 2); +} + +void sieve_trace_log_printf(struct sieve_trace_log *trace_log, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + T_BEGIN { + o_stream_nsend_str(trace_log->output, + t_strdup_vprintf(fmt, args)); + } T_END; + va_end(args); +} + +void sieve_trace_log_free(struct sieve_trace_log **_trace_log) +{ + struct sieve_trace_log *trace_log = *_trace_log; + + *_trace_log = NULL; + + if (o_stream_finish(trace_log->output) < 0) { + i_error("write(%s) failed: %s", + o_stream_get_name(trace_log->output), + o_stream_get_error(trace_log->output)); + } + o_stream_destroy(&trace_log->output); + i_free(trace_log); +} + +int sieve_trace_config_get(struct sieve_instance *svinst, + struct sieve_trace_config *tr_config) +{ + const char *tr_level = + sieve_setting_get(svinst, "sieve_trace_level"); + bool tr_debug, tr_addresses; + + i_zero(tr_config); + + if (tr_level == NULL || *tr_level == '\0' || + strcasecmp(tr_level, "none") == 0) + return -1; + + if (strcasecmp(tr_level, "actions") == 0) + tr_config->level = SIEVE_TRLVL_ACTIONS; + else if (strcasecmp(tr_level, "commands") == 0) + tr_config->level = SIEVE_TRLVL_COMMANDS; + else if (strcasecmp(tr_level, "tests") == 0) + tr_config->level = SIEVE_TRLVL_TESTS; + else if (strcasecmp(tr_level, "matching") == 0) + tr_config->level = SIEVE_TRLVL_MATCHING; + else { + e_error(svinst->event, "Unknown trace level: %s", tr_level); + return -1; + } + + tr_debug = FALSE; + (void)sieve_setting_get_bool_value(svinst, "sieve_trace_debug", + &tr_debug); + tr_addresses = FALSE; + (void)sieve_setting_get_bool_value(svinst, "sieve_trace_addresses", + &tr_addresses); + + if (tr_debug) + tr_config->flags |= SIEVE_TRFLG_DEBUG; + if (tr_addresses) + tr_config->flags |= SIEVE_TRFLG_ADDRESSES; + return 0; +} + +/* + * Execution exit codes + */ + +const char *sieve_execution_exitcode_to_str(int code) +{ + switch (code) { + case SIEVE_EXEC_OK: + return "ok"; + case SIEVE_EXEC_FAILURE: + return "failure"; + case SIEVE_EXEC_TEMP_FAILURE: + return "temporary_failure"; + case SIEVE_EXEC_BIN_CORRUPT: + return "binary_corrupt"; + case SIEVE_EXEC_KEEP_FAILED: + return "keep_failed"; + case SIEVE_EXEC_RESOURCE_LIMIT: + return "resource_limit"; + } + i_unreached(); +} + +/* + * User e-mail address + */ + +const struct smtp_address *sieve_get_user_email(struct sieve_instance *svinst) +{ + struct smtp_address *address; + const char *username = svinst->username; + + if (svinst->user_email_implicit != NULL) + return svinst->user_email_implicit; + if (svinst->user_email != NULL) + return svinst->user_email; + + if (smtp_address_parse_mailbox(svinst->pool, username, 0, + &address, NULL) >= 0) { + svinst->user_email_implicit = address; + return svinst->user_email_implicit; + } + + if (svinst->domainname != NULL) { + svinst->user_email_implicit = smtp_address_create( + svinst->pool, username, svinst->domainname); + return svinst->user_email_implicit; + } + return NULL; +} + +/* + * Postmaster address + */ + +const struct message_address * +sieve_get_postmaster(const struct sieve_script_env *senv) +{ + i_assert(senv->postmaster_address != NULL); + return senv->postmaster_address; +} + +const struct smtp_address * +sieve_get_postmaster_smtp(const struct sieve_script_env *senv) +{ + struct smtp_address *addr; + int ret; + + ret = smtp_address_create_from_msg_temp( + sieve_get_postmaster(senv), &addr); + i_assert(ret >= 0); + return addr; +} + +const char *sieve_get_postmaster_address(const struct sieve_script_env *senv) +{ + const struct message_address *postmaster = + sieve_get_postmaster(senv); + string_t *addr = t_str_new(256); + + message_address_write(addr, postmaster); + return str_c(addr); +} + +/* + * Resource usage + */ + +void sieve_resource_usage_init(struct sieve_resource_usage *rusage_r) +{ + i_zero(rusage_r); +} + +void sieve_resource_usage_add(struct sieve_resource_usage *dst, + const struct sieve_resource_usage *src) +{ + if ((UINT_MAX - dst->cpu_time_msecs) < src->cpu_time_msecs) + dst->cpu_time_msecs = UINT_MAX; + else + dst->cpu_time_msecs += src->cpu_time_msecs; +} + +bool sieve_resource_usage_is_high(struct sieve_instance *svinst ATTR_UNUSED, + const struct sieve_resource_usage *rusage) +{ + return (rusage->cpu_time_msecs > SIEVE_HIGH_CPU_TIME_MSECS); +} + +bool sieve_resource_usage_is_excessive( + struct sieve_instance *svinst, + const struct sieve_resource_usage *rusage) +{ + i_assert(svinst->max_cpu_time_secs <= (UINT_MAX / 1000)); + if (svinst->max_cpu_time_secs == 0) + return FALSE; + return (rusage->cpu_time_msecs > (svinst->max_cpu_time_secs * 1000)); +} + +const char * +sieve_resource_usage_get_summary(const struct sieve_resource_usage *rusage) +{ + if (rusage->cpu_time_msecs == 0) + return "no usage recorded"; + + return t_strdup_printf("cpu time = %u ms", rusage->cpu_time_msecs); +} diff --git a/pigeonhole/src/lib-sieve/sieve.h b/pigeonhole/src/lib-sieve/sieve.h new file mode 100644 index 0000000..66a6d12 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve.h @@ -0,0 +1,261 @@ +#ifndef SIEVE_H +#define SIEVE_H + +struct sieve_script; +struct sieve_binary; + +#include "sieve-config.h" +#include "sieve-types.h" +#include "sieve-error.h" + +/* + * Main Sieve library interface + */ + +/* Initialize the sieve engine. Must be called before any sieve functionality is + used. */ +struct sieve_instance * +sieve_init(const struct sieve_environment *env, + const struct sieve_callbacks *callbacks, void *context, bool debug); + +/* Free all memory allocated by the sieve engine. */ +void sieve_deinit(struct sieve_instance **_svinst); + +/* Get capability string for a particular extension. */ +const char * +sieve_get_capabilities(struct sieve_instance *svinst, const char *name); + +/* Set the supported extensions. The provided string is parsed into a list + of extensions that are to be enabled/disabled. */ +void sieve_set_extensions(struct sieve_instance *svinst, + const char *extensions); + + +/* Get top-level event for this Sieve instance. */ +struct event *sieve_get_event(struct sieve_instance *svinst) ATTR_PURE; + +/* + * Script compilation + */ + +/* Compile a Sieve script from a Sieve script object. Returns Sieve binary upon + success and NULL upon failure. */ +struct sieve_binary * +sieve_compile_script(struct sieve_script *script, + struct sieve_error_handler *ehandler, + enum sieve_compile_flags flags, enum sieve_error *error_r) + ATTR_NULL(2, 4); + +/* Compile a Sieve script from a Sieve script location string. Returns Sieve + binary upon success and NULL upon failure. The provided script_name is used + for the internally created Sieve script object. */ +struct sieve_binary * +sieve_compile(struct sieve_instance *svinst, const char *script_location, + const char *script_name, struct sieve_error_handler *ehandler, + enum sieve_compile_flags flags, enum sieve_error *error_r) + ATTR_NULL(3, 4, 6); + +/* + * Reading/writing Sieve binaries + */ + +/* Loads the sieve binary indicated by the provided path. */ +struct sieve_binary * +sieve_load(struct sieve_instance *svinst, const char *bin_path, + enum sieve_error *error_r); +/* First tries to open the binary version of the specified script and if it does + not exist or if it contains errors, the script is (re-)compiled. Note that + errors in the bytecode are caught only at runtime. + */ +struct sieve_binary * +sieve_open_script(struct sieve_script *script, + struct sieve_error_handler *ehandler, + enum sieve_compile_flags flags, enum sieve_error *error_r); +/* First tries to open the binary version of the specified script and if it does + not exist or if it contains errors, the script is (re-)compiled. Note that + errors in the bytecode are caught only at runtime. + */ +struct sieve_binary * +sieve_open(struct sieve_instance *svinst, const char *script_location, + const char *script_name, struct sieve_error_handler *ehandler, + enum sieve_compile_flags flags, enum sieve_error *error_r); + +/* Record resource usage in the binary cumulatively. The binary is disabled when + resource limits are exceeded within a configured timeout. Returns FALSE when + resource limits are exceeded. */ +bool ATTR_NOWARN_UNUSED_RESULT +sieve_record_resource_usage(struct sieve_binary *sbin, + const struct sieve_resource_usage *rusage) + ATTR_NULL(1); + +/* Check whether Sieve binary is (still) executable. Returns 1 if all is OK, + 0 when an error occurred, and -1 when the error is internal. Sets the Sieve + error code in error_r and a user error message in client_error_r when the + error is not internal. */ +int sieve_check_executable(struct sieve_binary *sbin, + enum sieve_error *error_r, + const char **client_error_r); + +/* Saves the binary as the file indicated by the path parameter. This function + will not write the binary to disk when the provided binary object was loaded + earlier from the indicated bin_path, unless update is TRUE. + */ +int sieve_save_as(struct sieve_binary *sbin, const char *bin_path, bool update, + mode_t save_mode, enum sieve_error *error_r); + +/* Saves the binary to the default location. This function will not overwrite + the binary on disk when the provided binary object was loaded earlier from + the default location, unless update is TRUE. + */ +int sieve_save(struct sieve_binary *sbin, bool update, + enum sieve_error *error_r); + +/* Closes a compiled/opened sieve binary. */ +void sieve_close(struct sieve_binary **_sbin); + +/* Obtains the path the binary was compiled or loaded from. */ +const char *sieve_get_source(struct sieve_binary *sbin); +/* Indicates whether the binary was loaded from a pre-compiled file. */ +bool sieve_is_loaded(struct sieve_binary *sbin); + +/* + * Debugging + */ + +/* Dumps the byte code in human-readable form to the specified ostream. */ +void sieve_dump(struct sieve_binary *sbin, + struct ostream *stream, bool verbose); +/* Dumps the byte code in hexdump form to the specified ostream. */ +void sieve_hexdump(struct sieve_binary *sbin, struct ostream *stream); + +/* Executes the bytecode, but only prints the result to the given stream. */ +int sieve_test(struct sieve_binary *sbin, + const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv, + struct sieve_error_handler *ehandler, struct ostream *stream, + enum sieve_execute_flags flags); + +/* + * Script execution + */ + +/* Initializes the scirpt environment from the given mail_user. */ +int sieve_script_env_init(struct sieve_script_env *senv, struct mail_user *user, + const char **error_r); + +/* Executes the binary, including the result. */ +int sieve_execute(struct sieve_binary *sbin, + const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv, + struct sieve_error_handler *exec_ehandler, + struct sieve_error_handler *action_ehandler, + enum sieve_execute_flags flags); + +/* + * Multiscript support + */ + +struct sieve_multiscript; + +struct sieve_multiscript * +sieve_multiscript_start_execute(struct sieve_instance *svinst, + const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv); +struct sieve_multiscript * +sieve_multiscript_start_test(struct sieve_instance *svinst, + const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv, + struct ostream *stream); + +bool sieve_multiscript_run(struct sieve_multiscript *mscript, + struct sieve_binary *sbin, + struct sieve_error_handler *exec_ehandler, + struct sieve_error_handler *action_ehandler, + enum sieve_execute_flags flags); + +bool sieve_multiscript_will_discard(struct sieve_multiscript *mscript); +void sieve_multiscript_run_discard(struct sieve_multiscript *mscript, + struct sieve_binary *sbin, + struct sieve_error_handler *exec_ehandler, + struct sieve_error_handler *action_ehandler, + enum sieve_execute_flags flags); + +int sieve_multiscript_status(struct sieve_multiscript *mscript); + +int sieve_multiscript_finish(struct sieve_multiscript **_mscript, + struct sieve_error_handler *action_ehandler, + enum sieve_execute_flags flags, int status); + +/* + * Configured limits + */ + +unsigned int sieve_max_redirects(struct sieve_instance *svinst); +unsigned int sieve_max_actions(struct sieve_instance *svinst); +size_t sieve_max_script_size(struct sieve_instance *svinst); + +/* + * User log + */ + +const char *sieve_user_get_log_path(struct sieve_instance *svinst, + struct sieve_script *user_script) + ATTR_NULL(2); + +/* + * Script trace log + */ + +struct sieve_trace_log; + +int sieve_trace_log_create(struct sieve_instance *svinst, const char *path, + struct sieve_trace_log **trace_log_r) ATTR_NULL(2); +int sieve_trace_log_create_dir(struct sieve_instance *svinst, const char *dir, + struct sieve_trace_log **trace_log_r) + ATTR_NULL(3); + +int sieve_trace_log_open(struct sieve_instance *svinst, + struct sieve_trace_log **trace_log_r) ATTR_NULL(2); + +void sieve_trace_log_printf(struct sieve_trace_log *trace_log, + const char *fmt, ...) ATTR_FORMAT(2, 3); + +void sieve_trace_log_free(struct sieve_trace_log **_trace_log); + +int sieve_trace_config_get(struct sieve_instance *svinst, + struct sieve_trace_config *tr_config); + +/* + * Execution exit codes + */ + +const char *sieve_execution_exitcode_to_str(int code); + +/* + * Resource usage + */ + +/* Initialize the resource usage struct, clearing all usage statistics. */ +void sieve_resource_usage_init(struct sieve_resource_usage *rusage_r); + +/* Calculate the sum of the provided resource usage statistics, writing the + result to the first. */ +void sieve_resource_usage_add(struct sieve_resource_usage *dst, + const struct sieve_resource_usage *src); + +/* Returns TRUE if the resource usage is sufficiently high to warrant recording + for checking cumulative resource limits (across several different script + executions). */ +bool sieve_resource_usage_is_high(struct sieve_instance *svinst, + const struct sieve_resource_usage *rusage); +/* Returns TRUE when the provided resource usage statistics exceed a configured + policy limit. */ +bool sieve_resource_usage_is_excessive( + struct sieve_instance *svinst, + const struct sieve_resource_usage *rusage); +/* Returns a string containing a description of the resource usage (to be used + log messages). */ +const char * +sieve_resource_usage_get_summary(const struct sieve_resource_usage *rusage); + +#endif diff --git a/pigeonhole/src/lib-sieve/storage/Makefile.am b/pigeonhole/src/lib-sieve/storage/Makefile.am new file mode 100644 index 0000000..ba39e4a --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/Makefile.am @@ -0,0 +1,5 @@ +SUBDIRS = \ + data \ + file \ + dict \ + ldap diff --git a/pigeonhole/src/lib-sieve/storage/Makefile.in b/pigeonhole/src/lib-sieve/storage/Makefile.in new file mode 100644 index 0000000..d81c0c5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/Makefile.in @@ -0,0 +1,697 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/storage +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = \ + data \ + file \ + dict \ + ldap + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/storage/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/storage/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/storage/data/Makefile.am b/pigeonhole/src/lib-sieve/storage/data/Makefile.am new file mode 100644 index 0000000..c17741d --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/data/Makefile.am @@ -0,0 +1,13 @@ +noinst_LTLIBRARIES = libsieve_storage_data.la + +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/lib-sieve + +libsieve_storage_data_la_SOURCES = \ + sieve-data-script.c \ + sieve-data-storage.c + +noinst_HEADERS = \ + sieve-data-storage.h diff --git a/pigeonhole/src/lib-sieve/storage/data/Makefile.in b/pigeonhole/src/lib-sieve/storage/data/Makefile.in new file mode 100644 index 0000000..199f2db --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/data/Makefile.in @@ -0,0 +1,686 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/storage/data +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_storage_data_la_LIBADD = +am_libsieve_storage_data_la_OBJECTS = sieve-data-script.lo \ + sieve-data-storage.lo +libsieve_storage_data_la_OBJECTS = \ + $(am_libsieve_storage_data_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/sieve-data-script.Plo \ + ./$(DEPDIR)/sieve-data-storage.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_storage_data_la_SOURCES) +DIST_SOURCES = $(libsieve_storage_data_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_storage_data.la +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/lib-sieve + +libsieve_storage_data_la_SOURCES = \ + sieve-data-script.c \ + sieve-data-storage.c + +noinst_HEADERS = \ + sieve-data-storage.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/storage/data/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/storage/data/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_storage_data.la: $(libsieve_storage_data_la_OBJECTS) $(libsieve_storage_data_la_DEPENDENCIES) $(EXTRA_libsieve_storage_data_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_storage_data_la_OBJECTS) $(libsieve_storage_data_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-data-script.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-data-storage.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/sieve-data-script.Plo + -rm -f ./$(DEPDIR)/sieve-data-storage.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/sieve-data-script.Plo + -rm -f ./$(DEPDIR)/sieve-data-storage.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/storage/data/sieve-data-script.c b/pigeonhole/src/lib-sieve/storage/data/sieve-data-script.c new file mode 100644 index 0000000..2241bc5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/data/sieve-data-script.c @@ -0,0 +1,95 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "strfuncs.h" +#include "istream.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-dump.h" +#include "sieve-binary.h" + +#include "sieve-data-storage.h" + +/* + * Script data implementation + */ + +static struct sieve_data_script *sieve_data_script_alloc(void) +{ + struct sieve_data_script *dscript; + pool_t pool; + + pool = pool_alloconly_create("sieve_data_script", 1024); + dscript = p_new(pool, struct sieve_data_script, 1); + dscript->script = sieve_data_script; + dscript->script.pool = pool; + + return dscript; +} + +struct sieve_script *sieve_data_script_create_from_input +(struct sieve_instance *svinst, const char *name, struct istream *input) +{ + struct sieve_storage *storage; + struct sieve_data_script *dscript = NULL; + + storage = sieve_storage_alloc(svinst, NULL, &sieve_data_storage, + "", 0, FALSE); + + dscript = sieve_data_script_alloc(); + sieve_script_init(&dscript->script, + storage, &sieve_data_script, "data:", name); + + dscript->data = input; + i_stream_ref(dscript->data); + + sieve_storage_unref(&storage); + + dscript->script.open = TRUE; + + return &dscript->script; +} + +static void sieve_data_script_destroy(struct sieve_script *script) +{ + struct sieve_data_script *dscript = + (struct sieve_data_script *)script; + + i_stream_unref(&dscript->data); +} + +static int sieve_data_script_get_stream +(struct sieve_script *script, struct istream **stream_r, + enum sieve_error *error_r) +{ + struct sieve_data_script *dscript = + (struct sieve_data_script *)script; + + i_stream_ref(dscript->data); + i_stream_seek(dscript->data, 0); + + *stream_r = dscript->data; + *error_r = SIEVE_ERROR_NONE; + return 0; +} + +static bool sieve_data_script_equals +(const struct sieve_script *script ATTR_UNUSED, + const struct sieve_script *other ATTR_UNUSED) +{ + return ( script == other ); +} + +const struct sieve_script sieve_data_script = { + .driver_name = SIEVE_DATA_STORAGE_DRIVER_NAME, + .v = { + .destroy = sieve_data_script_destroy, + + .get_stream = sieve_data_script_get_stream, + + .equals = sieve_data_script_equals + } +}; diff --git a/pigeonhole/src/lib-sieve/storage/data/sieve-data-storage.c b/pigeonhole/src/lib-sieve/storage/data/sieve-data-storage.c new file mode 100644 index 0000000..21b4f35 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/data/sieve-data-storage.c @@ -0,0 +1,47 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-error.h" + +#include "sieve-data-storage.h" + +/* + * Storage class + */ + +static struct sieve_storage *sieve_data_storage_alloc(void) +{ + struct sieve_data_storage *dstorage; + pool_t pool; + + pool = pool_alloconly_create("sieve_data_storage", 1024); + dstorage = p_new(pool, struct sieve_data_storage, 1); + dstorage->storage = sieve_data_storage; + dstorage->storage.pool = pool; + + return &dstorage->storage; +} + +static int sieve_data_storage_init +(struct sieve_storage *storage ATTR_UNUSED, + const char *const *options ATTR_UNUSED, + enum sieve_error *error_r ATTR_UNUSED) +{ + return 0; +} + +/* + * Driver definition + */ + +const struct sieve_storage sieve_data_storage = { + .driver_name = SIEVE_DATA_STORAGE_DRIVER_NAME, + .version = 0, + .v = { + .alloc = sieve_data_storage_alloc, + .init = sieve_data_storage_init, + } +}; diff --git a/pigeonhole/src/lib-sieve/storage/data/sieve-data-storage.h b/pigeonhole/src/lib-sieve/storage/data/sieve-data-storage.h new file mode 100644 index 0000000..a200e25 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/data/sieve-data-storage.h @@ -0,0 +1,30 @@ +#ifndef SIEVE_DATA_STORAGE_H +#define SIEVE_DATA_STORAGE_H + +#include "sieve.h" +#include "sieve-script-private.h" +#include "sieve-storage-private.h" + +/* + * Storage class + */ + +struct sieve_data_storage { + struct sieve_storage storage; +}; + +/* + * Script class + */ + +struct sieve_data_script { + struct sieve_script script; + + struct istream *data; +}; + +struct sieve_script *sieve_data_script_create_from_input + (struct sieve_instance *svinst, const char *name, + struct istream *input); + +#endif diff --git a/pigeonhole/src/lib-sieve/storage/dict/Makefile.am b/pigeonhole/src/lib-sieve/storage/dict/Makefile.am new file mode 100644 index 0000000..2a73f43 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/dict/Makefile.am @@ -0,0 +1,13 @@ +noinst_LTLIBRARIES = libsieve_storage_dict.la + +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/lib-sieve + +libsieve_storage_dict_la_SOURCES = \ + sieve-dict-script.c \ + sieve-dict-storage.c + +noinst_HEADERS = \ + sieve-dict-storage.h diff --git a/pigeonhole/src/lib-sieve/storage/dict/Makefile.in b/pigeonhole/src/lib-sieve/storage/dict/Makefile.in new file mode 100644 index 0000000..58fd0c5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/dict/Makefile.in @@ -0,0 +1,686 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/storage/dict +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_storage_dict_la_LIBADD = +am_libsieve_storage_dict_la_OBJECTS = sieve-dict-script.lo \ + sieve-dict-storage.lo +libsieve_storage_dict_la_OBJECTS = \ + $(am_libsieve_storage_dict_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/sieve-dict-script.Plo \ + ./$(DEPDIR)/sieve-dict-storage.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_storage_dict_la_SOURCES) +DIST_SOURCES = $(libsieve_storage_dict_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_storage_dict.la +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/lib-sieve + +libsieve_storage_dict_la_SOURCES = \ + sieve-dict-script.c \ + sieve-dict-storage.c + +noinst_HEADERS = \ + sieve-dict-storage.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/storage/dict/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/storage/dict/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_storage_dict.la: $(libsieve_storage_dict_la_OBJECTS) $(libsieve_storage_dict_la_DEPENDENCIES) $(EXTRA_libsieve_storage_dict_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_storage_dict_la_OBJECTS) $(libsieve_storage_dict_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-dict-script.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-dict-storage.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/sieve-dict-script.Plo + -rm -f ./$(DEPDIR)/sieve-dict-storage.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/sieve-dict-script.Plo + -rm -f ./$(DEPDIR)/sieve-dict-storage.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/storage/dict/sieve-dict-script.c b/pigeonhole/src/lib-sieve/storage/dict/sieve-dict-script.c new file mode 100644 index 0000000..eb28f7d --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/dict/sieve-dict-script.c @@ -0,0 +1,343 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "strfuncs.h" +#include "istream.h" +#include "dict.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-dump.h" +#include "sieve-binary.h" + +#include "sieve-dict-storage.h" + +/* + * Script dict implementation + */ + +static struct sieve_dict_script *sieve_dict_script_alloc(void) +{ + struct sieve_dict_script *dscript; + pool_t pool; + + pool = pool_alloconly_create("sieve_dict_script", 1024); + dscript = p_new(pool, struct sieve_dict_script, 1); + dscript->script = sieve_dict_script; + dscript->script.pool = pool; + + return dscript; +} + +struct sieve_dict_script *sieve_dict_script_init +(struct sieve_dict_storage *dstorage, const char *name) +{ + struct sieve_storage *storage = &dstorage->storage; + struct sieve_dict_script *dscript = NULL; + const char *location; + + if ( name == NULL ) { + name = SIEVE_DICT_SCRIPT_DEFAULT; + location = storage->location; + } else { + location = t_strconcat + (storage->location, ";name=", name, NULL); + } + + dscript = sieve_dict_script_alloc(); + sieve_script_init(&dscript->script, + storage, &sieve_dict_script, location, name); + + return dscript; +} + +static void sieve_dict_script_destroy(struct sieve_script *script) +{ + struct sieve_dict_script *dscript = + (struct sieve_dict_script *)script; + + if ( dscript->data_pool != NULL ) + pool_unref(&dscript->data_pool); +} + +static int sieve_dict_script_open +(struct sieve_script *script, enum sieve_error *error_r) +{ + struct sieve_dict_script *dscript = + (struct sieve_dict_script *)script; + struct sieve_storage *storage = script->storage; + struct sieve_dict_storage *dstorage = + (struct sieve_dict_storage *)storage; + const char *name = script->name; + const char *path, *data_id, *error; + int ret; + + if ( sieve_dict_storage_get_dict + (dstorage, &dscript->dict, error_r) < 0 ) + return -1; + + path = t_strconcat + (DICT_SIEVE_NAME_PATH, dict_escape_string(name), NULL); + + struct dict_op_settings set = { + .username = dstorage->username, + }; + ret = dict_lookup + (dscript->dict, &set, script->pool, path, &data_id, &error); + if ( ret <= 0 ) { + if ( ret < 0 ) { + sieve_script_set_critical(script, + "Failed to lookup script id from path %s: %s", path, error); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + } else { + e_debug(script->event, + "Script `%s' not found at path %s", name, path); + sieve_script_set_error(script, + SIEVE_ERROR_NOT_FOUND, + "Sieve script `%s' not found", name); + *error_r = SIEVE_ERROR_NOT_FOUND; + } + return -1; + } + + dscript->data_id = p_strdup(script->pool, data_id); + return 0; +} + +static int sieve_dict_script_get_stream +(struct sieve_script *script, struct istream **stream_r, + enum sieve_error *error_r) +{ + struct sieve_dict_script *dscript = + (struct sieve_dict_script *)script; + struct sieve_dict_storage *dstorage = + (struct sieve_dict_storage *)script->storage; + const char *path, *name = script->name, *data, *error; + int ret; + + dscript->data_pool = + pool_alloconly_create("sieve_dict_script data pool", 1024); + + path = t_strconcat + (DICT_SIEVE_DATA_PATH, dict_escape_string(dscript->data_id), NULL); + + struct dict_op_settings set = { + .username = dstorage->username, + }; + ret = dict_lookup + (dscript->dict, &set, dscript->data_pool, path, &data, &error); + if ( ret <= 0 ) { + if ( ret < 0 ) { + sieve_script_set_critical(script, + "Failed to lookup data with id `%s' " + "for script `%s' from path %s: %s", + dscript->data_id, name, path, error); + } else { + sieve_script_set_critical(script, + "Data with id `%s' for script `%s' " + "not found at path %s", + dscript->data_id, name, path); + } + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + + dscript->data = p_strdup(script->pool, data); + *stream_r = i_stream_create_from_data(dscript->data, strlen(dscript->data)); + return 0; +} + +static int sieve_dict_script_binary_read_metadata +(struct sieve_script *script, struct sieve_binary_block *sblock, + sieve_size_t *offset) +{ + struct sieve_dict_script *dscript = + (struct sieve_dict_script *)script; + struct sieve_binary *sbin = + sieve_binary_block_get_binary(sblock); + string_t *data_id; + + if ( dscript->data_id == NULL && + sieve_script_open(script, NULL) < 0 ) + return 0; + + if ( !sieve_binary_read_string(sblock, offset, &data_id) ) { + e_error(script->event, + "Binary `%s' has invalid metadata for script `%s'", + sieve_binary_path(sbin), sieve_script_location(script)); + return -1; + } + i_assert( dscript->data_id != NULL ); + if ( strcmp(str_c(data_id), dscript->data_id) != 0 ) { + e_debug(script->event, + "Binary `%s' reports different data ID for script `%s' " + "(`%s' rather than `%s')", + sieve_binary_path(sbin), sieve_script_location(script), + str_c(data_id), dscript->data_id); + return 0; + } + return 1; +} + +static void sieve_dict_script_binary_write_metadata +(struct sieve_script *script, struct sieve_binary_block *sblock) +{ + struct sieve_dict_script *dscript = + (struct sieve_dict_script *)script; + + sieve_binary_emit_cstring(sblock, dscript->data_id); +} + +static bool sieve_dict_script_binary_dump_metadata +(struct sieve_script *script ATTR_UNUSED, struct sieve_dumptime_env *denv, + struct sieve_binary_block *sblock, sieve_size_t *offset) +{ + string_t *data_id; + + if ( !sieve_binary_read_string(sblock, offset, &data_id) ) + return FALSE; + sieve_binary_dumpf(denv, "dict.data_id = %s\n", str_c(data_id)); + + return TRUE; +} + +static const char * sieve_dict_script_get_binpath +(struct sieve_dict_script *dscript) +{ + struct sieve_script *script = &dscript->script; + struct sieve_storage *storage = script->storage; + + if ( dscript->binpath == NULL ) { + if ( storage->bin_dir == NULL ) + return NULL; + dscript->binpath = p_strconcat(script->pool, + storage->bin_dir, "/", + sieve_binfile_from_name(script->name), NULL); + } + + return dscript->binpath; +} + +static struct sieve_binary *sieve_dict_script_binary_load +(struct sieve_script *script, enum sieve_error *error_r) +{ + struct sieve_dict_script *dscript = + (struct sieve_dict_script *)script; + + if ( sieve_dict_script_get_binpath(dscript) == NULL ) + return NULL; + + return sieve_binary_open(script->storage->svinst, + dscript->binpath, script, error_r); +} + +static int sieve_dict_script_binary_save +(struct sieve_script *script, struct sieve_binary *sbin, bool update, + enum sieve_error *error_r) +{ + struct sieve_dict_script *dscript = + (struct sieve_dict_script *)script; + + if ( sieve_dict_script_get_binpath(dscript) == NULL ) + return 0; + if ( sieve_storage_setup_bindir(script->storage, 0700) < 0 ) + return -1; + + return sieve_binary_save(sbin, + dscript->binpath, update, 0600, error_r); +} + +static bool sieve_dict_script_equals +(const struct sieve_script *script, const struct sieve_script *other) +{ + struct sieve_storage *storage = script->storage; + struct sieve_storage *sother = other->storage; + + if ( strcmp(storage->location, sother->location) != 0 ) + return FALSE; + + i_assert( script->name != NULL && other->name != NULL ); + + return ( strcmp(script->name, other->name) == 0 ); +} + +const struct sieve_script sieve_dict_script = { + .driver_name = SIEVE_DICT_STORAGE_DRIVER_NAME, + .v = { + .destroy = sieve_dict_script_destroy, + + .open = sieve_dict_script_open, + + .get_stream = sieve_dict_script_get_stream, + + .binary_read_metadata =sieve_dict_script_binary_read_metadata, + .binary_write_metadata = sieve_dict_script_binary_write_metadata, + .binary_dump_metadata = sieve_dict_script_binary_dump_metadata, + .binary_load = sieve_dict_script_binary_load, + .binary_save = sieve_dict_script_binary_save, + + .equals = sieve_dict_script_equals + } +}; + +/* + * Script sequence + */ + +struct sieve_dict_script_sequence { + struct sieve_script_sequence seq; + + bool done:1; +}; + +struct sieve_script_sequence *sieve_dict_storage_get_script_sequence +(struct sieve_storage *storage, enum sieve_error *error_r) +{ + struct sieve_dict_script_sequence *dseq = NULL; + + if ( error_r != NULL ) + *error_r = SIEVE_ERROR_NONE; + + /* Create sequence object */ + dseq = i_new(struct sieve_dict_script_sequence, 1); + sieve_script_sequence_init(&dseq->seq, storage); + + return &dseq->seq; +} + +struct sieve_script *sieve_dict_script_sequence_next +(struct sieve_script_sequence *seq, enum sieve_error *error_r) +{ + struct sieve_dict_script_sequence *dseq = + (struct sieve_dict_script_sequence *)seq; + struct sieve_dict_storage *dstorage = + (struct sieve_dict_storage *)seq->storage; + struct sieve_dict_script *dscript; + + if ( error_r != NULL ) + *error_r = SIEVE_ERROR_NONE; + + if ( dseq->done ) + return NULL; + dseq->done = TRUE; + + dscript = sieve_dict_script_init + (dstorage, seq->storage->script_name); + if ( sieve_script_open(&dscript->script, error_r) < 0 ) { + struct sieve_script *script = &dscript->script; + sieve_script_unref(&script); + return NULL; + } + + return &dscript->script; +} + +void sieve_dict_script_sequence_destroy(struct sieve_script_sequence *seq) +{ + struct sieve_dict_script_sequence *dseq = + (struct sieve_dict_script_sequence *)seq; + i_free(dseq); +} + diff --git a/pigeonhole/src/lib-sieve/storage/dict/sieve-dict-storage.c b/pigeonhole/src/lib-sieve/storage/dict/sieve-dict-storage.c new file mode 100644 index 0000000..7f50816 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/dict/sieve-dict-storage.c @@ -0,0 +1,193 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "dict.h" + +#include "sieve-common.h" +#include "sieve-error.h" + +#include "sieve-dict-storage.h" + +/* + * Storage class + */ + +static struct sieve_storage *sieve_dict_storage_alloc(void) +{ + struct sieve_dict_storage *dstorage; + pool_t pool; + + pool = pool_alloconly_create("sieve_dict_storage", 1024); + dstorage = p_new(pool, struct sieve_dict_storage, 1); + dstorage->storage = sieve_dict_storage; + dstorage->storage.pool = pool; + + return &dstorage->storage; +} + +static int sieve_dict_storage_init +(struct sieve_storage *storage, const char *const *options, + enum sieve_error *error_r) +{ + struct sieve_dict_storage *dstorage = + (struct sieve_dict_storage *)storage; + struct sieve_instance *svinst = storage->svinst; + const char *uri = storage->location, *username = NULL; + + if ( options != NULL ) { + while ( *options != NULL ) { + const char *option = *options; + + if ( strncasecmp(option, "user=", 5) == 0 && option[5] != '\0' ) { + username = option+5; + } else { + sieve_storage_set_critical(storage, + "Invalid option `%s'", option); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + + options++; + } + } + + if ( username == NULL ) { + if ( svinst->username == NULL ) { + sieve_storage_set_critical(storage, + "No username specified"); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + username = svinst->username; + } + + if ( svinst->base_dir == NULL ) { + sieve_storage_set_critical(storage, + "BUG: Sieve interpreter is initialized without a base_dir"); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + + e_debug(storage->event, "user=%s, uri=%s", username, uri); + + dstorage->uri = p_strdup(storage->pool, uri); + dstorage->username = p_strdup(storage->pool, username); + + storage->location = p_strconcat(storage->pool, + SIEVE_DICT_STORAGE_DRIVER_NAME, ":", storage->location, + ";user=", username, NULL); + + return 0; +} + +int sieve_dict_storage_get_dict +(struct sieve_dict_storage *dstorage, struct dict **dict_r, + enum sieve_error *error_r) +{ + struct sieve_storage *storage = &dstorage->storage; + struct sieve_instance *svinst = storage->svinst; + struct dict_settings dict_set; + const char *error; + int ret; + + if ( dstorage->dict == NULL ) { + i_zero(&dict_set); + dict_set.base_dir = svinst->base_dir; + ret = dict_init(dstorage->uri, &dict_set, &dstorage->dict, &error); + if ( ret < 0 ) { + sieve_storage_set_critical(storage, + "Failed to initialize dict with data `%s' for user `%s': %s", + dstorage->uri, dstorage->username, error); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + } + + *dict_r = dstorage->dict; + return 0; +} + +static void sieve_dict_storage_destroy(struct sieve_storage *storage) +{ + struct sieve_dict_storage *dstorage = + (struct sieve_dict_storage *)storage; + + if ( dstorage->dict != NULL ) + dict_deinit(&dstorage->dict); +} + +/* + * Script access + */ + +static struct sieve_script *sieve_dict_storage_get_script +(struct sieve_storage *storage, const char *name) +{ + struct sieve_dict_storage *dstorage = + (struct sieve_dict_storage *)storage; + struct sieve_dict_script *dscript; + + T_BEGIN { + dscript = sieve_dict_script_init(dstorage, name); + } T_END; + + return &dscript->script; +} + +/* + * Active script + */ + +struct sieve_script *sieve_dict_storage_active_script_open +(struct sieve_storage *storage) +{ + struct sieve_dict_storage *dstorage = + (struct sieve_dict_storage *)storage; + struct sieve_dict_script *dscript; + + dscript = sieve_dict_script_init + (dstorage, storage->script_name); + if ( sieve_script_open(&dscript->script, NULL) < 0 ) { + struct sieve_script *script = &dscript->script; + sieve_script_unref(&script); + return NULL; + } + + return &dscript->script; +} + +int sieve_dict_storage_active_script_get_name +(struct sieve_storage *storage, const char **name_r) +{ + if ( storage->script_name != NULL ) + *name_r = storage->script_name; + else + *name_r = SIEVE_DICT_SCRIPT_DEFAULT; + return 0; +} + +/* + * Driver definition + */ + +const struct sieve_storage sieve_dict_storage = { + .driver_name = SIEVE_DICT_STORAGE_DRIVER_NAME, + .version = 0, + .v = { + .alloc = sieve_dict_storage_alloc, + .destroy = sieve_dict_storage_destroy, + .init = sieve_dict_storage_init, + + .get_script = sieve_dict_storage_get_script, + + .get_script_sequence = sieve_dict_storage_get_script_sequence, + .script_sequence_next = sieve_dict_script_sequence_next, + .script_sequence_destroy = sieve_dict_script_sequence_destroy, + + .active_script_get_name = sieve_dict_storage_active_script_get_name, + .active_script_open = sieve_dict_storage_active_script_open, + + // FIXME: impement management interface + } +}; diff --git a/pigeonhole/src/lib-sieve/storage/dict/sieve-dict-storage.h b/pigeonhole/src/lib-sieve/storage/dict/sieve-dict-storage.h new file mode 100644 index 0000000..1f92221 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/dict/sieve-dict-storage.h @@ -0,0 +1,66 @@ +#ifndef SIEVE_DICT_STORAGE_H +#define SIEVE_DICT_STORAGE_H + +#include "sieve.h" +#include "sieve-script-private.h" +#include "sieve-storage-private.h" + +#define DICT_SIEVE_PATH DICT_PATH_PRIVATE"sieve/" +#define DICT_SIEVE_NAME_PATH DICT_SIEVE_PATH"name/" +#define DICT_SIEVE_DATA_PATH DICT_SIEVE_PATH"data/" + +#define SIEVE_DICT_SCRIPT_DEFAULT "default" + +/* + * Storage class + */ + +struct sieve_dict_storage { + struct sieve_storage storage; + + const char *username; + const char *uri; + + struct dict *dict; +}; + +int sieve_dict_storage_get_dict + (struct sieve_dict_storage *dstorage, struct dict **dict_r, + enum sieve_error *error_r); + +struct sieve_script *sieve_dict_storage_active_script_open + (struct sieve_storage *storage); +int sieve_dict_storage_active_script_get_name + (struct sieve_storage *storage, const char **name_r); + +/* + * Script class + */ + +struct sieve_dict_script { + struct sieve_script script; + + struct dict *dict; + + pool_t data_pool; + const char *data_id; + const char *data; + + const char *binpath; +}; + +struct sieve_dict_script *sieve_dict_script_init + (struct sieve_dict_storage *dstorage, const char *name); + +/* + * Script sequence + */ + +struct sieve_script_sequence *sieve_dict_storage_get_script_sequence + (struct sieve_storage *storage, enum sieve_error *error_r); + +struct sieve_script *sieve_dict_script_sequence_next + (struct sieve_script_sequence *seq, enum sieve_error *error_r); +void sieve_dict_script_sequence_destroy(struct sieve_script_sequence *seq); + +#endif diff --git a/pigeonhole/src/lib-sieve/storage/file/Makefile.am b/pigeonhole/src/lib-sieve/storage/file/Makefile.am new file mode 100644 index 0000000..b401fa8 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/file/Makefile.am @@ -0,0 +1,19 @@ +noinst_LTLIBRARIES = libsieve_storage_file.la + +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/lib-sieve \ + -I$(top_srcdir)/src/lib-sieve/util + +libsieve_storage_file_la_SOURCES = \ + sieve-file-script.c \ + sieve-file-script-sequence.c \ + sieve-file-storage-active.c \ + sieve-file-storage-save.c \ + sieve-file-storage-list.c \ + sieve-file-storage-quota.c \ + sieve-file-storage.c + +noinst_HEADERS = \ + sieve-file-storage.h diff --git a/pigeonhole/src/lib-sieve/storage/file/Makefile.in b/pigeonhole/src/lib-sieve/storage/file/Makefile.in new file mode 100644 index 0000000..8432831 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/file/Makefile.in @@ -0,0 +1,714 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-sieve/storage/file +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_storage_file_la_LIBADD = +am_libsieve_storage_file_la_OBJECTS = sieve-file-script.lo \ + sieve-file-script-sequence.lo sieve-file-storage-active.lo \ + sieve-file-storage-save.lo sieve-file-storage-list.lo \ + sieve-file-storage-quota.lo sieve-file-storage.lo +libsieve_storage_file_la_OBJECTS = \ + $(am_libsieve_storage_file_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/sieve-file-script-sequence.Plo \ + ./$(DEPDIR)/sieve-file-script.Plo \ + ./$(DEPDIR)/sieve-file-storage-active.Plo \ + ./$(DEPDIR)/sieve-file-storage-list.Plo \ + ./$(DEPDIR)/sieve-file-storage-quota.Plo \ + ./$(DEPDIR)/sieve-file-storage-save.Plo \ + ./$(DEPDIR)/sieve-file-storage.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_storage_file_la_SOURCES) +DIST_SOURCES = $(libsieve_storage_file_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_storage_file.la +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/lib-sieve \ + -I$(top_srcdir)/src/lib-sieve/util + +libsieve_storage_file_la_SOURCES = \ + sieve-file-script.c \ + sieve-file-script-sequence.c \ + sieve-file-storage-active.c \ + sieve-file-storage-save.c \ + sieve-file-storage-list.c \ + sieve-file-storage-quota.c \ + sieve-file-storage.c + +noinst_HEADERS = \ + sieve-file-storage.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/storage/file/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/storage/file/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_storage_file.la: $(libsieve_storage_file_la_OBJECTS) $(libsieve_storage_file_la_DEPENDENCIES) $(EXTRA_libsieve_storage_file_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_storage_file_la_OBJECTS) $(libsieve_storage_file_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-file-script-sequence.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-file-script.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-file-storage-active.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-file-storage-list.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-file-storage-quota.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-file-storage-save.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-file-storage.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/sieve-file-script-sequence.Plo + -rm -f ./$(DEPDIR)/sieve-file-script.Plo + -rm -f ./$(DEPDIR)/sieve-file-storage-active.Plo + -rm -f ./$(DEPDIR)/sieve-file-storage-list.Plo + -rm -f ./$(DEPDIR)/sieve-file-storage-quota.Plo + -rm -f ./$(DEPDIR)/sieve-file-storage-save.Plo + -rm -f ./$(DEPDIR)/sieve-file-storage.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/sieve-file-script-sequence.Plo + -rm -f ./$(DEPDIR)/sieve-file-script.Plo + -rm -f ./$(DEPDIR)/sieve-file-storage-active.Plo + -rm -f ./$(DEPDIR)/sieve-file-storage-list.Plo + -rm -f ./$(DEPDIR)/sieve-file-storage-quota.Plo + -rm -f ./$(DEPDIR)/sieve-file-storage-save.Plo + -rm -f ./$(DEPDIR)/sieve-file-storage.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/storage/file/sieve-file-script-sequence.c b/pigeonhole/src/lib-sieve/storage/file/sieve-file-script-sequence.c new file mode 100644 index 0000000..a1ae75d --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/file/sieve-file-script-sequence.c @@ -0,0 +1,244 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "array.h" +#include "eacces-error.h" + +#include "sieve-common.h" +#include "sieve-script-private.h" + +#include "sieve-file-storage.h" + +#include <stdio.h> +#include <dirent.h> + +/* + * Script sequence + */ + +struct sieve_file_script_sequence { + struct sieve_script_sequence seq; + pool_t pool; + + ARRAY_TYPE(const_string) script_files; + unsigned int index; + + bool storage_is_file:1; +}; + +static int sieve_file_script_sequence_read_dir +(struct sieve_file_script_sequence *fseq, const char *path) +{ + struct sieve_storage *storage = fseq->seq.storage; + DIR *dirp; + int ret = 0; + + /* Open the directory */ + if ( (dirp = opendir(path)) == NULL ) { + switch ( errno ) { + case ENOENT: + sieve_storage_set_error(storage, + SIEVE_ERROR_NOT_FOUND, + "Script sequence location not found"); + break; + case EACCES: + sieve_storage_set_error(storage, + SIEVE_ERROR_NO_PERMISSION, + "Script sequence location not accessible"); + e_error(storage->event, + "Failed to open sieve sequence: %s", + eacces_error_get("stat", path)); + break; + default: + sieve_storage_set_critical(storage, + "Failed to open sieve sequence: " + "opendir(%s) failed: %m", path); + break; + } + return -1; + } + + /* Read and sort script files */ + for (;;) { + const char *const *files; + unsigned int count, i; + const char *file; + struct dirent *dp; + struct stat st; + + errno = 0; + if ( (dp=readdir(dirp)) == NULL ) + break; + + if ( !sieve_script_file_has_extension(dp->d_name) ) + continue; + + file = NULL; + T_BEGIN { + if ( path[strlen(path)-1] == '/' ) + file = t_strconcat(path, dp->d_name, NULL); + else + file = t_strconcat(path, "/", dp->d_name, NULL); + + if ( stat(file, &st) == 0 && S_ISREG(st.st_mode) ) + file = p_strdup(fseq->pool, dp->d_name); + else + file = NULL; + } T_END; + + if (file == NULL) + continue; + + /* Insert into sorted array */ + files = array_get(&fseq->script_files, &count); + for ( i = 0; i < count; i++ ) { + if ( strcmp(file, files[i]) < 0 ) + break; + } + + if ( i == count ) + array_append(&fseq->script_files, &file, 1); + else + array_insert(&fseq->script_files, i, &file, 1); + } + + if ( errno != 0 ) { + sieve_storage_set_critical(storage, + "Failed to read sequence directory: " + "readdir(%s) failed: %m", path); + ret = -1; + } + + /* Close the directory */ + if ( dirp != NULL && closedir(dirp) < 0 ) { + e_error(storage->event, + "Failed to close sequence directory: " + "closedir(%s) failed: %m", path); + } + return ret; +} + +struct sieve_script_sequence *sieve_file_storage_get_script_sequence +(struct sieve_storage *storage, enum sieve_error *error_r) +{ + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)storage; + struct sieve_file_script_sequence *fseq = NULL; + const char *name = storage->script_name; + const char *file; + pool_t pool; + struct stat st; + + /* Specified path can either be a regular file or a directory */ + if ( stat(fstorage->path, &st) != 0 ) { + switch ( errno ) { + case ENOENT: + sieve_storage_set_error(storage, + SIEVE_ERROR_NOT_FOUND, + "Script sequence location not found"); + break; + case EACCES: + sieve_storage_set_error(storage, + SIEVE_ERROR_NO_PERMISSION, + "Script sequence location not accessible"); + e_error(storage->event, + "Failed to open sieve sequence: %s", + eacces_error_get("stat", fstorage->path)); + break; + default: + sieve_storage_set_critical(storage, + "Failed to open sieve sequence: " + "stat(%s) failed: %m", fstorage->path); + break; + } + *error_r = storage->error_code; + return NULL; + } + + /* Create sequence object */ + pool = pool_alloconly_create("sieve_file_script_sequence", 1024); + fseq = p_new(pool, struct sieve_file_script_sequence, 1); + fseq->pool = pool; + sieve_script_sequence_init(&fseq->seq, storage); + + if ( S_ISDIR(st.st_mode) ) { + i_array_init(&fseq->script_files, 16); + + /* Path is directory */ + if (name == 0 || *name == '\0') { + /* Read all '.sieve' files in directory */ + if (sieve_file_script_sequence_read_dir + (fseq, fstorage->path) < 0) { + *error_r = storage->error_code; + sieve_file_script_sequence_destroy(&fseq->seq); + return NULL; + } + + } else { + /* Read specific script file */ + file = sieve_script_file_from_name(name); + file = p_strdup(pool, file); + array_append(&fseq->script_files, &file, 1); + } + + } else { + /* Path is a file + (apparently; we'll see about that once it is opened) */ + fseq->storage_is_file = TRUE; + } + + return &fseq->seq; +} + +struct sieve_script *sieve_file_script_sequence_next +(struct sieve_script_sequence *seq, enum sieve_error *error_r) +{ + struct sieve_file_script_sequence *fseq = + (struct sieve_file_script_sequence *)seq; + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)seq->storage; + struct sieve_file_script *fscript; + const char *const *files; + unsigned int count; + + if ( error_r != NULL ) + *error_r = SIEVE_ERROR_NONE; + + fscript = NULL; + if ( fseq->storage_is_file ) { + if ( fseq->index++ < 1 ) + fscript = sieve_file_script_open_from_name(fstorage, NULL); + + } else { + files = array_get(&fseq->script_files, &count); + + while ( fseq->index < count ) { + fscript = sieve_file_script_open_from_filename + (fstorage, files[fseq->index++], NULL); + if (fscript != NULL) + break; + if (seq->storage->error_code != SIEVE_ERROR_NOT_FOUND) + break; + sieve_storage_clear_error(seq->storage); + } + } + + if (fscript == NULL ) { + if ( error_r != NULL ) + *error_r = seq->storage->error_code; + return NULL; + } + return &fscript->script; +} + +void sieve_file_script_sequence_destroy(struct sieve_script_sequence *seq) +{ + struct sieve_file_script_sequence *fseq = + (struct sieve_file_script_sequence *)seq; + + if ( array_is_created(&fseq->script_files) ) + array_free(&fseq->script_files); + pool_unref(&fseq->pool); +} diff --git a/pigeonhole/src/lib-sieve/storage/file/sieve-file-script.c b/pigeonhole/src/lib-sieve/storage/file/sieve-file-script.c new file mode 100644 index 0000000..3c4ec60 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/file/sieve-file-script.c @@ -0,0 +1,832 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "mempool.h" +#include "path-util.h" +#include "istream.h" +#include "time-util.h" +#include "eacces-error.h" + +#include "sieve-binary.h" +#include "sieve-script-private.h" + +#include "sieve-file-storage.h" + +#include <stdio.h> +#include <unistd.h> +#include <ctype.h> +#include <time.h> +#include <fcntl.h> + +/* + * Filename to name/name to filename + */ + +const char *sieve_script_file_get_scriptname(const char *filename) +{ + const char *ext; + + /* Extract the script name */ + ext = strrchr(filename, '.'); + if ( ext == NULL || ext == filename || + strcmp(ext, "."SIEVE_SCRIPT_FILEEXT) != 0 ) + return NULL; + + return t_strdup_until(filename, ext); +} + +bool sieve_script_file_has_extension(const char *filename) +{ + return ( sieve_script_file_get_scriptname(filename) != NULL ); +} + +const char *sieve_script_file_from_name(const char *name) +{ + return t_strconcat(name, "."SIEVE_SCRIPT_FILEEXT, NULL); +} + +/* + * Common error handling + */ + +static void sieve_file_script_handle_error +(struct sieve_file_script *fscript, const char *op, const char *path, + const char *name, enum sieve_error *error_r) +{ + struct sieve_script *script = &fscript->script; + const char *abspath, *error; + + switch ( errno ) { + case ENOENT: + if (t_abspath(path, &abspath, &error) < 0) { + sieve_script_set_error(script, + SIEVE_ERROR_TEMP_FAILURE, + "t_abspath(%s) failed: %s", + path, error); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + break; + } + e_debug(script->event, "File `%s' not found", abspath); + sieve_script_set_error(script, + SIEVE_ERROR_NOT_FOUND, + "Sieve script `%s' not found", name); + *error_r = SIEVE_ERROR_NOT_FOUND; + break; + case EACCES: + sieve_script_set_critical(script, + "Failed to %s sieve script: %s", + op, eacces_error_get(op, path)); + *error_r = SIEVE_ERROR_NO_PERMISSION; + break; + default: + sieve_script_set_critical(script, + "Failed to %s sieve script: %s(%s) failed: %m", + op, op, path); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + break; + } +} + +/* + * + */ + +static struct sieve_file_script *sieve_file_script_alloc(void) +{ + struct sieve_file_script *fscript; + pool_t pool; + + pool = pool_alloconly_create("sieve_file_script", 2048); + fscript = p_new(pool, struct sieve_file_script, 1); + fscript->script = sieve_file_script; + fscript->script.pool = pool; + + return fscript; +} + +struct sieve_file_script *sieve_file_script_init_from_filename +(struct sieve_file_storage *fstorage, const char *filename, + const char *scriptname) +{ + struct sieve_storage *storage = &fstorage->storage; + struct sieve_file_script *fscript = NULL; + + /* Prevent initializing the active script link as a script when it + * resides in the sieve storage directory. + */ + if ( scriptname != NULL && fstorage->link_path != NULL && + *(fstorage->link_path) == '\0' ) { + if ( strcmp(filename, fstorage->active_fname) == 0 ) { + sieve_storage_set_error(storage, + SIEVE_ERROR_NOT_FOUND, + "Script `%s' does not exist.", scriptname); + return NULL; + } + } + + fscript = sieve_file_script_alloc(); + sieve_script_init + (&fscript->script, storage, &sieve_file_script, + sieve_file_storage_path_extend(fstorage, filename), scriptname); + fscript->filename = p_strdup(fscript->script.pool, filename); + return fscript; +} + +struct sieve_file_script *sieve_file_script_open_from_filename +(struct sieve_file_storage *fstorage, const char *filename, + const char *scriptname) +{ + struct sieve_file_script *fscript; + enum sieve_error error; + + fscript = sieve_file_script_init_from_filename + (fstorage, filename, scriptname); + if ( fscript == NULL ) + return NULL; + + if ( sieve_script_open(&fscript->script, &error) < 0 ) { + struct sieve_script *script = &fscript->script; + sieve_script_unref(&script); + return NULL; + } + + return fscript; +} + +struct sieve_file_script *sieve_file_script_init_from_name +(struct sieve_file_storage *fstorage, const char *name) +{ + struct sieve_storage *storage = &fstorage->storage; + struct sieve_file_script *fscript; + + if (name != NULL && S_ISDIR(fstorage->st.st_mode)) { + return sieve_file_script_init_from_filename + (fstorage, sieve_script_file_from_name(name), name); + } + + fscript = sieve_file_script_alloc(); + sieve_script_init + (&fscript->script, storage, &sieve_file_script, + fstorage->active_path, name); + return fscript; +} + +struct sieve_file_script *sieve_file_script_open_from_name +(struct sieve_file_storage *fstorage, const char *name) +{ + struct sieve_file_script *fscript; + enum sieve_error error; + + fscript = sieve_file_script_init_from_name(fstorage, name); + if ( fscript == NULL ) + return NULL; + + if ( sieve_script_open(&fscript->script, &error) < 0 ) { + struct sieve_script *script = &fscript->script; + sieve_script_unref(&script); + return NULL; + } + + return fscript; +} + +struct sieve_file_script *sieve_file_script_init_from_path +(struct sieve_file_storage *fstorage, const char *path, + const char *scriptname, enum sieve_error *error_r) +{ + struct sieve_instance *svinst = fstorage->storage.svinst; + struct sieve_file_storage *fsubstorage; + struct sieve_file_script *fscript; + struct sieve_storage *substorage; + enum sieve_error error; + + if ( error_r != NULL ) + *error_r = SIEVE_ERROR_NONE; + else + error_r = &error; + + fsubstorage = sieve_file_storage_init_from_path + (svinst, path, 0, error_r); + if (fsubstorage == NULL) + return NULL; + substorage = &fsubstorage->storage; + + fscript = sieve_file_script_alloc(); + sieve_script_init(&fscript->script, + substorage, &sieve_file_script, path, scriptname); + sieve_storage_unref(&substorage); + + return fscript; +} + +struct sieve_file_script *sieve_file_script_open_from_path +(struct sieve_file_storage *fstorage, const char *path, + const char *scriptname, enum sieve_error *error_r) +{ + struct sieve_storage *storage = &fstorage->storage; + struct sieve_file_script *fscript; + enum sieve_error error; + + if ( error_r != NULL ) + *error_r = SIEVE_ERROR_NONE; + else + error_r = &error; + + fscript = sieve_file_script_init_from_path + (fstorage, path, scriptname, error_r); + if (fscript == NULL) { + sieve_storage_set_error(storage, + *error_r, "Failed to open script"); + return NULL; + } + + if ( sieve_script_open(&fscript->script, error_r) < 0 ) { + struct sieve_script *script = &fscript->script; + const char *errormsg; + + errormsg = sieve_script_get_last_error(&fscript->script, error_r); + sieve_storage_set_error(storage, + *error_r, "%s", errormsg); + sieve_script_unref(&script); + return NULL; + } + + return fscript; +} + +/* + * Open + */ + +static int sieve_file_script_stat +(const char *path, struct stat *st, struct stat *lnk_st) +{ + if ( lstat(path, st) < 0 ) + return -1; + + *lnk_st = *st; + + if ( S_ISLNK(st->st_mode) && stat(path, st) < 0 ) + return -1; + + return 0; +} + +static const char * +path_split_filename(const char *path, const char **dirpath_r) +{ + const char *filename; + + filename = strrchr(path, '/'); + if ( filename == NULL ) { + *dirpath_r = ""; + filename = path; + } else { + *dirpath_r = t_strdup_until(path, filename); + filename++; + } + return filename; +} + +static int sieve_file_script_open +(struct sieve_script *script, enum sieve_error *error_r) +{ + struct sieve_file_script *fscript = + (struct sieve_file_script *)script; + struct sieve_storage *storage = script->storage; + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)storage; + pool_t pool = script->pool; + const char *filename, *name, *path; + const char *dirpath, *basename, *binpath, *binprefix; + struct stat st, lnk_st; + bool success = TRUE; + int ret = 0; + + filename = fscript->filename; + basename = NULL; + name = script->name; + st = fstorage->st; + lnk_st = fstorage->lnk_st; + + if (name == NULL) + name = storage->script_name; + + T_BEGIN { + if ( S_ISDIR(st.st_mode) ) { + /* Storage is a directory */ + path = fstorage->path; + + if ( (filename == NULL || *filename == '\0') && + name != NULL && *name != '\0' ) { + /* Name is used to find actual filename */ + filename = sieve_script_file_from_name(name); + basename = name; + } + if ( filename == NULL || *filename == '\0' ) { + sieve_script_set_critical(script, + "Sieve script file path '%s' is a directory.", path); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + success = FALSE; + } else { + /* Extend storage path with filename */ + if (name == NULL) { + if ( basename == NULL && + (basename=sieve_script_file_get_scriptname(filename)) == NULL ) + basename = filename; + name = basename; + } else if (basename == NULL) { + basename = name; + } + dirpath = path; + + path = sieve_file_storage_path_extend(fstorage, filename); + ret = sieve_file_script_stat(path, &st, &lnk_st); + } + + } else { + /* Storage is a single file */ + path = fstorage->active_path; + + /* Extract filename from path */ + filename = path_split_filename(path, &dirpath); + + if ( (basename=sieve_script_file_get_scriptname(filename)) == NULL ) + basename = filename; + + if ( name == NULL ) + name = basename; + } + + if ( success ) { + if ( ret < 0 ) { + /* Make sure we have a script name for the error */ + if ( name == NULL ) { + i_assert( basename != NULL ); + name = basename; + } + sieve_file_script_handle_error + (fscript, "stat", path, name, error_r); + success = FALSE; + + } else if ( !S_ISREG(st.st_mode) ) { + sieve_script_set_critical(script, + "Sieve script file '%s' is not a regular file.", path); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + success = FALSE; + } + } + + if ( success ) { + const char *bpath, *bfile, *bprefix; + + if ( storage->bin_dir != NULL ) { + bpath = storage->bin_dir; + bfile = sieve_binfile_from_name(name); + bprefix = name; + + } else { + bpath = dirpath; + bfile = sieve_binfile_from_name(basename); + bprefix = basename; + } + + if ( *bpath == '\0' ) { + binpath = bfile; + binprefix = bprefix; + } else if ( bpath[strlen(bpath)-1] == '/' ) { + binpath = t_strconcat(bpath, bfile, NULL); + binprefix = t_strconcat(bpath, bprefix, NULL); + } else { + binpath = t_strconcat(bpath, "/", bfile, NULL); + binprefix = t_strconcat(bpath, "/", bprefix, NULL); + } + + fscript->st = st; + fscript->lnk_st = lnk_st; + fscript->path = p_strdup(pool, path); + fscript->filename = p_strdup(pool, filename); + fscript->dirpath = p_strdup(pool, dirpath); + fscript->binpath = p_strdup(pool, binpath); + fscript->binprefix = p_strdup(pool, binprefix); + + fscript->script.location = fscript->path; + + if ( fscript->script.name == NULL ) + fscript->script.name = p_strdup(pool, basename); + } + } T_END; + + return ( success ? 0 : -1 ); +} + +static int sieve_file_script_get_stream +(struct sieve_script *script, struct istream **stream_r, + enum sieve_error *error_r) +{ + struct sieve_file_script *fscript = (struct sieve_file_script *)script; + struct stat st; + struct istream *result; + int fd; + + if ( (fd=open(fscript->path, O_RDONLY)) < 0 ) { + sieve_file_script_handle_error + (fscript, "open", fscript->path, fscript->script.name, error_r); + return -1; + } + + if ( fstat(fd, &st) != 0 ) { + sieve_script_set_critical(script, + "Failed to open sieve script: fstat(fd=%s) failed: %m", + fscript->path); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + result = NULL; + } else { + /* Re-check the file type just to be sure */ + if ( !S_ISREG(st.st_mode) ) { + sieve_script_set_critical(script, + "Sieve script file `%s' is not a regular file", fscript->path); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + result = NULL; + } else { + result = i_stream_create_fd_autoclose(&fd, SIEVE_FILE_READ_BLOCK_SIZE); + fscript->st = fscript->lnk_st = st; + } + } + + if ( result == NULL ) { + /* Something went wrong, close the fd */ + if ( fd >= 0 && close(fd) != 0 ) { + e_error(script->event, + "Failed to close sieve script: " + "close(fd=%s) failed: %m", fscript->path); + } + return -1; + } + + *stream_r = result; + return 0; +} + +/* + * Binary + */ + +static int sieve_file_script_binary_read_metadata +(struct sieve_script *script, struct sieve_binary_block *sblock, + sieve_size_t *offset ATTR_UNUSED) +{ + struct sieve_file_script *fscript = (struct sieve_file_script *)script; + struct sieve_instance *svinst = script->storage->svinst; + struct sieve_binary *sbin = sieve_binary_block_get_binary(sblock); + const struct stat *sstat, *bstat; + + bstat = sieve_binary_stat(sbin); + if ( fscript->st.st_mtime > fscript->lnk_st.st_mtime || + (fscript->st.st_mtime == fscript->lnk_st.st_mtime && + ST_MTIME_NSEC(fscript->st) >= ST_MTIME_NSEC(fscript->lnk_st)) ) { + sstat = &fscript->st; + } else { + sstat = &fscript->lnk_st; + } + + if ( bstat->st_mtime < sstat->st_mtime || + (bstat->st_mtime == sstat->st_mtime && + ST_MTIME_NSEC(*bstat) <= ST_MTIME_NSEC(*sstat)) ) { + if ( svinst->debug ) { + e_debug(script->event, + "Sieve binary `%s' is not newer " + "than the Sieve script `%s' (%s.%lu <= %s.%lu)", + sieve_binary_path(sbin), sieve_script_location(script), + t_strflocaltime("%Y-%m-%d %H:%M:%S", bstat->st_mtime), + ST_MTIME_NSEC(*bstat), + t_strflocaltime("%Y-%m-%d %H:%M:%S", sstat->st_mtime), + ST_MTIME_NSEC(*sstat)); + } + return 0; + } + + return 1; +} + +static struct sieve_binary *sieve_file_script_binary_load +(struct sieve_script *script, enum sieve_error *error_r) +{ + struct sieve_file_script *fscript = (struct sieve_file_script *)script; + struct sieve_instance *svinst = script->storage->svinst; + + return sieve_binary_open(svinst, fscript->binpath, script, error_r); +} + +static int sieve_file_script_binary_save +(struct sieve_script *script, struct sieve_binary *sbin, bool update, + enum sieve_error *error_r) +{ + struct sieve_storage *storage = script->storage; + struct sieve_file_script *fscript = (struct sieve_file_script *)script; + + if ( storage->bin_dir != NULL && + sieve_storage_setup_bindir(storage, 0700) < 0 ) + return -1; + + return sieve_binary_save(sbin, fscript->binpath, update, + fscript->st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO), error_r); +} + +static const char *sieve_file_script_binary_get_prefix +(struct sieve_script *script) +{ + struct sieve_file_script *fscript = (struct sieve_file_script *)script; + + return fscript->binprefix; +} + +/* + * Management + */ + +static int sieve_file_storage_script_is_active(struct sieve_script *script) +{ + struct sieve_file_script *fscript = + (struct sieve_file_script *) script; + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)script->storage; + const char *afile; + int ret = 0; + + T_BEGIN { + ret = sieve_file_storage_active_script_get_file(fstorage, &afile); + + if ( ret > 0 ) { + /* Is the requested script active? */ + ret = ( strcmp(fscript->filename, afile) == 0 ? 1 : 0 ); + } + } T_END; + + return ret; +} + +static int sieve_file_storage_script_delete(struct sieve_script *script) +{ + struct sieve_file_script *fscript = + (struct sieve_file_script *)script; + int ret = 0; + + if ( sieve_file_storage_pre_modify(script->storage) < 0 ) + return -1; + + ret = unlink(fscript->path); + if ( ret < 0 ) { + if ( errno == ENOENT ) { + sieve_script_set_error(script, + SIEVE_ERROR_NOT_FOUND, + "Sieve script does not exist."); + } else { + sieve_script_set_critical(script, + "Performing unlink() failed on sieve file `%s': %m", + fscript->path); + } + } + return ret; +} + +static int _sieve_file_storage_script_activate +(struct sieve_file_script *fscript) +{ + struct sieve_script *script = &fscript->script; + struct sieve_storage *storage = script->storage; + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)storage; + struct stat st; + const char *link_path, *afile; + int activated = 0; + int ret; + + /* Find out whether there is an active script, but recreate + * the symlink either way. This way, any possible error in the symlink + * resolves automatically. This step is only necessary to provide a + * proper return value indicating whether the script was already active. + */ + ret = sieve_file_storage_active_script_get_file(fstorage, &afile); + + /* Is the requested script already active? */ + if ( ret <= 0 || strcmp(fscript->filename, afile) != 0 ) + activated = 1; + + i_assert( fstorage->link_path != NULL ); + + /* Check the scriptfile we are trying to activate */ + if ( lstat(fscript->path, &st) != 0 ) { + sieve_script_set_critical(script, + "Failed to activate Sieve script: lstat(%s) failed: %m.", + fscript->path); + return -1; + } + + /* Rescue a possible .dovecot.sieve regular file remaining from old + * installations. + */ + if ( !sieve_file_storage_active_rescue_regular(fstorage) ) { + /* Rescue failed, manual intervention is necessary */ + return -1; + } + + /* Just try to create the symlink first */ + link_path = t_strconcat + ( fstorage->link_path, fscript->filename, NULL ); + + ret = symlink(link_path, fstorage->active_path); + if ( ret < 0 ) { + if ( errno == EEXIST ) { + ret = sieve_file_storage_active_replace_link(fstorage, link_path); + if ( ret < 0 ) { + return ret; + } + } else { + /* Other error, critical */ + sieve_script_set_critical(script, + "Failed to activate Sieve script: " + "symlink(%s, %s) failed: %m", + link_path, fstorage->active_path); + return -1; + } + } + return activated; +} + +static int sieve_file_storage_script_activate +(struct sieve_script *script) +{ + struct sieve_file_script *fscript = + (struct sieve_file_script *)script; + int ret; + + if ( sieve_file_storage_pre_modify(script->storage) < 0 ) + return -1; + + T_BEGIN { + ret = _sieve_file_storage_script_activate(fscript); + } T_END; + + return ret; +} + +static int sieve_file_storage_script_rename +(struct sieve_script *script, const char *newname) +{ + struct sieve_file_script *fscript = + (struct sieve_file_script *)script; + struct sieve_storage *storage = script->storage; + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)storage; + const char *newpath, *newfile, *link_path; + int ret = 0; + + if ( sieve_file_storage_pre_modify(storage) < 0 ) + return -1; + + T_BEGIN { + newfile = sieve_script_file_from_name(newname); + newpath = t_strconcat( fstorage->path, "/", newfile, NULL ); + + /* The normal rename() system call overwrites the existing file without + * notice. Also, active scripts must not be disrupted by renaming a script. + * That is why we use a link(newpath) [activate newpath] unlink(oldpath) + */ + + /* Link to the new path */ + ret = link(fscript->path, newpath); + if ( ret >= 0 ) { + /* Is the requested script active? */ + if ( sieve_script_is_active(script) > 0 ) { + /* Active; make active link point to the new copy */ + i_assert( fstorage->link_path != NULL ); + link_path = t_strconcat + ( fstorage->link_path, newfile, NULL ); + + ret = sieve_file_storage_active_replace_link(fstorage, link_path); + } + + if ( ret >= 0 ) { + /* If all is good, remove the old link */ + if ( unlink(fscript->path) < 0 ) { + e_error(script->event, + "Failed to clean up after rename: " + "unlink(%s) failed: %m", fscript->path); + } + + if ( script->name != NULL && *script->name != '\0' ) + script->name = p_strdup(script->pool, newname); + fscript->path = p_strdup(script->pool, newpath); + fscript->filename = p_strdup(script->pool, newfile); + } else { + /* If something went wrong, remove the new link to restore previous + * state + */ + if ( unlink(newpath) < 0 ) { + e_error(script->event, + "Failed to clean up after failed rename: " + "unlink(%s) failed: %m", newpath); + } + } + } else { + /* Our efforts failed right away */ + switch ( errno ) { + case ENOENT: + sieve_script_set_error(script, SIEVE_ERROR_NOT_FOUND, + "Sieve script does not exist."); + break; + case EEXIST: + sieve_script_set_error(script, SIEVE_ERROR_EXISTS, + "A sieve script with that name already exists."); + break; + default: + sieve_script_set_critical(script, + "Failed to rename Sieve script: " + "link(%s, %s) failed: %m", fscript->path, newpath); + } + } + } T_END; + + return ret; +} + +/* + * Properties + */ + +static int sieve_file_script_get_size +(const struct sieve_script *script, uoff_t *size_r) +{ + struct sieve_file_script *fscript = (struct sieve_file_script *)script; + + *size_r = fscript->st.st_size; + return 1; +} + +const char *sieve_file_script_get_dirpath +(const struct sieve_script *script) +{ + struct sieve_file_script *fscript = (struct sieve_file_script *)script; + + if ( script->driver_name != sieve_file_script.driver_name ) + return NULL; + + return fscript->dirpath; +} + +const char *sieve_file_script_get_path +(const struct sieve_script *script) +{ + struct sieve_file_script *fscript = (struct sieve_file_script *)script; + + if ( script->driver_name != sieve_file_script.driver_name ) + return NULL; + + return fscript->path; +} + +/* + * Matching + */ + +static bool sieve_file_script_equals +(const struct sieve_script *script, const struct sieve_script *other) +{ + struct sieve_file_script *fscript = + (struct sieve_file_script *)script; + struct sieve_file_script *fother = + (struct sieve_file_script *)other; + + return ( CMP_DEV_T(fscript->st.st_dev, fother->st.st_dev) && + fscript->st.st_ino == fother->st.st_ino ); +} + +/* + * Driver definition + */ + +const struct sieve_script sieve_file_script = { + .driver_name = SIEVE_FILE_STORAGE_DRIVER_NAME, + .v = { + .open = sieve_file_script_open, + + .get_stream = sieve_file_script_get_stream, + + .binary_read_metadata = sieve_file_script_binary_read_metadata, + .binary_load = sieve_file_script_binary_load, + .binary_save = sieve_file_script_binary_save, + .binary_get_prefix = sieve_file_script_binary_get_prefix, + + .rename = sieve_file_storage_script_rename, + .delete = sieve_file_storage_script_delete, + .is_active = sieve_file_storage_script_is_active, + .activate = sieve_file_storage_script_activate, + + .get_size = sieve_file_script_get_size, + + .equals = sieve_file_script_equals + } +}; + diff --git a/pigeonhole/src/lib-sieve/storage/file/sieve-file-storage-active.c b/pigeonhole/src/lib-sieve/storage/file/sieve-file-storage-active.c new file mode 100644 index 0000000..28bc9eb --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/file/sieve-file-storage-active.c @@ -0,0 +1,403 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "path-util.h" +#include "ioloop.h" +#include "hostpid.h" +#include "file-copy.h" +#include "time-util.h" + +#include "sieve-file-storage.h" + +#include <unistd.h> + +/* + * Symlink manipulation + */ + +static int sieve_file_storage_active_read_link +(struct sieve_file_storage *fstorage, const char **link_r) +{ + struct sieve_storage *storage = &fstorage->storage; + const char *error = NULL; + int ret; + + ret = t_readlink(fstorage->active_path, link_r, &error); + + if ( ret < 0 ) { + *link_r = NULL; + + if ( errno == EINVAL ) { + /* Our symlink is no symlink. Report 'no active script'. + * Activating a script will automatically resolve this, so + * there is no need to panic on this one. + */ + if ( (storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0 && + (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0 ) { + e_warning(storage->event, + "Active sieve script symlink %s is no symlink.", + fstorage->active_path); + } + return 0; + } + + if ( errno == ENOENT ) { + /* Symlink not found */ + return 0; + } + + /* We do need to panic otherwise */ + sieve_storage_set_critical(storage, + "Performing t_readlink() on active sieve symlink '%s' failed: %s", + fstorage->active_path, error); + return -1; + } + + /* ret is now assured to be valid, i.e. > 0 */ + return 1; +} + +static const char *sieve_file_storage_active_parse_link +(struct sieve_file_storage *fstorage, const char *link, + const char **scriptname_r) +{ + struct sieve_storage *storage = &fstorage->storage; + const char *fname, *scriptname, *scriptpath, *link_dir; + + /* Split off directory from link path */ + fname = strrchr(fstorage->active_path, '/'); + if (fname == NULL) + link_dir = ""; + else + link_dir = t_strdup_until(fstorage->active_path, fname+1); + + /* Split link into path and filename */ + fname = strrchr(link, '/'); + if ( fname != NULL ) { + scriptpath = t_strdup_until(link, fname+1); + fname++; + } else { + scriptpath = ""; + fname = link; + } + + /* Check the script name */ + scriptname = sieve_script_file_get_scriptname(fname); + + /* Warn if link is deemed to be invalid */ + if ( scriptname == NULL ) { + e_warning(storage->event, + "Active Sieve script symlink %s is broken: " + "Invalid scriptname (points to %s).", + fstorage->active_path, link); + return NULL; + } + + /* Check whether the path is any good */ + const char *error = NULL; + if ( t_normpath_to(scriptpath, link_dir, &scriptpath, &error) < 0 ) { + e_warning(storage->event, + "Failed to check active Sieve script symlink %s: " + "Failed to normalize path (points to %s): %s", + fstorage->active_path, scriptpath, error); + return NULL; + } + if ( strcmp(scriptpath, fstorage->path) != 0 ) { + e_warning(storage->event, + "Active sieve script symlink %s is broken: " + "Invalid/unknown path to storage (points to %s).", + fstorage->active_path, scriptpath); + return NULL; + } + + if ( scriptname_r != NULL ) + *scriptname_r = scriptname; + + return fname; +} + +int sieve_file_storage_active_replace_link +(struct sieve_file_storage *fstorage, const char *link_path) +{ + struct sieve_storage *storage = &fstorage->storage; + const char *active_path_new; + struct timeval *tv, tv_now; + int ret = 0; + + tv = &ioloop_timeval; + + for (;;) { + /* First the new symlink is created with a different filename */ + active_path_new = t_strdup_printf + ("%s-new.%s.P%sM%s.%s", + fstorage->active_path, + dec2str(tv->tv_sec), my_pid, + dec2str(tv->tv_usec), my_hostname); + + ret = symlink(link_path, active_path_new); + + if ( ret < 0 ) { + /* If link exists we try again later */ + if ( errno == EEXIST ) { + /* Wait and try again - very unlikely */ + sleep(2); + tv = &tv_now; + i_gettimeofday(&tv_now); + continue; + } + + /* Other error, critical */ + sieve_storage_set_critical(storage, + "Creating symlink() %s to %s failed: %m", + active_path_new, link_path); + return -1; + } + + /* Link created */ + break; + } + + /* Replace the existing link. This activates the new script */ + ret = rename(active_path_new, fstorage->active_path); + + if ( ret < 0 ) { + /* Failed; created symlink must be deleted */ + i_unlink(active_path_new); + sieve_storage_set_critical(storage, + "Performing rename() %s to %s failed: %m", + active_path_new, fstorage->active_path); + return -1; + } + + return 1; +} + +/* + * Active script properties + */ + +int sieve_file_storage_active_script_get_file +(struct sieve_file_storage *fstorage, const char **file_r) +{ + const char *link, *scriptfile; + int ret; + + *file_r = NULL; + + /* Read the active link */ + if ( (ret=sieve_file_storage_active_read_link(fstorage, &link)) <= 0 ) + return ret; + + /* Parse the link */ + scriptfile = sieve_file_storage_active_parse_link(fstorage, link, NULL); + + if (scriptfile == NULL) { + /* Obviously, someone has been playing with our symlink: + * ignore this situation and report 'no active script'. + * Activation should fix this situation. + */ + return 0; + } + + *file_r = scriptfile; + return 1; +} + +int sieve_file_storage_active_script_get_name +(struct sieve_storage *storage, const char **name_r) +{ + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)storage; + const char *link; + int ret; + + *name_r = NULL; + + /* Read the active link */ + if ( (ret=sieve_file_storage_active_read_link + (fstorage, &link)) <= 0 ) + return ret; + + if ( sieve_file_storage_active_parse_link + (fstorage, link, name_r) == NULL ) { + /* Obviously, someone has been playing with our symlink: + * ignore this situation and report 'no active script'. + * Activation should fix this situation. + */ + return 0; + } + + return 1; +} + +/* + * Active script + */ + +struct sieve_script *sieve_file_storage_active_script_open +(struct sieve_storage *storage) +{ + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)storage; + struct sieve_file_script *fscript; + const char *scriptfile, *link; + int ret; + + sieve_storage_clear_error(storage); + + /* Read the active link */ + if ( (ret=sieve_file_storage_active_read_link(fstorage, &link)) <= 0 ) { + if ( ret < 0 ) + return NULL; + + /* Try to open the active_path as a regular file */ + if ( S_ISDIR(fstorage->st.st_mode) ) { + fscript = sieve_file_script_open_from_path(fstorage, + fstorage->active_path, NULL, NULL); + } else { + fscript = sieve_file_script_open_from_name(fstorage, NULL); + } + if ( fscript == NULL ) { + if ( storage->error_code != SIEVE_ERROR_NOT_FOUND ) { + sieve_storage_set_critical(storage, + "Failed to open active path `%s' as regular file: %s", + fstorage->active_path, storage->error); + } + return NULL; + } + + return &fscript->script; + } + + /* Parse the link */ + scriptfile = sieve_file_storage_active_parse_link(fstorage, link, NULL); + if (scriptfile == NULL) { + /* Obviously someone has been playing with our symlink, + * ignore this situation and report 'no active script'. + * Activation should fix this situation. + */ + sieve_storage_set_error(storage, SIEVE_ERROR_NOT_FOUND, + "Active script is invalid"); + return NULL; + } + + fscript = sieve_file_script_open_from_path(fstorage, + fstorage->active_path, + sieve_script_file_get_scriptname(scriptfile), + NULL); + if ( fscript == NULL && storage->error_code == SIEVE_ERROR_NOT_FOUND ) { + e_warning(storage->event, + "Active sieve script symlink %s points to non-existent script " + "(points to %s).", fstorage->active_path, link); + } + return (fscript != NULL ? &fscript->script : NULL); +} + +int sieve_file_storage_active_script_get_last_change +(struct sieve_storage *storage, time_t *last_change_r) +{ + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)storage; + struct stat st; + + /* Try direct lstat first */ + if ( lstat(fstorage->active_path, &st) == 0 ) { + if ( !S_ISLNK(st.st_mode) ) { + *last_change_r = st.st_mtime; + return 0; + } + } + /* Check error */ + else if ( errno != ENOENT ) { + sieve_storage_set_critical(storage, + "lstat(%s) failed: %m", fstorage->active_path); + } + + /* Fall back to statting storage directory */ + return sieve_storage_get_last_change(storage, last_change_r); +} + +bool sieve_file_storage_active_rescue_regular +(struct sieve_file_storage *fstorage) +{ + struct sieve_storage *storage = &fstorage->storage; + struct stat st; + + /* Stat the file */ + if ( lstat(fstorage->active_path, &st) != 0 ) { + if ( errno != ENOENT ) { + sieve_storage_set_critical(storage, + "Failed to stat active sieve script symlink (%s): %m.", + fstorage->active_path); + return FALSE; + } + return TRUE; + } + + if ( S_ISLNK( st.st_mode ) ) { + e_debug(storage->event, + "Nothing to rescue %s.", fstorage->active_path); + return TRUE; /* Nothing to rescue */ + } + + /* Only regular files can be rescued */ + if ( S_ISREG( st.st_mode ) ) { + const char *dstpath; + bool result = TRUE; + + T_BEGIN { + + dstpath = t_strconcat( fstorage->path, "/", + sieve_script_file_from_name("dovecot.orig"), NULL ); + if ( file_copy(fstorage->active_path, dstpath, TRUE) < 1 ) { + sieve_storage_set_critical(storage, + "Active sieve script file '%s' is a regular file " + "and copying it to the script storage as '%s' failed. " + "This needs to be fixed manually.", + fstorage->active_path, dstpath); + result = FALSE; + } else { + e_info(storage->event, + "Moved active sieve script file '%s' " + "to script storage as '%s'.", + fstorage->active_path, dstpath); + } + } T_END; + + return result; + } + + sieve_storage_set_critical(storage, + "Active sieve script file '%s' is no symlink nor a regular file. " + "This needs to be fixed manually.", fstorage->active_path); + return FALSE; +} + +int sieve_file_storage_deactivate(struct sieve_storage *storage) +{ + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)storage; + int ret; + + if ( sieve_file_storage_pre_modify(storage) < 0 ) + return -1; + + if ( !sieve_file_storage_active_rescue_regular(fstorage) ) + return -1; + + /* Delete the symlink, so no script is active */ + ret = unlink(fstorage->active_path); + + if ( ret < 0 ) { + if ( errno != ENOENT ) { + sieve_storage_set_critical(storage, + "Failed to deactivate Sieve: " + "unlink(%s) failed: %m", fstorage->active_path); + return -1; + } else { + return 0; + } + } + return 1; +} diff --git a/pigeonhole/src/lib-sieve/storage/file/sieve-file-storage-list.c b/pigeonhole/src/lib-sieve/storage/file/sieve-file-storage-list.c new file mode 100644 index 0000000..75a34c9 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/file/sieve-file-storage-list.c @@ -0,0 +1,140 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "eacces-error.h" + +#include "sieve-common.h" +#include "sieve-script-private.h" + +#include "sieve-file-storage.h" + +#include <stdio.h> +#include <dirent.h> + +struct sieve_file_list_context { + struct sieve_storage_list_context context; + pool_t pool; + + const char *active; + const char *dir; + DIR *dirp; +}; + +struct sieve_storage_list_context *sieve_file_storage_list_init +(struct sieve_storage *storage) +{ + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)storage; + struct sieve_file_list_context *flctx; + const char *active = NULL; + pool_t pool; + DIR *dirp; + + /* Open the directory */ + if ( (dirp = opendir(fstorage->path)) == NULL ) { + switch ( errno ) { + case ENOENT: + sieve_storage_set_error(storage, + SIEVE_ERROR_NOT_FOUND, + "Script storage not found"); + break; + case EACCES: + sieve_storage_set_error(storage, + SIEVE_ERROR_NO_PERMISSION, + "Script storage not accessible"); + e_error(storage->event, "Failed to list scripts: %s", + eacces_error_get("opendir", fstorage->path)); + break; + default: + sieve_storage_set_critical(storage, + "Failed to list scripts: " + "opendir(%s) failed: %m", fstorage->path); + break; + } + return NULL; + } + + T_BEGIN { + /* Get the name of the active script */ + if ( sieve_file_storage_active_script_get_file(fstorage, &active) < 0) { + flctx = NULL; + } else { + pool = pool_alloconly_create("sieve_file_list_context", 1024); + flctx = p_new(pool, struct sieve_file_list_context, 1); + flctx->pool = pool; + flctx->dirp = dirp; + flctx->active = ( active != NULL ? p_strdup(pool, active) : NULL ); + } + } T_END; + + if ( flctx == NULL ) { + if ( closedir(dirp) < 0) { + e_error(storage->event, + "closedir(%s) failed: %m", fstorage->path); + } + return NULL; + } + return &flctx->context; +} + +const char *sieve_file_storage_list_next +(struct sieve_storage_list_context *ctx, bool *active) +{ + struct sieve_file_list_context *flctx = + (struct sieve_file_list_context *)ctx; + const struct sieve_file_storage *fstorage = + (const struct sieve_file_storage *)ctx->storage; + struct dirent *dp; + const char *scriptname; + + *active = FALSE; + + for (;;) { + if ( (dp = readdir(flctx->dirp)) == NULL ) + return NULL; + + scriptname = sieve_script_file_get_scriptname(dp->d_name); + if (scriptname != NULL ) { + /* Don't list our active sieve script link if the link + * resides in the script dir (generally a bad idea). + */ + i_assert( fstorage->link_path != NULL ); + if ( *(fstorage->link_path) == '\0' && + strcmp(fstorage->active_fname, dp->d_name) == 0 ) + continue; + + break; + } + } + + if ( flctx->active != NULL && strcmp(dp->d_name, flctx->active) == 0 ) { + *active = TRUE; + flctx->active = NULL; + } + + return scriptname; +} + +int sieve_file_storage_list_deinit(struct sieve_storage_list_context *lctx) +{ + struct sieve_file_list_context *flctx = + (struct sieve_file_list_context *)lctx; + const struct sieve_file_storage *fstorage = + (const struct sieve_file_storage *)lctx->storage; + + if (closedir(flctx->dirp) < 0) { + e_error(lctx->storage->event, + "closedir(%s) failed: %m", fstorage->path); + } + + pool_unref(&flctx->pool); + + // FIXME: return error here if something went wrong during listing + return 0; +} + + + + diff --git a/pigeonhole/src/lib-sieve/storage/file/sieve-file-storage-quota.c b/pigeonhole/src/lib-sieve/storage/file/sieve-file-storage-quota.c new file mode 100644 index 0000000..65e075d --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/file/sieve-file-storage-quota.c @@ -0,0 +1,120 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" + +#include "sieve.h" +#include "sieve-script.h" + +#include "sieve-file-storage.h" + +#include <stdio.h> +#include <dirent.h> +#include <unistd.h> +#include <fcntl.h> + +int sieve_file_storage_quota_havespace +(struct sieve_storage *storage, const char *scriptname, size_t size, + enum sieve_storage_quota *quota_r, uint64_t *limit_r) +{ + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)storage; + struct dirent *dp; + DIR *dirp; + uint64_t script_count = 1; + uint64_t script_storage = size; + int result = 1; + + /* Open the directory */ + if ( (dirp = opendir(fstorage->path)) == NULL ) { + sieve_storage_set_critical(storage, + "quota: opendir(%s) failed: %m", fstorage->path); + return -1; + } + + /* Scan all files */ + for (;;) { + const char *name; + bool replaced = FALSE; + + /* Read next entry */ + errno = 0; + if ( (dp = readdir(dirp)) == NULL ) { + if ( errno != 0 ) { + sieve_storage_set_critical(storage, + "quota: readdir(%s) failed: %m", fstorage->path); + result = -1; + } + break; + } + + /* Parse filename */ + name = sieve_script_file_get_scriptname(dp->d_name); + + /* Ignore non-script files */ + if ( name == NULL ) + continue; + + /* Don't list our active sieve script link if the link + * resides in the script dir (generally a bad idea). + */ + i_assert( fstorage->link_path != NULL ); + if ( *(fstorage->link_path) == '\0' && + strcmp(fstorage->active_fname, dp->d_name) == 0 ) + continue; + + if ( strcmp(name, scriptname) == 0 ) + replaced = TRUE; + + /* Check count quota if necessary */ + if ( storage->max_scripts > 0 ) { + if ( !replaced ) { + script_count++; + + if ( script_count > storage->max_scripts ) { + *quota_r = SIEVE_STORAGE_QUOTA_MAXSCRIPTS; + *limit_r = storage->max_scripts; + result = 0; + break; + } + } + } + + /* Check storage quota if necessary */ + if ( storage->max_storage > 0 ) { + const char *path; + struct stat st; + + path = t_strconcat(fstorage->path, "/", dp->d_name, NULL); + + if ( stat(path, &st) < 0 ) { + e_warning(storage->event, + "quota: stat(%s) failed: %m", path); + continue; + } + + if ( !replaced ) { + script_storage += st.st_size; + + if ( script_storage > storage->max_storage ) { + *quota_r = SIEVE_STORAGE_QUOTA_MAXSTORAGE; + *limit_r = storage->max_storage; + result = 0; + break; + } + } + } + } + + /* Close directory */ + if ( closedir(dirp) < 0 ) { + sieve_storage_set_critical(storage, + "quota: closedir(%s) failed: %m", fstorage->path); + } + return result; +} + + + + diff --git a/pigeonhole/src/lib-sieve/storage/file/sieve-file-storage-save.c b/pigeonhole/src/lib-sieve/storage/file/sieve-file-storage-save.c new file mode 100644 index 0000000..bfbe380 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/file/sieve-file-storage-save.c @@ -0,0 +1,544 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "hostpid.h" +#include "ioloop.h" +#include "array.h" +#include "buffer.h" +#include "istream.h" +#include "ostream.h" +#include "str.h" +#include "eacces-error.h" +#include "safe-mkstemp.h" + +#include "sieve-file-storage.h" + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <utime.h> + +struct sieve_file_save_context { + struct sieve_storage_save_context context; + + pool_t pool; + + struct ostream *output; + int fd; + const char *tmp_path; + + time_t mtime; + + bool failed:1; + bool finished:1; +}; + +static const char *sieve_generate_tmp_filename(const char *scriptname) +{ + static struct timeval last_tv = { 0, 0 }; + struct timeval tv; + + /* use secs + usecs to guarantee uniqueness within this process. */ + if (ioloop_timeval.tv_sec > last_tv.tv_sec || + (ioloop_timeval.tv_sec == last_tv.tv_sec && + ioloop_timeval.tv_usec > last_tv.tv_usec)) { + tv = ioloop_timeval; + } else { + tv = last_tv; + if (++tv.tv_usec == 1000000) { + tv.tv_sec++; + tv.tv_usec = 0; + } + } + last_tv = tv; + + if ( scriptname == NULL ) { + return t_strdup_printf("%s.M%sP%s.%s.tmp", + dec2str(tv.tv_sec), dec2str(tv.tv_usec), + my_pid, my_hostname); + } + + scriptname = t_strdup_printf("%s_%s.M%sP%s.%s", + scriptname, dec2str(tv.tv_sec), dec2str(tv.tv_usec), + my_pid, my_hostname); + return sieve_script_file_from_name(scriptname); +} + +static int sieve_file_storage_create_tmp +(struct sieve_file_storage *fstorage, const char *scriptname, + const char **fpath_r) +{ + struct sieve_storage *storage = &fstorage->storage; + struct stat st; + unsigned int prefix_len; + const char *tmp_fname = NULL; + string_t *path; + int fd; + + path = t_str_new(256); + str_append(path, fstorage->path); + str_append(path, "/tmp/"); + prefix_len = str_len(path); + + for (;;) { + tmp_fname = sieve_generate_tmp_filename(scriptname); + str_truncate(path, prefix_len); + str_append(path, tmp_fname); + + /* stat() first to see if it exists. pretty much the only + possibility of that happening is if time had moved + backwards, but even then it's highly unlikely. */ + if (stat(str_c(path), &st) == 0) { + /* try another file name */ + } else if (errno != ENOENT) { + switch ( errno ) { + case EACCES: + sieve_storage_set_critical(storage, "save: %s", + eacces_error_get("stat", fstorage->path)); + break; + default: + sieve_storage_set_critical(storage, "save: " + "stat(%s) failed: %m", str_c(path)); + break; + } + return -1; + } else { + /* doesn't exist */ + mode_t old_mask = umask(0777 & ~(fstorage->file_create_mode)); + fd = open(str_c(path), + O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0777); + umask(old_mask); + + if (fd != -1 || errno != EEXIST) + break; + /* race condition between stat() and open(). + highly unlikely. */ + } + } + + *fpath_r = str_c(path); + if (fd == -1) { + if (ENOQUOTA(errno)) { + sieve_storage_set_error(storage, + SIEVE_ERROR_NO_QUOTA, + "Not enough disk quota"); + } else { + switch ( errno ) { + case EACCES: + sieve_storage_set_critical(storage, "save: %s", + eacces_error_get("open", fstorage->path)); + break; + default: + sieve_storage_set_critical(storage, "save: " + "open(%s) failed: %m", str_c(path)); + break; + } + } + } + + return fd; +} + +static int sieve_file_storage_script_move +(struct sieve_file_save_context *fsctx, const char *dst) +{ + struct sieve_storage_save_context *sctx = &fsctx->context; + struct sieve_storage *storage = sctx->storage; + int result = 0; + + T_BEGIN { + + /* Using rename() to ensure existing files are replaced + * without conflicts with other processes using the same + * file. The kernel wont fully delete the original until + * all processes have closed the file. + */ + if (rename(fsctx->tmp_path, dst) == 0) + result = 0; + else { + result = -1; + if ( ENOQUOTA(errno) ) { + sieve_storage_set_error(storage, + SIEVE_ERROR_NO_QUOTA, + "Not enough disk quota"); + } else if ( errno == EACCES ) { + sieve_storage_set_critical(storage, "save: " + "Failed to save Sieve script: " + "%s", eacces_error_get("rename", dst)); + } else { + sieve_storage_set_critical(storage, "save: " + "rename(%s, %s) failed: %m", fsctx->tmp_path, dst); + } + } + + /* Always destroy temp file */ + if (unlink(fsctx->tmp_path) < 0 && errno != ENOENT) { + e_warning(storage->event, "save: " + "unlink(%s) failed: %m", fsctx->tmp_path); + } + } T_END; + + return result; +} + +struct sieve_storage_save_context * +sieve_file_storage_save_alloc(struct sieve_storage *storage) +{ + struct sieve_file_save_context *fsctx; + pool_t pool; + + pool = pool_alloconly_create("sieve_file_save_context", 1024); + fsctx = p_new(pool, struct sieve_file_save_context, 1); + fsctx->context.pool = pool; + fsctx->context.storage = storage; + + return &fsctx->context; +} + +int sieve_file_storage_save_init(struct sieve_storage_save_context *sctx, + const char *scriptname, struct istream *input) +{ + struct sieve_storage *storage = sctx->storage; + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)storage; + struct sieve_file_save_context *fsctx = + (struct sieve_file_save_context *)sctx; + pool_t pool = sctx->pool; + const char *path; + int fd, ret = 0; + + if ( sieve_file_storage_pre_modify(storage) < 0 ) + return -1; + + if ( scriptname != NULL ) { + /* Prevent overwriting the active script link when it resides in the + * sieve storage directory. + */ + i_assert( fstorage->link_path != NULL ); + if ( *(fstorage->link_path) == '\0' ) { + const char *svext; + size_t namelen; + + svext = strrchr(fstorage->active_fname, '.'); + namelen = svext - fstorage->active_fname; + if ( svext != NULL && str_begins(svext+1, "sieve") && + strlen(scriptname) == namelen && + str_begins(fstorage->active_fname, scriptname) ) + { + sieve_storage_set_error(storage, + SIEVE_ERROR_BAD_PARAMS, + "Script name `%s' is reserved for internal use.", + scriptname); + return -1; + } + } + } + + T_BEGIN { + fd = sieve_file_storage_create_tmp(fstorage, scriptname, &path); + if (fd == -1) { + ret = -1; + } else { + fsctx->context.scriptname = p_strdup(pool, scriptname); + fsctx->context.input = input; + fsctx->fd = fd; + fsctx->output = o_stream_create_fd(fsctx->fd, 0); + fsctx->tmp_path = p_strdup(pool, path); + } + } T_END; + + return ret; +} + +int sieve_file_storage_save_continue +(struct sieve_storage_save_context *sctx) +{ + struct sieve_file_save_context *fsctx = + (struct sieve_file_save_context *)sctx; + + switch (o_stream_send_istream(fsctx->output, sctx->input)) { + case OSTREAM_SEND_ISTREAM_RESULT_FINISHED: + case OSTREAM_SEND_ISTREAM_RESULT_WAIT_INPUT: + return 0; + case OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT: + i_unreached(); + case OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT: + sieve_storage_set_critical(sctx->storage, + "save: read(%s) failed: %s", + i_stream_get_name(sctx->input), + i_stream_get_error(sctx->input)); + return -1; + case OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT: + sieve_storage_set_critical(sctx->storage, + "save: write(%s) failed: %s", fsctx->tmp_path, + o_stream_get_error(fsctx->output)); + return -1; + } + return 0; +} + +int sieve_file_storage_save_finish +(struct sieve_storage_save_context *sctx) +{ + struct sieve_file_save_context *fsctx = + (struct sieve_file_save_context *)sctx; + struct sieve_storage *storage = sctx->storage; + int output_errno; + + if ( sctx->failed && fsctx->fd == -1 ) { + /* tmp file creation failed */ + return -1; + } + + T_BEGIN { + output_errno = fsctx->output->stream_errno; + o_stream_destroy(&fsctx->output); + + if ( fsync(fsctx->fd) < 0 ) { + sieve_storage_set_critical(storage, "save: " + "fsync(%s) failed: %m", fsctx->tmp_path); + sctx->failed = TRUE; + } + if ( close(fsctx->fd) < 0 ) { + sieve_storage_set_critical(storage, "save: " + "close(%s) failed: %m", fsctx->tmp_path); + sctx->failed = TRUE; + } + fsctx->fd = -1; + + if ( sctx->failed ) { + /* delete the tmp file */ + if (unlink(fsctx->tmp_path) < 0 && errno != ENOENT) { + e_warning(storage->event, "save: " + "unlink(%s) failed: %m", + fsctx->tmp_path); + } + + errno = output_errno; + if ( ENOQUOTA(errno) ) { + sieve_storage_set_error(storage, + SIEVE_ERROR_NO_QUOTA, + "Not enough disk quota"); + } else if ( errno != 0 ) { + sieve_storage_set_critical(storage, "save: " + "write(%s) failed: %m", fsctx->tmp_path); + } + fsctx->tmp_path = NULL; + } + } T_END; + + return ( sctx->failed ? -1 : 0 ); +} + +struct sieve_script *sieve_file_storage_save_get_tempscript +(struct sieve_storage_save_context *sctx) +{ + struct sieve_file_save_context *fsctx = + (struct sieve_file_save_context *)sctx; + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)sctx->storage; + struct sieve_file_script *tmpscript; + enum sieve_error error; + const char *scriptname; + + if (sctx->failed) + return NULL; + + if ( sctx->scriptobject != NULL ) + return sctx->scriptobject; + + scriptname = + ( sctx->scriptname == NULL ? "" : sctx->scriptname ); + tmpscript = sieve_file_script_open_from_path + (fstorage, fsctx->tmp_path, scriptname, &error); + + if ( tmpscript == NULL ) { + if ( error == SIEVE_ERROR_NOT_FOUND ) { + sieve_storage_set_critical(sctx->storage, "save: " + "Temporary script file `%s' got lost, " + "which should not happen (possibly deleted externally).", + fsctx->tmp_path); + } else { + sieve_storage_set_critical(sctx->storage, "save: " + "Failed to open temporary script file `%s'", + fsctx->tmp_path); + } + return NULL; + } + + return &tmpscript->script; +} + +static void sieve_file_storage_update_mtime +(struct sieve_storage *storage, const char *path, time_t mtime) +{ + struct utimbuf times = { .actime = mtime, .modtime = mtime }; + + if ( utime(path, ×) < 0 ) { + switch ( errno ) { + case ENOENT: + break; + case EACCES: + e_error(storage->event, "save: %s", + eacces_error_get("utime", path)); + break; + default: + e_error(storage->event, + "save: utime(%s) failed: %m", path); + } + } +} + +int sieve_file_storage_save_commit +(struct sieve_storage_save_context *sctx) +{ + struct sieve_file_save_context *fsctx = + (struct sieve_file_save_context *)sctx; + struct sieve_storage *storage = sctx->storage; + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)sctx->storage; + const char *dest_path; + bool failed = FALSE; + + i_assert(fsctx->output == NULL); + + T_BEGIN { + dest_path = t_strconcat(fstorage->path, "/", + sieve_script_file_from_name(sctx->scriptname), NULL); + + failed = ( sieve_file_storage_script_move(fsctx, dest_path) < 0 ); + if ( sctx->mtime != (time_t)-1 ) + sieve_file_storage_update_mtime(storage, dest_path, sctx->mtime); + } T_END; + + return ( failed ? -1 : 0 ); +} + +void sieve_file_storage_save_cancel(struct sieve_storage_save_context *sctx) +{ + struct sieve_file_save_context *fsctx = + (struct sieve_file_save_context *)sctx; + struct sieve_storage *storage = sctx->storage; + + if (fsctx->tmp_path != NULL && + unlink(fsctx->tmp_path) < 0 && errno != ENOENT) { + e_warning(storage->event, "save: unlink(%s) failed: %m", + fsctx->tmp_path); + } + + i_assert(fsctx->output == NULL); +} + +static int +sieve_file_storage_save_to(struct sieve_file_storage *fstorage, + string_t *temp_path, struct istream *input, + const char *target) +{ + struct sieve_storage *storage = &fstorage->storage; + struct ostream *output; + int fd; + + // FIXME: move this to base class + // FIXME: use io_stream_temp + + fd = safe_mkstemp_hostpid + (temp_path, fstorage->file_create_mode, (uid_t)-1, (gid_t)-1); + if ( fd < 0 ) { + if ( errno == EACCES ) { + sieve_storage_set_critical(storage, + "Failed to create temporary file: %s", + eacces_error_get_creating("open", str_c(temp_path))); + } else { + sieve_storage_set_critical(storage, + "Failed to create temporary file: open(%s) failed: %m", + str_c(temp_path)); + } + return -1; + } + + output = o_stream_create_fd(fd, 0); + switch ( o_stream_send_istream(output, input) ) { + case OSTREAM_SEND_ISTREAM_RESULT_FINISHED: + break; + case OSTREAM_SEND_ISTREAM_RESULT_WAIT_INPUT: + case OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT: + i_unreached(); + case OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT: + sieve_storage_set_critical(storage, + "read(%s) failed: %s", i_stream_get_name(input), + i_stream_get_error(input)); + o_stream_destroy(&output); + i_unlink(str_c(temp_path)); + return -1; + case OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT: + sieve_storage_set_critical(storage, + "write(%s) failed: %s", str_c(temp_path), + o_stream_get_error(output)); + o_stream_destroy(&output); + i_unlink(str_c(temp_path)); + return -1; + } + o_stream_destroy(&output); + + if ( rename(str_c(temp_path), target) < 0 ) { + if ( ENOQUOTA(errno) ) { + sieve_storage_set_error(storage, + SIEVE_ERROR_NO_QUOTA, + "Not enough disk quota"); + } else if ( errno == EACCES ) { + sieve_storage_set_critical(storage, + "%s", eacces_error_get("rename", target)); + } else { + sieve_storage_set_critical(storage, + "rename(%s, %s) failed: %m", + str_c(temp_path), target); + } + i_unlink(str_c(temp_path)); + } + return 0; +} + +int sieve_file_storage_save_as +(struct sieve_storage *storage, struct istream *input, + const char *name) +{ + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)storage; + string_t *temp_path; + const char *dest_path; + + temp_path = t_str_new(256); + str_append(temp_path, fstorage->path); + str_append(temp_path, "/tmp/"); + str_append(temp_path, sieve_script_file_from_name(name)); + str_append_c(temp_path, '.'); + + dest_path = t_strconcat(fstorage->path, "/", + sieve_script_file_from_name(name), NULL); + + return sieve_file_storage_save_to + (fstorage, temp_path, input, dest_path); +} + +int sieve_file_storage_save_as_active +(struct sieve_storage *storage, struct istream *input, + time_t mtime) +{ + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)storage; + string_t *temp_path; + + temp_path = t_str_new(256); + str_append(temp_path, fstorage->active_path); + str_append_c(temp_path, '.'); + + if ( sieve_file_storage_save_to + (fstorage, temp_path, input, fstorage->active_path) < 0 ) + return -1; + + sieve_file_storage_update_mtime + (storage, fstorage->active_path, mtime); + return 0; +} + diff --git a/pigeonhole/src/lib-sieve/storage/file/sieve-file-storage.c b/pigeonhole/src/lib-sieve/storage/file/sieve-file-storage.c new file mode 100644 index 0000000..76b3ebf --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/file/sieve-file-storage.c @@ -0,0 +1,918 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "path-util.h" +#include "home-expand.h" +#include "ioloop.h" +#include "mkdir-parents.h" +#include "eacces-error.h" +#include "unlink-old-files.h" +#include "mail-storage-private.h" + +#include "sieve.h" +#include "sieve-common.h" +#include "sieve-settings.h" +#include "sieve-error-private.h" +#include "sieve-settings.h" + +#include "sieve-file-storage.h" + +#include <stdio.h> +#include <unistd.h> +#include <ctype.h> +#include <utime.h> +#include <sys/time.h> + + +#define MAX_DIR_CREATE_MODE 0770 + +/* + * Utility + */ + +const char *sieve_file_storage_path_extend +(struct sieve_file_storage *fstorage, const char *filename) +{ + const char *path = fstorage->path; + + if ( path[strlen(path)-1] == '/' ) + return t_strconcat(path, filename, NULL); + + return t_strconcat(path, "/", filename , NULL); +} + +/* + * + */ + +static int sieve_file_storage_stat +(struct sieve_file_storage *fstorage, const char *path, + enum sieve_error *error_r) +{ + struct sieve_storage *storage = &fstorage->storage; + struct stat st; + const char *abspath, *error; + + if ( lstat(path, &st) == 0 ) { + fstorage->lnk_st = st; + + if ( !S_ISLNK(st.st_mode) || stat(path, &st) == 0 ) { + fstorage->st = st; + return 0; + } + } + + switch ( errno ) { + case ENOENT: + if (t_abspath(path, &abspath, &error) < 0) { + sieve_storage_set_critical(storage, + "t_abspath(%s) failed: %s", path, error); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + break; + } + e_debug(storage->event, "Storage path `%s' not found", abspath); + sieve_storage_set_internal_error(storage); // should be overriden + *error_r = SIEVE_ERROR_NOT_FOUND; + break; + case EACCES: + sieve_storage_set_critical(storage, + "Failed to stat sieve storage path: %s", + eacces_error_get("stat", path)); + *error_r = SIEVE_ERROR_NO_PERMISSION; + break; + default: + sieve_storage_set_critical(storage, + "Failed to stat sieve storage path: " + "stat(%s) failed: %m", path); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + break; + } + + return -1; +} + +static const char *sieve_storage_get_relative_link_path + (const char *active_path, const char *storage_dir) +{ + const char *link_path, *p; + size_t pathlen; + + /* Determine to what extent the sieve storage and active script + * paths match up. This enables the managed symlink to be short and the + * sieve storages can be moved around without trouble (if the active + * script path is common to the script storage). + */ + p = strrchr(active_path, '/'); + if ( p == NULL ) { + link_path = storage_dir; + } else { + pathlen = p - active_path; + + if ( strncmp( storage_dir, active_path, pathlen ) == 0 && + (storage_dir[pathlen] == '/' || storage_dir[pathlen] == '\0') ) + { + if ( storage_dir[pathlen] == '\0' ) + link_path = ""; + else + link_path = storage_dir + pathlen + 1; + } else + link_path = storage_dir; + } + + /* Add trailing '/' when link path is not empty + */ + pathlen = strlen(link_path); + if ( pathlen != 0 && link_path[pathlen-1] != '/') + return t_strconcat(link_path, "/", NULL); + + return t_strdup(link_path); +} + +static mode_t get_dir_mode(mode_t mode) +{ + /* Add the execute bit if either read or write bit is set */ + + if ((mode & 0600) != 0) mode |= 0100; + if ((mode & 0060) != 0) mode |= 0010; + if ((mode & 0006) != 0) mode |= 0001; + + return mode; +} + +static int mkdir_verify +(struct sieve_storage *storage, const char *dir, + mode_t mode, gid_t gid, const char *gid_origin) +{ + struct stat st; + + if ( stat(dir, &st) == 0 ) + return 0; + + if ( errno == EACCES ) { + e_error(storage->event, "mkdir_verify: %s", + eacces_error_get("stat", dir)); + return -1; + } else if ( errno != ENOENT ) { + e_error(storage->event, "mkdir_verify: " + "stat(%s) failed: %m", dir); + return -1; + } + + if ( mkdir_parents_chgrp(dir, mode, gid, gid_origin) == 0 ) { + e_debug(storage->event, "Created storage directory %s", dir); + return 0; + } + + switch ( errno ) { + case EEXIST: + return 0; + case ENOENT: + e_error(storage->event, + "Storage was deleted while it was being created"); + break; + case EACCES: + e_error(storage->event, "%s", + eacces_error_get_creating("mkdir_parents_chgrp", dir)); + break; + default: + e_error(storage->event, + "mkdir_parents_chgrp(%s) failed: %m", dir); + break; + } + + return -1; +} + +static int check_tmp(struct sieve_storage *storage, const char *path) +{ + struct stat st; + + /* If tmp/ directory exists, we need to clean it up once in a while */ + if ( stat(path, &st) < 0 ) { + if ( errno == ENOENT ) + return 0; + if ( errno == EACCES ) { + e_error(storage->event, "check_tmp: %s", + eacces_error_get("stat", path)); + return -1; + } + e_error(storage->event, "check_tmp: stat(%s) failed: %m", path); + return -1; + } + + if ( st.st_atime > st.st_ctime + SIEVE_FILE_STORAGE_TMP_DELETE_SECS ) { + /* The directory should be empty. we won't do anything + until ctime changes. */ + } else if ( st.st_atime < ioloop_time - SIEVE_FILE_STORAGE_TMP_SCAN_SECS ) { + /* Time to scan */ + (void)unlink_old_files(path, "", + ioloop_time - SIEVE_FILE_STORAGE_TMP_DELETE_SECS); + } + return 1; +} + +static struct sieve_storage *sieve_file_storage_alloc(void) +{ + struct sieve_file_storage *fstorage; + pool_t pool; + + pool = pool_alloconly_create("sieve_file_storage", 2048); + fstorage = p_new(pool, struct sieve_file_storage, 1); + fstorage->storage = sieve_file_storage; + fstorage->storage.pool = pool; + + return &fstorage->storage; +} + +static int sieve_file_storage_get_full_path +(struct sieve_file_storage *fstorage, const char **storage_path, + enum sieve_error *error_r) +{ + struct sieve_storage *storage = &fstorage->storage; + struct sieve_instance *svinst = storage->svinst; + const char *path = *storage_path; + + /* Get full storage path */ + + if ( path != NULL && + ((path[0] == '~' && (path[1] == '/' || path[1] == '\0')) || + (((svinst->flags & SIEVE_FLAG_HOME_RELATIVE) != 0 ) && path[0] != '/')) ) { + /* home-relative path. change to absolute. */ + const char *home = sieve_environment_get_homedir(svinst); + + if ( home != NULL ) { + if ( path[0] == '~' && (path[1] == '/' || path[1] == '\0') ) + path = home_expand_tilde(path, home); + else + path = t_strconcat(home, "/", path, NULL); + } else { + sieve_storage_set_critical(storage, + "Sieve storage path `%s' is relative to home directory, " + "but home directory is not available.", path); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + } + *storage_path = path; + return 0; +} + +static int sieve_file_storage_get_full_active_path +(struct sieve_file_storage *fstorage, const char **active_path, + enum sieve_error *error_r) +{ + struct sieve_storage *storage = &fstorage->storage; + struct sieve_instance *svinst = storage->svinst; + const char *path = *active_path; + + if ( path != NULL && *path != '\0' && + ((path[0] == '~' && (path[1] == '/' || path[1] == '\0')) || + (((svinst->flags & SIEVE_FLAG_HOME_RELATIVE) != 0 ) && path[0] != '/')) + ) { + /* home-relative path. change to absolute. */ + const char *home = sieve_environment_get_homedir(svinst); + + if ( home != NULL ) { + if ( path[0] == '~' && (path[1] == '/' || path[1] == '\0') ) + path = home_expand_tilde(path, home); + else + path = t_strconcat(home, "/", path, NULL); + } else { + sieve_storage_set_critical(storage, + "Sieve storage active script path `%s' is relative to home directory, " + "but home directory is not available.", path); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + } + *active_path = path; + return 0; +} + +static int sieve_file_storage_init_common +(struct sieve_file_storage *fstorage, const char *active_path, + const char *storage_path, bool exists, enum sieve_error *error_r) + ATTR_NULL(2, 3) +{ + struct sieve_storage *storage = &fstorage->storage; + const char *tmp_dir, *link_path, *active_fname, *storage_dir, *error; + bool have_link = FALSE; + int ret; + + i_assert( storage_path != NULL || active_path != NULL ); + + fstorage->prev_mtime = (time_t)-1; + + /* Get active script path */ + + if ( sieve_file_storage_get_full_active_path + (fstorage, &active_path, error_r) < 0 ) + return -1; + + /* Get the filename for the active script link */ + + active_fname = NULL; + if ( active_path != NULL && *active_path != '\0' ) { + const char *active_dir; + + active_fname = strrchr(active_path, '/'); + if ( active_fname == NULL ) { + active_fname = active_path; + active_dir = ""; + } else { + active_dir = t_strdup_until(active_path, active_fname); + active_fname++; + } + + if ( *active_fname == '\0' ) { + /* Link cannot be just a path ending in '/' */ + sieve_storage_set_critical(storage, + "Path to %sscript must include the filename (path=%s)", + ( storage_path != NULL ? "active link/" : "" ), + active_path); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + + if (t_realpath(active_dir, &active_dir, &error) < 0) { + if (errno != ENOENT) { + e_error(storage->event, + "Failed to normalize active script directory " + "(path=%s): %s", active_dir, error); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + e_debug(storage->event, + "Failed to normalize active script directory " + "(path=%s): " + "Part of the path does not exist (yet)", + active_dir); + } else { + active_path = t_abspath_to(active_fname, active_dir); + } + + e_debug(storage->event, "Using %sSieve script path: %s", + (storage_path != NULL ? "active " : ""), active_path); + + fstorage->active_path = p_strdup(storage->pool, active_path); + fstorage->active_fname = p_strdup(storage->pool, active_fname); + } + + /* Determine storage path */ + + storage_dir = storage_path; + if ( storage_path != NULL && *storage_path != '\0' ) { + e_debug(storage->event, "Using script storage path: %s", + storage_path); + have_link = TRUE; + + } else { + if ((storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0 ) { + sieve_storage_set_critical(storage, + "Storage path cannot be empty for write access"); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + + storage_path = active_path; + } + + i_assert(storage_path != NULL); + + /* Prepare for write access */ + + if ( (storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0 ) { + mode_t dir_create_mode, file_create_mode; + gid_t file_create_gid; + const char *file_create_gid_origin; + + /* Use safe permission defaults */ + file_create_mode = 0600; + dir_create_mode = 0700; + file_create_gid = (gid_t)-1; + file_create_gid_origin = "defaults"; + + /* Get actual permissions */ + if ( exists ) { + file_create_mode = (fstorage->st.st_mode & 0666) | 0600; + dir_create_mode = (fstorage->st.st_mode & 0777) | 0700; + file_create_gid_origin = storage_dir; + + if ( !S_ISDIR(fstorage->st.st_mode) ) { + /* We're getting permissions from a file. + Apply +x modes as necessary. */ + dir_create_mode = get_dir_mode(dir_create_mode); + } + + if (S_ISDIR(fstorage->st.st_mode) && + (fstorage->st.st_mode & S_ISGID) != 0) { + /* Directory's GID is used automatically for new files */ + file_create_gid = (gid_t)-1; + } else if ((fstorage->st.st_mode & 0070) >> 3 == + (fstorage->st.st_mode & 0007)) { + /* Group has same permissions as world, so don't bother changing it */ + file_create_gid = (gid_t)-1; + } else if (getegid() == fstorage->st.st_gid) { + /* Using our own gid, no need to change it */ + file_create_gid = (gid_t)-1; + } else { + file_create_gid = fstorage->st.st_gid; + } + } + + e_debug(storage->event, + "Using permissions from %s: mode=0%o gid=%ld", + file_create_gid_origin, (int)dir_create_mode, + file_create_gid == (gid_t)-1 ? + -1L : (long)file_create_gid); + + /* + * Ensure sieve local directory structure exists (full autocreate): + * This currently only consists of a ./tmp direcory + */ + + tmp_dir = t_strconcat(storage_path, "/tmp", NULL); + + /* Try to find and clean up tmp dir */ + if ( (ret=check_tmp(storage, tmp_dir)) < 0 ) { + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + + /* Auto-create if necessary */ + if ( ret == 0 && mkdir_verify(storage, tmp_dir, + dir_create_mode, file_create_gid, file_create_gid_origin) < 0 ) { + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + + fstorage->dir_create_mode = dir_create_mode; + fstorage->file_create_mode = file_create_mode; + fstorage->file_create_gid = file_create_gid; + } + + if ( !exists && sieve_file_storage_stat + (fstorage, storage_path, error_r) < 0 ) + return -1; + + if ( have_link ) { + if ( t_realpath(storage_path, &storage_path, &error) < 0 ) { + e_error(storage->event, + "Failed to normalize storage path (path=%s): %s", + storage_path, error); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + if ( active_path != NULL && *active_path != '\0' ) { + /* Get the path to be prefixed to the script name in the symlink + * pointing to the active script. + */ + link_path = sieve_storage_get_relative_link_path + (fstorage->active_path, storage_path); + + e_debug(storage->event, + "Relative path to sieve storage in active link: %s", + link_path); + + fstorage->link_path = p_strdup(storage->pool, link_path); + } + } + + fstorage->path = p_strdup(storage->pool, storage_path); + storage->location = fstorage->path; + + return 0; +} + +static int sieve_file_storage_init +(struct sieve_storage *storage, const char *const *options, + enum sieve_error *error_r) +{ + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)storage; + const char *storage_path = storage->location; + const char *active_path = ""; + bool exists = FALSE; + + if ( options != NULL ) { + while ( *options != NULL ) { + const char *option = *options; + + if ( strncasecmp(option, "active=", 7) == 0 && option[7] != '\0' ) { + active_path = option+7; + } else { + sieve_storage_set_critical(storage, + "Invalid option `%s'", option); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + + options++; + } + } + + /* Get full storage path */ + + if ( sieve_file_storage_get_full_path + (fstorage, &storage_path, error_r) < 0 ) + return -1; + + /* Stat storage directory */ + + if ( storage_path != NULL && *storage_path != '\0' ) { + if ( sieve_file_storage_stat(fstorage, storage_path, error_r) < 0 ) { + if ( *error_r != SIEVE_ERROR_NOT_FOUND ) + return -1; + if ( (storage->flags & SIEVE_STORAGE_FLAG_READWRITE) == 0 ) { + /* For backwards compatibility, recognize when storage directory + does not exist while active script exists and is a regular + file. */ + if ( active_path == NULL || *active_path == '\0' ) + return -1; + if ( sieve_file_storage_get_full_active_path + (fstorage, &active_path, error_r) < 0 ) + return -1; + if ( sieve_file_storage_stat + (fstorage, active_path, error_r) < 0 ) + return -1; + if ( !S_ISREG(fstorage->lnk_st.st_mode) ) + return -1; + e_debug(storage->event, + "Sieve storage path `%s' not found, " + "but the active script `%s' is a regular file, " + "so this is used for backwards compatibility.", + storage_path, active_path); + storage_path = NULL; + } + } else { + exists = TRUE; + + if ( !S_ISDIR(fstorage->st.st_mode) ) { + if ( (storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0 ) { + sieve_storage_set_critical(storage, + "Sieve storage path `%s' is not a directory, " + "but it is to be opened for write access", storage_path); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + if ( active_path != NULL && *active_path != '\0' ) { + e_warning(storage->event, + "Explicitly specified active script path `%s' is ignored; " + "storage path `%s' is not a directory", + active_path, storage_path); + } + active_path = storage_path; + storage_path = NULL; + } + } + } + + if ( active_path == NULL || *active_path == '\0' ) { + if ( storage->main_storage || + (storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0) { + e_debug(storage->event, + "Active script path is unconfigured; " + "using default (path=%s)", + SIEVE_FILE_DEFAULT_PATH); + active_path = SIEVE_FILE_DEFAULT_PATH; + } + } + + return sieve_file_storage_init_common + (fstorage, active_path, storage_path, exists, error_r); +} + +static void sieve_file_storage_autodetect +(struct sieve_file_storage *fstorage, const char **storage_path_r) +{ + struct sieve_storage *storage = &fstorage->storage; + struct sieve_instance *svinst = storage->svinst; + const char *home = sieve_environment_get_homedir(svinst); + int mode = ( (storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0 ? + R_OK|W_OK|X_OK : R_OK|X_OK ); + + e_debug(storage->event, "Performing auto-detection"); + + /* We'll need to figure out the storage location ourself. + * + * It's $HOME/sieve or /sieve when (presumed to be) chrooted. + */ + if ( home != NULL && *home != '\0' ) { + /* Use default ~/sieve */ + e_debug(storage->event, "Use home (%s)", home); + *storage_path_r = t_strconcat(home, "/sieve", NULL); + } else { + e_debug(storage->event, "HOME is not set"); + + if (access("/sieve", mode) == 0) { + *storage_path_r = "/sieve"; + e_debug(storage->event, + "Directory `/sieve' exists, assuming chroot"); + } + } +} + +static int sieve_file_storage_do_init_legacy +(struct sieve_file_storage *fstorage, const char *active_path, + const char *storage_path, enum sieve_error *error_r) +{ + struct sieve_storage *storage = &fstorage->storage; + bool explicit = FALSE, exists = FALSE; + + if ( storage_path == NULL || *storage_path == '\0' ) { + /* Try autodectection */ + sieve_file_storage_autodetect(fstorage, &storage_path); + + if ( storage_path != NULL && *storage_path != '\0') { + /* Got something: stat it */ + if (sieve_file_storage_stat + (fstorage, storage_path, error_r) < 0 ) { + if (*error_r != SIEVE_ERROR_NOT_FOUND) { + /* Error */ + return -1; + } + } else if ( S_ISDIR(fstorage->st.st_mode) ) { + /* Success */ + exists = TRUE; + } + } + + if ( (storage_path == NULL || *storage_path == '\0') && + (storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0 ) { + sieve_storage_set_critical(storage, + "Could not find storage root directory for write access; " + "path was left unconfigured and autodetection failed"); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + + } else { + /* Get full storage path */ + if ( sieve_file_storage_get_full_path + (fstorage, &storage_path, error_r) < 0 ) + return -1; + + /* Stat storage directory */ + if ( sieve_file_storage_stat(fstorage, storage_path, error_r) < 0 ) { + if ( (*error_r != SIEVE_ERROR_NOT_FOUND) ) + return -1; + if ( (storage->flags & SIEVE_STORAGE_FLAG_READWRITE) == 0 ) + storage_path = NULL; + } else { + exists = TRUE; + } + + /* Storage path must be a directory */ + if ( exists && !S_ISDIR(fstorage->st.st_mode) ) { + sieve_storage_set_critical(storage, + "Sieve storage path `%s' configured using sieve_dir " + "is not a directory", storage_path); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + + explicit = TRUE; + } + + if ( (active_path == NULL || *active_path == '\0') ) { + if ( storage->main_storage || + (storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0) { + e_debug(storage->event, + "Active script path is unconfigured; " + "using default (path=%s)", + SIEVE_FILE_DEFAULT_PATH); + active_path = SIEVE_FILE_DEFAULT_PATH; + } else { + return -1; + } + } + + if ( !explicit && !exists && + active_path != NULL && *active_path != '\0' && + (storage->flags & SIEVE_STORAGE_FLAG_READWRITE) == 0 ) + storage_path = NULL; + + if ( sieve_file_storage_init_common + (fstorage, active_path, storage_path, exists, error_r) < 0 ) + return -1; + return 0; +} + +struct sieve_storage *sieve_file_storage_init_legacy +(struct sieve_instance *svinst, const char *active_path, + const char *storage_path, enum sieve_storage_flags flags, + enum sieve_error *error_r) +{ + struct sieve_storage *storage; + struct sieve_file_storage *fstorage; + + storage = sieve_storage_alloc(svinst, NULL, &sieve_file_storage, + "", flags, TRUE); + fstorage = (struct sieve_file_storage *)storage; + + T_BEGIN { + if ( sieve_file_storage_do_init_legacy + (fstorage, active_path, storage_path, error_r) < 0 ) { + sieve_storage_unref(&storage); + storage = NULL; + } + } T_END; + + return storage; +} + +struct sieve_file_storage *sieve_file_storage_init_from_path +(struct sieve_instance *svinst, const char *path, + enum sieve_storage_flags flags, enum sieve_error *error_r) +{ + struct sieve_storage *storage; + struct sieve_file_storage *fstorage; + + i_assert( path != NULL ); + + storage = sieve_storage_alloc(svinst, NULL, &sieve_file_storage, + "", flags, FALSE); + fstorage = (struct sieve_file_storage *)storage; + + T_BEGIN { + if ( sieve_file_storage_init_common + (fstorage, path, NULL, FALSE, error_r) < 0 ) { + sieve_storage_unref(&storage); + fstorage = NULL; + } + } T_END; + + return fstorage; +} + +static int sieve_file_storage_is_singular +(struct sieve_storage *storage) +{ + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)storage; + struct stat st; + + if ( fstorage->active_path == NULL ) + return 1; + + /* Stat the file */ + if ( lstat(fstorage->active_path, &st) != 0 ) { + if ( errno != ENOENT ) { + sieve_storage_set_critical(storage, + "Failed to stat active sieve script symlink (%s): %m.", + fstorage->active_path); + return -1; + } + return 0; + } + + if ( S_ISLNK( st.st_mode ) ) + return 0; + if ( !S_ISREG( st.st_mode ) ) { + sieve_storage_set_critical(storage, + "Active sieve script file '%s' is no symlink nor a regular file.", + fstorage->active_path); + return -1; + } + return 1; +} + +/* + * + */ + +static int sieve_file_storage_get_last_change +(struct sieve_storage *storage, time_t *last_change_r) +{ + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)storage; + struct stat st; + + if ( fstorage->prev_mtime == (time_t)-1 ) { + /* Get the storage mtime before we modify it ourself */ + if ( stat(fstorage->path, &st) < 0 ) { + if ( errno != ENOENT ) { + e_error(storage->event, + "stat(%s) failed: %m", + fstorage->path); + return -1; + } + st.st_mtime = 0; + } + + fstorage->prev_mtime = st.st_mtime; + } + + if ( last_change_r != NULL ) + *last_change_r = fstorage->prev_mtime; + return 0; +} + +int sieve_file_storage_pre_modify +(struct sieve_storage *storage) +{ + i_assert( (storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0 ); + + return sieve_storage_get_last_change(storage, NULL); +} + +static void sieve_file_storage_set_modified +(struct sieve_storage *storage, time_t mtime) +{ + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)storage; + struct utimbuf times; + time_t cur_mtime; + + if ( mtime != (time_t)-1 ) { + if ( sieve_storage_get_last_change(storage, &cur_mtime) >= 0 && + cur_mtime > mtime ) + return; + } else { + mtime = ioloop_time; + } + + times.actime = mtime; + times.modtime = mtime; + if ( utime(fstorage->path, ×) < 0 ) { + switch ( errno ) { + case ENOENT: + break; + case EACCES: + e_error(storage->event, "%s", + eacces_error_get("utime", fstorage->path)); + break; + default: + e_error(storage->event, + "utime(%s) failed: %m", fstorage->path); + } + } else { + fstorage->prev_mtime = mtime; + } +} + +/* + * Script access + */ + +static struct sieve_script *sieve_file_storage_get_script +(struct sieve_storage *storage, const char *name) +{ + struct sieve_file_storage *fstorage = + (struct sieve_file_storage *)storage; + struct sieve_file_script *fscript; + + T_BEGIN { + fscript = sieve_file_script_init_from_name(fstorage, name); + } T_END; + + return &fscript->script; +} + +/* + * Driver definition + */ + +const struct sieve_storage sieve_file_storage = { + .driver_name = SIEVE_FILE_STORAGE_DRIVER_NAME, + .version = 0, + .allows_synchronization = TRUE, + .v = { + .alloc = sieve_file_storage_alloc, + .init = sieve_file_storage_init, + + .get_last_change = sieve_file_storage_get_last_change, + .set_modified = sieve_file_storage_set_modified, + + .is_singular = sieve_file_storage_is_singular, + + .get_script = sieve_file_storage_get_script, + + .get_script_sequence = sieve_file_storage_get_script_sequence, + .script_sequence_next = sieve_file_script_sequence_next, + .script_sequence_destroy = sieve_file_script_sequence_destroy, + + .active_script_get_name = sieve_file_storage_active_script_get_name, + .active_script_open = sieve_file_storage_active_script_open, + .deactivate = sieve_file_storage_deactivate, + .active_script_get_last_change = + sieve_file_storage_active_script_get_last_change, + + .list_init = sieve_file_storage_list_init, + .list_next = sieve_file_storage_list_next, + .list_deinit = sieve_file_storage_list_deinit, + + .save_alloc = sieve_file_storage_save_alloc, + .save_init = sieve_file_storage_save_init, + .save_continue = sieve_file_storage_save_continue, + .save_finish = sieve_file_storage_save_finish, + .save_get_tempscript = sieve_file_storage_save_get_tempscript, + .save_cancel = sieve_file_storage_save_cancel, + .save_commit = sieve_file_storage_save_commit, + .save_as = sieve_file_storage_save_as, + .save_as_active = sieve_file_storage_save_as_active, + + .quota_havespace = sieve_file_storage_quota_havespace + } +}; diff --git a/pigeonhole/src/lib-sieve/storage/file/sieve-file-storage.h b/pigeonhole/src/lib-sieve/storage/file/sieve-file-storage.h new file mode 100644 index 0000000..ea7b92f --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/file/sieve-file-storage.h @@ -0,0 +1,186 @@ +#ifndef SIEVE_FILE_STORAGE_H +#define SIEVE_FILE_STORAGE_H + +#include "lib.h" +#include "mail-user.h" + +#include "sieve.h" +#include "sieve-script-private.h" +#include "sieve-storage-private.h" + +#include <sys/types.h> +#include <sys/stat.h> + +#define SIEVE_FILE_READ_BLOCK_SIZE (1024*8) + +#define SIEVE_FILE_DEFAULT_PATH "~/.dovecot."SIEVE_SCRIPT_FILEEXT + +/* How often to scan tmp/ directory for old files (based on dir's atime) */ +#define SIEVE_FILE_STORAGE_TMP_SCAN_SECS (8*60*60) +/* Delete files having ctime older than this from tmp/. 36h is standard. */ +#define SIEVE_FILE_STORAGE_TMP_DELETE_SECS (36*60*60) + +/* + * Storage class + */ + +struct sieve_file_storage { + struct sieve_storage storage; + + const char *path; + const char *active_path; + const char *active_fname; + const char *link_path; + + struct stat st; + struct stat lnk_st; + + mode_t dir_create_mode; + mode_t file_create_mode; + gid_t file_create_gid; + + time_t prev_mtime; +}; + +const char *sieve_file_storage_path_extend + (struct sieve_file_storage *fstorage, const char *filename); + +struct sieve_file_storage *sieve_file_storage_init_from_path +(struct sieve_instance *svinst, const char *path, + enum sieve_storage_flags flags, enum sieve_error *error_r) + ATTR_NULL(4); + +int sieve_file_storage_pre_modify + (struct sieve_storage *storage); + +/* Active script */ + +int sieve_file_storage_active_replace_link + (struct sieve_file_storage *fstorage, const char *link_path); +bool sieve_file_storage_active_rescue_regular + (struct sieve_file_storage *fstorage); + +int sieve_file_storage_active_script_get_name + (struct sieve_storage *storage, const char **name_r); +struct sieve_script *sieve_file_storage_active_script_open + (struct sieve_storage *storage); + +int sieve_file_storage_active_script_get_file + (struct sieve_file_storage *fstorage, const char **file_r); +int sieve_file_storage_active_script_is_no_link + (struct sieve_file_storage *fstorage); + +int sieve_file_storage_deactivate + (struct sieve_storage *storage); + +int sieve_file_storage_active_script_get_last_change + (struct sieve_storage *storage, time_t *last_change_r); + +/* Listing */ + +struct sieve_storage_list_context *sieve_file_storage_list_init + (struct sieve_storage *storage); +const char *sieve_file_storage_list_next + (struct sieve_storage_list_context *ctx, bool *active); +int sieve_file_storage_list_deinit + (struct sieve_storage_list_context *lctx); + +/* Saving */ + +struct sieve_storage_save_context * +sieve_file_storage_save_alloc(struct sieve_storage *storage); +int sieve_file_storage_save_init(struct sieve_storage_save_context *sctx, + const char *scriptname, struct istream *input); +int sieve_file_storage_save_continue + (struct sieve_storage_save_context *sctx); +int sieve_file_storage_save_finish + (struct sieve_storage_save_context *sctx); +struct sieve_script *sieve_file_storage_save_get_tempscript + (struct sieve_storage_save_context *sctx); +int sieve_file_storage_save_commit + (struct sieve_storage_save_context *sctx); +void sieve_file_storage_save_cancel + (struct sieve_storage_save_context *sctx); + +int sieve_file_storage_save_as + (struct sieve_storage *storage, struct istream *input, + const char *name); +int sieve_file_storage_save_as_active + (struct sieve_storage *storage, struct istream *input, + time_t mtime); + +/* Quota */ + +int sieve_file_storage_quota_havespace +(struct sieve_storage *storage, const char *scriptname, size_t size, + enum sieve_storage_quota *quota_r, uint64_t *limit_r); + +/* + * Sieve script filenames + */ + +const char *sieve_script_file_get_scriptname(const char *filename); +const char *sieve_script_file_from_name(const char *name); + +/* + * Script class + */ + +struct sieve_file_script { + struct sieve_script script; + + struct stat st; + struct stat lnk_st; + + const char *path; + const char *dirpath; + const char *filename; + const char *binpath; + const char *binprefix; + + time_t prev_mtime; +}; + +struct sieve_file_script *sieve_file_script_init_from_filename + (struct sieve_file_storage *fstorage, const char *filename, + const char *scriptname); +struct sieve_file_script *sieve_file_script_open_from_filename + (struct sieve_file_storage *fstorage, const char *filename, + const char *scriptname); +struct sieve_file_script *sieve_file_script_init_from_name + (struct sieve_file_storage *fstorage, const char *name); +struct sieve_file_script *sieve_file_script_open_from_name + (struct sieve_file_storage *fstorage, const char *name); + +struct sieve_file_script *sieve_file_script_init_from_path + (struct sieve_file_storage *fstorage, const char *path, + const char *scriptname, enum sieve_error *error_r) + ATTR_NULL(4); +struct sieve_file_script *sieve_file_script_open_from_path + (struct sieve_file_storage *fstorage, const char *path, + const char *scriptname, enum sieve_error *error_r) + ATTR_NULL(4); + +/* Return directory where script resides in. Returns NULL if this is not a file + * script. + */ +const char *sieve_file_script_get_dirpath + (const struct sieve_script *script); + +/* Return full path to file script. Returns NULL if this is not a file script. + */ +const char *sieve_file_script_get_path + (const struct sieve_script *script); + +/* + * Script sequence + */ + +struct sieve_script_sequence *sieve_file_storage_get_script_sequence + (struct sieve_storage *storage, enum sieve_error *error_r); + +struct sieve_script *sieve_file_script_sequence_next + (struct sieve_script_sequence *seq, enum sieve_error *error_r); +void sieve_file_script_sequence_destroy(struct sieve_script_sequence *seq); + +#endif diff --git a/pigeonhole/src/lib-sieve/storage/ldap/Makefile.am b/pigeonhole/src/lib-sieve/storage/ldap/Makefile.am new file mode 100644 index 0000000..86df92c --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/ldap/Makefile.am @@ -0,0 +1,32 @@ +noinst_LTLIBRARIES = libsieve_storage_ldap.la + +sieve_plugindir = $(dovecot_moduledir)/sieve +sieve_plugin_LTLIBRARIES = + +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/lib-sieve + +ldap_sources = \ + sieve-ldap-db.c \ + sieve-ldap-script.c \ + sieve-ldap-storage.c \ + sieve-ldap-storage-settings.c + +libsieve_storage_ldap_la_SOURCES = $(ldap_sources) +libsieve_storage_ldap_la_LIBADD = $(LDAP_LIBS) + +noinst_HEADERS = \ + sieve-ldap-db.h \ + sieve-ldap-storage.h + +if LDAP_PLUGIN +sieve_plugin_LTLIBRARIES += lib10_sieve_storage_ldap_plugin.la + +lib10_sieve_storage_ldap_plugin_la_LDFLAGS = -module -avoid-version +lib10_sieve_storage_ldap_plugin_la_LIBADD = $(LDAP_LIBS) +lib10_sieve_storage_ldap_plugin_la_DEPENDENCIES = $(LDAP_LIBS) +lib10_sieve_storage_ldap_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DPLUGIN_BUILD +lib10_sieve_storage_ldap_plugin_la_SOURCES = $(ldap_sources) +endif diff --git a/pigeonhole/src/lib-sieve/storage/ldap/Makefile.in b/pigeonhole/src/lib-sieve/storage/ldap/Makefile.in new file mode 100644 index 0000000..232f781 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/ldap/Makefile.in @@ -0,0 +1,843 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@LDAP_PLUGIN_TRUE@am__append_1 = lib10_sieve_storage_ldap_plugin.la +subdir = src/lib-sieve/storage/ldap +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(sieve_plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(sieve_plugin_LTLIBRARIES) +am__DEPENDENCIES_1 = +am__lib10_sieve_storage_ldap_plugin_la_SOURCES_DIST = sieve-ldap-db.c \ + sieve-ldap-script.c sieve-ldap-storage.c \ + sieve-ldap-storage-settings.c +am__objects_1 = lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.lo \ + lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.lo \ + lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.lo \ + lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.lo +@LDAP_PLUGIN_TRUE@am_lib10_sieve_storage_ldap_plugin_la_OBJECTS = \ +@LDAP_PLUGIN_TRUE@ $(am__objects_1) +lib10_sieve_storage_ldap_plugin_la_OBJECTS = \ + $(am_lib10_sieve_storage_ldap_plugin_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +lib10_sieve_storage_ldap_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) \ + --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ + $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(lib10_sieve_storage_ldap_plugin_la_LDFLAGS) $(LDFLAGS) -o $@ +@LDAP_PLUGIN_TRUE@am_lib10_sieve_storage_ldap_plugin_la_rpath = \ +@LDAP_PLUGIN_TRUE@ -rpath $(sieve_plugindir) +libsieve_storage_ldap_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am__objects_2 = sieve-ldap-db.lo sieve-ldap-script.lo \ + sieve-ldap-storage.lo sieve-ldap-storage-settings.lo +am_libsieve_storage_ldap_la_OBJECTS = $(am__objects_2) +libsieve_storage_ldap_la_OBJECTS = \ + $(am_libsieve_storage_ldap_la_OBJECTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.Plo \ + ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.Plo \ + ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.Plo \ + ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.Plo \ + ./$(DEPDIR)/sieve-ldap-db.Plo \ + ./$(DEPDIR)/sieve-ldap-script.Plo \ + ./$(DEPDIR)/sieve-ldap-storage-settings.Plo \ + ./$(DEPDIR)/sieve-ldap-storage.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(lib10_sieve_storage_ldap_plugin_la_SOURCES) \ + $(libsieve_storage_ldap_la_SOURCES) +DIST_SOURCES = $(am__lib10_sieve_storage_ldap_plugin_la_SOURCES_DIST) \ + $(libsieve_storage_ldap_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_storage_ldap.la +sieve_plugindir = $(dovecot_moduledir)/sieve +sieve_plugin_LTLIBRARIES = $(am__append_1) +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/lib-sieve + +ldap_sources = \ + sieve-ldap-db.c \ + sieve-ldap-script.c \ + sieve-ldap-storage.c \ + sieve-ldap-storage-settings.c + +libsieve_storage_ldap_la_SOURCES = $(ldap_sources) +libsieve_storage_ldap_la_LIBADD = $(LDAP_LIBS) +noinst_HEADERS = \ + sieve-ldap-db.h \ + sieve-ldap-storage.h + +@LDAP_PLUGIN_TRUE@lib10_sieve_storage_ldap_plugin_la_LDFLAGS = -module -avoid-version +@LDAP_PLUGIN_TRUE@lib10_sieve_storage_ldap_plugin_la_LIBADD = $(LDAP_LIBS) +@LDAP_PLUGIN_TRUE@lib10_sieve_storage_ldap_plugin_la_DEPENDENCIES = $(LDAP_LIBS) +@LDAP_PLUGIN_TRUE@lib10_sieve_storage_ldap_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DPLUGIN_BUILD +@LDAP_PLUGIN_TRUE@lib10_sieve_storage_ldap_plugin_la_SOURCES = $(ldap_sources) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/storage/ldap/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/storage/ldap/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-sieve_pluginLTLIBRARIES: $(sieve_plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(sieve_plugin_LTLIBRARIES)'; test -n "$(sieve_plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(sieve_plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sieve_plugindir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(sieve_plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(sieve_plugindir)"; \ + } + +uninstall-sieve_pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(sieve_plugin_LTLIBRARIES)'; test -n "$(sieve_plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(sieve_plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(sieve_plugindir)/$$f"; \ + done + +clean-sieve_pluginLTLIBRARIES: + -test -z "$(sieve_plugin_LTLIBRARIES)" || rm -f $(sieve_plugin_LTLIBRARIES) + @list='$(sieve_plugin_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +lib10_sieve_storage_ldap_plugin.la: $(lib10_sieve_storage_ldap_plugin_la_OBJECTS) $(lib10_sieve_storage_ldap_plugin_la_DEPENDENCIES) $(EXTRA_lib10_sieve_storage_ldap_plugin_la_DEPENDENCIES) + $(AM_V_CCLD)$(lib10_sieve_storage_ldap_plugin_la_LINK) $(am_lib10_sieve_storage_ldap_plugin_la_rpath) $(lib10_sieve_storage_ldap_plugin_la_OBJECTS) $(lib10_sieve_storage_ldap_plugin_la_LIBADD) $(LIBS) + +libsieve_storage_ldap.la: $(libsieve_storage_ldap_la_OBJECTS) $(libsieve_storage_ldap_la_DEPENDENCIES) $(EXTRA_libsieve_storage_ldap_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_storage_ldap_la_OBJECTS) $(libsieve_storage_ldap_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-ldap-db.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-ldap-script.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-ldap-storage-settings.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-ldap-storage.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.lo: sieve-ldap-db.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib10_sieve_storage_ldap_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.lo -MD -MP -MF $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.Tpo -c -o lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.lo `test -f 'sieve-ldap-db.c' || echo '$(srcdir)/'`sieve-ldap-db.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.Tpo $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sieve-ldap-db.c' object='lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib10_sieve_storage_ldap_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.lo `test -f 'sieve-ldap-db.c' || echo '$(srcdir)/'`sieve-ldap-db.c + +lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.lo: sieve-ldap-script.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib10_sieve_storage_ldap_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.lo -MD -MP -MF $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.Tpo -c -o lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.lo `test -f 'sieve-ldap-script.c' || echo '$(srcdir)/'`sieve-ldap-script.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.Tpo $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sieve-ldap-script.c' object='lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib10_sieve_storage_ldap_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.lo `test -f 'sieve-ldap-script.c' || echo '$(srcdir)/'`sieve-ldap-script.c + +lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.lo: sieve-ldap-storage.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib10_sieve_storage_ldap_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.lo -MD -MP -MF $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.Tpo -c -o lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.lo `test -f 'sieve-ldap-storage.c' || echo '$(srcdir)/'`sieve-ldap-storage.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.Tpo $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sieve-ldap-storage.c' object='lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib10_sieve_storage_ldap_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.lo `test -f 'sieve-ldap-storage.c' || echo '$(srcdir)/'`sieve-ldap-storage.c + +lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.lo: sieve-ldap-storage-settings.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib10_sieve_storage_ldap_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.lo -MD -MP -MF $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.Tpo -c -o lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.lo `test -f 'sieve-ldap-storage-settings.c' || echo '$(srcdir)/'`sieve-ldap-storage-settings.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.Tpo $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sieve-ldap-storage-settings.c' object='lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib10_sieve_storage_ldap_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.lo `test -f 'sieve-ldap-storage-settings.c' || echo '$(srcdir)/'`sieve-ldap-storage-settings.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(sieve_plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-sieve_pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.Plo + -rm -f ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.Plo + -rm -f ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.Plo + -rm -f ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.Plo + -rm -f ./$(DEPDIR)/sieve-ldap-db.Plo + -rm -f ./$(DEPDIR)/sieve-ldap-script.Plo + -rm -f ./$(DEPDIR)/sieve-ldap-storage-settings.Plo + -rm -f ./$(DEPDIR)/sieve-ldap-storage.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-sieve_pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.Plo + -rm -f ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.Plo + -rm -f ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.Plo + -rm -f ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.Plo + -rm -f ./$(DEPDIR)/sieve-ldap-db.Plo + -rm -f ./$(DEPDIR)/sieve-ldap-script.Plo + -rm -f ./$(DEPDIR)/sieve-ldap-storage-settings.Plo + -rm -f ./$(DEPDIR)/sieve-ldap-storage.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-sieve_pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-sieve_pluginLTLIBRARIES cscopelist-am ctags ctags-am \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-sieve_pluginLTLIBRARIES \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-sieve_pluginLTLIBRARIES + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-db.c b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-db.c new file mode 100644 index 0000000..0a7b440 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-db.c @@ -0,0 +1,1378 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-common.h" + +#include "sieve-ldap-storage.h" + +/* FIXME: Imported this from Dovecot auth for now. We're working on a proper + lib-ldap, but, until then, some code is duplicated here. */ + +#if defined(SIEVE_BUILTIN_LDAP) || defined(PLUGIN_BUILD) + +#include "net.h" +#include "ioloop.h" +#include "array.h" +#include "hash.h" +#include "aqueue.h" +#include "str.h" +#include "time-util.h" +#include "env-util.h" +#include "var-expand.h" +#include "istream.h" + +#include <stddef.h> +#include <unistd.h> + +struct db_ldap_result { + int refcount; + LDAPMessage *msg; +}; + +struct db_ldap_result_iterate_context { + pool_t pool; + + struct auth_request *auth_request; + const ARRAY_TYPE(ldap_field) *attr_map; + unsigned int attr_idx; + + /* attribute name => value */ + HASH_TABLE(char *, struct db_ldap_value *) ldap_attrs; + + const char *val_1_arr[2]; + string_t *var, *debug; + + bool skip_null_values; + bool iter_dn_values; +}; + +struct db_ldap_sasl_bind_context { + const char *authcid; + const char *passwd; + const char *realm; + const char *authzid; +}; + +static struct ldap_connection *ldap_connections = NULL; + +static int db_ldap_bind(struct ldap_connection *conn); +static void db_ldap_conn_close(struct ldap_connection *conn); + +int ldap_deref_from_str(const char *str, int *deref_r) +{ + if (strcasecmp(str, "never") == 0) + *deref_r = LDAP_DEREF_NEVER; + else if (strcasecmp(str, "searching") == 0) + *deref_r = LDAP_DEREF_SEARCHING; + else if (strcasecmp(str, "finding") == 0) + *deref_r = LDAP_DEREF_FINDING; + else if (strcasecmp(str, "always") == 0) + *deref_r = LDAP_DEREF_ALWAYS; + else + return -1; + return 0; +} + +int ldap_scope_from_str(const char *str, int *scope_r) +{ + if (strcasecmp(str, "base") == 0) + *scope_r = LDAP_SCOPE_BASE; + else if (strcasecmp(str, "onelevel") == 0) + *scope_r = LDAP_SCOPE_ONELEVEL; + else if (strcasecmp(str, "subtree") == 0) + *scope_r = LDAP_SCOPE_SUBTREE; + else + return -1; + return 0; +} + +#ifdef OPENLDAP_TLS_OPTIONS +int ldap_tls_require_cert_from_str(const char *str, int *opt_x_tls_r) +{ + if (strcasecmp(str, "never") == 0) + *opt_x_tls_r = LDAP_OPT_X_TLS_NEVER; + else if (strcasecmp(str, "hard") == 0) + *opt_x_tls_r = LDAP_OPT_X_TLS_HARD; + else if (strcasecmp(str, "demand") == 0) + *opt_x_tls_r = LDAP_OPT_X_TLS_DEMAND; + else if (strcasecmp(str, "allow") == 0) + *opt_x_tls_r = LDAP_OPT_X_TLS_ALLOW; + else if (strcasecmp(str, "try") == 0) + *opt_x_tls_r = LDAP_OPT_X_TLS_TRY; + else + return -1; + return 0; +} +#endif + + +static int ldap_get_errno(struct ldap_connection *conn) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + int ret, err; + + ret = ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, (void *) &err); + if (ret != LDAP_SUCCESS) { + e_error(storage->event, "db: " + "Can't get error number: %s", + ldap_err2string(ret)); + return LDAP_UNAVAILABLE; + } + + return err; +} + +const char *ldap_get_error(struct ldap_connection *conn) +{ + const char *ret; + char *str = NULL; + + ret = ldap_err2string(ldap_get_errno(conn)); + + ldap_get_option(conn->ld, LDAP_OPT_ERROR_STRING, (void *)&str); + if (str != NULL) { + ret = t_strconcat(ret, ", ", str, NULL); + ldap_memfree(str); + } + ldap_set_option(conn->ld, LDAP_OPT_ERROR_STRING, NULL); + return ret; +} + +static void ldap_conn_reconnect(struct ldap_connection *conn) +{ + db_ldap_conn_close(conn); + if (sieve_ldap_db_connect(conn) < 0) + db_ldap_conn_close(conn); +} + +static int ldap_handle_error(struct ldap_connection *conn) +{ + int err = ldap_get_errno(conn); + + switch (err) { + case LDAP_SUCCESS: + i_unreached(); + case LDAP_SIZELIMIT_EXCEEDED: + case LDAP_TIMELIMIT_EXCEEDED: + case LDAP_NO_SUCH_ATTRIBUTE: + case LDAP_UNDEFINED_TYPE: + case LDAP_INAPPROPRIATE_MATCHING: + case LDAP_CONSTRAINT_VIOLATION: + case LDAP_TYPE_OR_VALUE_EXISTS: + case LDAP_INVALID_SYNTAX: + case LDAP_NO_SUCH_OBJECT: + case LDAP_ALIAS_PROBLEM: + case LDAP_INVALID_DN_SYNTAX: + case LDAP_IS_LEAF: + case LDAP_ALIAS_DEREF_PROBLEM: + case LDAP_FILTER_ERROR: + /* invalid input */ + return -1; + case LDAP_SERVER_DOWN: + case LDAP_TIMEOUT: + case LDAP_UNAVAILABLE: + case LDAP_BUSY: +#ifdef LDAP_CONNECT_ERROR + case LDAP_CONNECT_ERROR: +#endif + case LDAP_LOCAL_ERROR: + case LDAP_INVALID_CREDENTIALS: + case LDAP_OPERATIONS_ERROR: + default: + /* connection problems */ + ldap_conn_reconnect(conn); + return 0; + } +} + +static int db_ldap_request_search(struct ldap_connection *conn, + struct ldap_request *request) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + + i_assert(conn->conn_state == LDAP_CONN_STATE_BOUND); + i_assert(request->msgid == -1); + + request->msgid = + ldap_search(conn->ld, *request->base == '\0' ? NULL : + request->base, request->scope, + request->filter, request->attributes, 0); + if (request->msgid == -1) { + e_error(storage->event, "db: " + "ldap_search(%s) parsing failed: %s", + request->filter, ldap_get_error(conn)); + if (ldap_handle_error(conn) < 0) { + /* broken request, remove it */ + return 0; + } + return -1; + } + return 1; +} + +static bool db_ldap_request_queue_next(struct ldap_connection *conn) +{ + struct ldap_request *const *requestp, *request; + int ret = -1; + + /* connecting may call db_ldap_connect_finish(), which gets us back + here. so do the connection before checking the request queue. */ + if (sieve_ldap_db_connect(conn) < 0) + return FALSE; + + if (conn->pending_count == aqueue_count(conn->request_queue)) { + /* no non-pending requests */ + return FALSE; + } + if (conn->pending_count > DB_LDAP_MAX_PENDING_REQUESTS) { + /* wait until server has replied to some requests */ + return FALSE; + } + + requestp = array_idx(&conn->request_array, + aqueue_idx(conn->request_queue, + conn->pending_count)); + request = *requestp; + + switch (conn->conn_state) { + case LDAP_CONN_STATE_DISCONNECTED: + case LDAP_CONN_STATE_BINDING: + /* wait until we're in bound state */ + return FALSE; + case LDAP_CONN_STATE_BOUND: + /* we can do anything in this state */ + break; + } + + ret = db_ldap_request_search(conn, request); + if (ret > 0) { + /* success */ + i_assert(request->msgid != -1); + conn->pending_count++; + return TRUE; + } else if (ret < 0) { + /* disconnected */ + return FALSE; + } else { + /* broken request, remove from queue */ + aqueue_delete_tail(conn->request_queue); + request->callback(conn, request, NULL); + return TRUE; + } +} + +static bool +db_ldap_check_limits(struct ldap_connection *conn) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + struct ldap_request *const *first_requestp; + unsigned int count; + time_t secs_diff; + + count = aqueue_count(conn->request_queue); + if (count == 0) + return TRUE; + + first_requestp = array_idx(&conn->request_array, + aqueue_idx(conn->request_queue, 0)); + secs_diff = ioloop_time - (*first_requestp)->create_time; + if (secs_diff > DB_LDAP_REQUEST_LOST_TIMEOUT_SECS) { + e_error(storage->event, "db: " + "Connection appears to be hanging, reconnecting"); + ldap_conn_reconnect(conn); + return TRUE; + } + return TRUE; +} + +void db_ldap_request(struct ldap_connection *conn, + struct ldap_request *request) +{ + request->msgid = -1; + request->create_time = ioloop_time; + + if (!db_ldap_check_limits(conn)) { + request->callback(conn, request, NULL); + return; + } + + aqueue_append(conn->request_queue, &request); + (void)db_ldap_request_queue_next(conn); +} + +static int db_ldap_connect_finish(struct ldap_connection *conn, int ret) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + const struct sieve_ldap_storage_settings *set = &conn->lstorage->set; + + if (ret == LDAP_SERVER_DOWN) { + e_error(storage->event, "db: " + "Can't connect to server: %s", + set->uris != NULL ? + set->uris : set->hosts); + return -1; + } + if (ret != LDAP_SUCCESS) { + e_error(storage->event, "db: " + "binding failed (dn %s): %s", + set->dn == NULL ? "(none)" : set->dn, + ldap_get_error(conn)); + return -1; + } + + timeout_remove(&conn->to); + conn->conn_state = LDAP_CONN_STATE_BOUND; + e_debug(storage->event, "db: " + "Successfully bound (dn %s)", + set->dn == NULL ? "(none)" : set->dn); + while (db_ldap_request_queue_next(conn)) + ; + return 0; +} + +static void db_ldap_default_bind_finished(struct ldap_connection *conn, + struct db_ldap_result *res) +{ + int ret; + + i_assert(conn->pending_count == 0); + conn->default_bind_msgid = -1; + + ret = ldap_result2error(conn->ld, res->msg, FALSE); + if (db_ldap_connect_finish(conn, ret) < 0) { + /* lost connection, close it */ + db_ldap_conn_close(conn); + } +} + +static void db_ldap_abort_requests(struct ldap_connection *conn, + unsigned int max_count, + unsigned int timeout_secs, + bool error, const char *reason) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + struct ldap_request *const *requestp, *request; + time_t diff; + + while (aqueue_count(conn->request_queue) > 0 && max_count > 0) { + requestp = array_idx(&conn->request_array, + aqueue_idx(conn->request_queue, 0)); + request = *requestp; + + diff = ioloop_time - request->create_time; + if (diff < (time_t)timeout_secs) + break; + + /* timed out, abort */ + aqueue_delete_tail(conn->request_queue); + + if (request->msgid != -1) { + i_assert(conn->pending_count > 0); + conn->pending_count--; + } + if (error) + e_error(storage->event, "db: %s", reason); + else + e_debug(storage->event, "db: %s", reason); + request->callback(conn, request, NULL); + max_count--; + } +} + +static struct ldap_request * +db_ldap_find_request(struct ldap_connection *conn, int msgid, + unsigned int *idx_r) +{ + struct ldap_request *const *requests, *request = NULL; + unsigned int i, count; + + count = aqueue_count(conn->request_queue); + if (count == 0) + return NULL; + + requests = array_idx(&conn->request_array, 0); + for (i = 0; i < count; i++) { + request = requests[aqueue_idx(conn->request_queue, i)]; + if (request->msgid == msgid) { + *idx_r = i; + return request; + } + if (request->msgid == -1) + break; + } + return NULL; +} + +static bool +db_ldap_handle_request_result(struct ldap_connection *conn, + struct ldap_request *request, unsigned int idx, + struct db_ldap_result *res) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + int ret; + bool final_result; + + i_assert(conn->pending_count > 0); + + switch (ldap_msgtype(res->msg)) { + case LDAP_RES_SEARCH_ENTRY: + case LDAP_RES_SEARCH_RESULT: + break; + case LDAP_RES_SEARCH_REFERENCE: + /* we're going to ignore this */ + return FALSE; + default: + e_error(storage->event, "db: Reply with unexpected type %d", + ldap_msgtype(res->msg)); + return TRUE; + } + + if (ldap_msgtype(res->msg) == LDAP_RES_SEARCH_ENTRY) { + ret = LDAP_SUCCESS; + final_result = FALSE; + } else { + final_result = TRUE; + ret = ldap_result2error(conn->ld, res->msg, 0); + } + if (ret != LDAP_SUCCESS) { + /* handle search failures here */ + e_error(storage->event, "db: " + "ldap_search(base=%s filter=%s) failed: %s", + request->base, request->filter, + ldap_err2string(ret)); + res = NULL; + } else { + if (!final_result && storage->svinst->debug) { + e_debug(storage->event, + "db: ldap_search(base=%s filter=%s) returned entry: %s", + request->base, request->filter, + ldap_get_dn(conn->ld, res->msg)); + } + } + if (res == NULL && !final_result) { + /* wait for the final reply */ + request->failed = TRUE; + return TRUE; + } + if (request->failed) + res = NULL; + if (final_result) { + conn->pending_count--; + aqueue_delete(conn->request_queue, idx); + } + + T_BEGIN { + request->callback(conn, request, res == NULL ? NULL : res->msg); + } T_END; + + if (idx > 0) { + /* see if there are timed out requests */ + db_ldap_abort_requests(conn, idx, + DB_LDAP_REQUEST_LOST_TIMEOUT_SECS, + TRUE, "Request lost"); + } + return TRUE; +} + +static void db_ldap_result_unref(struct db_ldap_result **_res) +{ + struct db_ldap_result *res = *_res; + + *_res = NULL; + i_assert(res->refcount > 0); + if (--res->refcount == 0) { + ldap_msgfree(res->msg); + i_free(res); + } +} + +static void +db_ldap_request_free(struct ldap_request *request) +{ + if (request->result != NULL) + db_ldap_result_unref(&request->result); +} + +static void +db_ldap_handle_result(struct ldap_connection *conn, struct db_ldap_result *res) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + struct ldap_request *request; + unsigned int idx; + int msgid; + + msgid = ldap_msgid(res->msg); + if (msgid == conn->default_bind_msgid) { + db_ldap_default_bind_finished(conn, res); + return; + } + + request = db_ldap_find_request(conn, msgid, &idx); + if (request == NULL) { + e_error(storage->event, + "db: Reply with unknown msgid %d", msgid); + return; + } + + if (db_ldap_handle_request_result(conn, request, idx, res)) + db_ldap_request_free(request); +} + +static void ldap_input(struct ldap_connection *conn) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + struct timeval timeout; + struct db_ldap_result *res; + LDAPMessage *msg; + time_t prev_reply_diff; + int ret; + + do { + if (conn->ld == NULL) + return; + + i_zero(&timeout); + ret = ldap_result(conn->ld, LDAP_RES_ANY, 0, &timeout, &msg); +#ifdef OPENLDAP_ASYNC_WORKAROUND + if (ret == 0) { + /* try again, there may be another in buffer */ + ret = ldap_result(conn->ld, LDAP_RES_ANY, 0, + &timeout, &msg); + } +#endif + if (ret <= 0) + break; + + res = i_new(struct db_ldap_result, 1); + res->refcount = 1; + res->msg = msg; + db_ldap_handle_result(conn, res); + db_ldap_result_unref(&res); + } while (conn->io != NULL); + + prev_reply_diff = ioloop_time - conn->last_reply_stamp; + conn->last_reply_stamp = ioloop_time; + + if (ret > 0) { + /* input disabled, continue once it's enabled */ + i_assert(conn->io == NULL); + } else if (ret == 0) { + /* send more requests */ + while (db_ldap_request_queue_next(conn)) + ; + } else if (ldap_get_errno(conn) != LDAP_SERVER_DOWN) { + e_error(storage->event, "db: ldap_result() failed: %s", + ldap_get_error(conn)); + ldap_conn_reconnect(conn); + } else if (aqueue_count(conn->request_queue) > 0 || + prev_reply_diff < DB_LDAP_IDLE_RECONNECT_SECS) { + e_error(storage->event, + "db: Connection lost to LDAP server, reconnecting"); + ldap_conn_reconnect(conn); + } else { + /* server probably disconnected an idle connection. don't + reconnect until the next request comes. */ + db_ldap_conn_close(conn); + } +} + +#ifdef HAVE_LDAP_SASL +static int +sasl_interact(LDAP *ld ATTR_UNUSED, unsigned flags ATTR_UNUSED, + void *defaults, void *interact) +{ + struct db_ldap_sasl_bind_context *context = defaults; + sasl_interact_t *in; + const char *str; + + for (in = interact; in->id != SASL_CB_LIST_END; in++) { + switch (in->id) { + case SASL_CB_GETREALM: + str = context->realm; + break; + case SASL_CB_AUTHNAME: + str = context->authcid; + break; + case SASL_CB_USER: + str = context->authzid; + break; + case SASL_CB_PASS: + str = context->passwd; + break; + default: + str = NULL; + break; + } + if (str != NULL) { + in->len = strlen(str); + in->result = str; + } + + } + return LDAP_SUCCESS; +} +#endif + +static void ldap_connection_timeout(struct ldap_connection *conn) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + i_assert(conn->conn_state == LDAP_CONN_STATE_BINDING); + + e_error(storage->event, "db: Initial binding to LDAP server timed out"); + db_ldap_conn_close(conn); +} + +static int db_ldap_bind(struct ldap_connection *conn) +{ + const struct sieve_ldap_storage_settings *set = &conn->lstorage->set; + int msgid; + + i_assert(conn->conn_state != LDAP_CONN_STATE_BINDING); + i_assert(conn->default_bind_msgid == -1); + i_assert(conn->pending_count == 0); + + msgid = ldap_bind(conn->ld, set->dn, set->dnpass, + LDAP_AUTH_SIMPLE); + if (msgid == -1) { + i_assert(ldap_get_errno(conn) != LDAP_SUCCESS); + if (db_ldap_connect_finish(conn, ldap_get_errno(conn)) < 0) { + /* lost connection, close it */ + db_ldap_conn_close(conn); + } + return -1; + } + + conn->conn_state = LDAP_CONN_STATE_BINDING; + conn->default_bind_msgid = msgid; + + timeout_remove(&conn->to); + conn->to = timeout_add(DB_LDAP_REQUEST_LOST_TIMEOUT_SECS*1000, + ldap_connection_timeout, conn); + return 0; +} + +static int db_ldap_get_fd(struct ldap_connection *conn) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + int ret; + + /* get the connection's fd */ + ret = ldap_get_option(conn->ld, LDAP_OPT_DESC, (void *)&conn->fd); + if (ret != LDAP_SUCCESS) { + e_error(storage->event, "db: Can't get connection fd: %s", + ldap_err2string(ret)); + return -1; + } + if (conn->fd <= STDERR_FILENO) { + /* Solaris LDAP library seems to be broken */ + e_error(storage->event, + "db: Buggy LDAP library returned wrong fd: %d", + conn->fd); + return -1; + } + i_assert(conn->fd != -1); + net_set_nonblock(conn->fd, TRUE); + return 0; +} + +static int +db_ldap_set_opt(struct ldap_connection *conn, int opt, const void *value, + const char *optname, const char *value_str) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + int ret; + + ret = ldap_set_option(conn->ld, opt, value); + if (ret != LDAP_SUCCESS) { + e_error(storage->event, "db: Can't set option %s to %s: %s", + optname, value_str, ldap_err2string(ret)); + return -1; + } + return 0; +} + +static int +db_ldap_set_opt_str(struct ldap_connection *conn, int opt, const char *value, + const char *optname) +{ + if (value != NULL) + return db_ldap_set_opt(conn, opt, value, optname, value); + return 0; +} + +static int db_ldap_set_tls_options(struct ldap_connection *conn) +{ + const struct sieve_ldap_storage_settings *set = &conn->lstorage->set; + + if (!set->tls) + return 0; + +#ifdef OPENLDAP_TLS_OPTIONS + if (db_ldap_set_opt_str(conn, LDAP_OPT_X_TLS_CACERTFILE, + set->tls_ca_cert_file, "tls_ca_cert_file") < 0) + return -1; + if (db_ldap_set_opt_str(conn, LDAP_OPT_X_TLS_CACERTDIR, + set->tls_ca_cert_dir, "tls_ca_cert_dir") < 0) + return -1; + if (db_ldap_set_opt_str(conn, LDAP_OPT_X_TLS_CERTFILE, + set->tls_cert_file, "tls_cert_file") < 0) + return -1; + if (db_ldap_set_opt_str(conn, LDAP_OPT_X_TLS_KEYFILE, + set->tls_key_file, "tls_key_file") < 0) + return -1; + if (db_ldap_set_opt_str(conn, LDAP_OPT_X_TLS_CIPHER_SUITE, + set->tls_cipher_suite, "tls_cipher_suite") < 0) + return -1; + if (set->tls_require_cert != NULL) { + if (db_ldap_set_opt(conn, LDAP_OPT_X_TLS_REQUIRE_CERT, + &set->ldap_tls_require_cert, + "tls_require_cert", set->tls_require_cert) < 0) + return -1; + } +#else + if (set->tls_ca_cert_file != NULL || + set->tls_ca_cert_dir != NULL || + set->tls_cert_file != NULL || + set->tls_key_file != NULL || + set->tls_cipher_suite != NULL) { + e_warning(&conn->lstorage->storage, "db: " + "tls_* settings ignored, " + "your LDAP library doesn't seem to support them"); + } +#endif + return 0; +} + +static int db_ldap_set_options(struct ldap_connection *conn) +{ + const struct sieve_ldap_storage_settings *set = &conn->lstorage->set; + struct sieve_storage *storage = &conn->lstorage->storage; + unsigned int ldap_version; + int value; + + if (db_ldap_set_opt(conn, LDAP_OPT_DEREF, &set->ldap_deref, + "deref", set->deref) < 0) + return -1; +#ifdef LDAP_OPT_DEBUG_LEVEL + if (str_to_int(set->debug_level, &value) >= 0 && value != 0) { + if (db_ldap_set_opt(conn, LDAP_OPT_DEBUG_LEVEL, &value, + "debug_level", set->debug_level) < 0) + return -1; + } +#endif + + if (set->ldap_version < 3) { + if (set->sasl_bind) { + e_error(storage->event, + "db: sasl_bind=yes requires ldap_version=3"); + return -1; + } + if (set->tls) { + e_error(storage->event, + "db: tls=yes requires ldap_version=3"); + return -1; + } + } + + ldap_version = set->ldap_version; + if (db_ldap_set_opt(conn, LDAP_OPT_PROTOCOL_VERSION, &ldap_version, + "protocol_version", dec2str(ldap_version)) < 0) + return -1; + if (db_ldap_set_tls_options(conn) < 0) + return -1; + return 0; +} + +int sieve_ldap_db_connect(struct ldap_connection *conn) +{ + const struct sieve_ldap_storage_settings *set = &conn->lstorage->set; + struct sieve_storage *storage = &conn->lstorage->storage; + struct timeval start, end; + int debug_level; + bool debug; +#if defined(HAVE_LDAP_SASL) || defined(LDAP_HAVE_START_TLS_S) + int ret; +#endif + + if (conn->conn_state != LDAP_CONN_STATE_DISCONNECTED) + return 0; + + debug = FALSE; + if (str_to_int(set->debug_level, &debug_level) >= 0) + debug = debug_level > 0; + + if (debug) + i_gettimeofday(&start); + i_assert(conn->pending_count == 0); + if (conn->ld == NULL) { + if (set->uris != NULL) { +#ifdef LDAP_HAVE_INITIALIZE + if (ldap_initialize(&conn->ld, set->uris) != LDAP_SUCCESS) + conn->ld = NULL; +#else + e_error(storage->event, "db: " + "Your LDAP library doesn't support " + "'uris' setting, use 'hosts' instead."); + return -1; +#endif + } else + conn->ld = ldap_init(set->hosts, LDAP_PORT); + + if (conn->ld == NULL) { + e_error(storage->event, "db: " + "ldap_init() failed with hosts: %s", set->hosts); + return -1; + } + + if (db_ldap_set_options(conn) < 0) + return -1; + } + + if (set->tls) { +#ifdef LDAP_HAVE_START_TLS_S + ret = ldap_start_tls_s(conn->ld, NULL, NULL); + if (ret != LDAP_SUCCESS) { + if (ret == LDAP_OPERATIONS_ERROR && + set->uris != NULL && + str_begins(set->uris, "ldaps:")) { + e_error(storage->event, "db: " + "Don't use both tls=yes and ldaps URI"); + } + e_error(storage->event, "db: " + "ldap_start_tls_s() failed: %s", + ldap_err2string(ret)); + return -1; + } +#else + e_error(storage->event, "db: " + "Your LDAP library doesn't support TLS"); + return -1; +#endif + } + + if (set->sasl_bind) { +#ifdef HAVE_LDAP_SASL + struct db_ldap_sasl_bind_context context; + + i_zero(&context); + context.authcid = set->dn; + context.passwd = set->dnpass; + context.realm = set->sasl_realm; + context.authzid = set->sasl_authz_id; + + /* There doesn't seem to be a way to do SASL binding + asynchronously.. */ + ret = ldap_sasl_interactive_bind_s(conn->ld, NULL, + set->sasl_mech, + NULL, NULL, LDAP_SASL_QUIET, + sasl_interact, &context); + if (db_ldap_connect_finish(conn, ret) < 0) + return -1; +#else + e_error(storage->event, "db: " + "sasl_bind=yes but no SASL support compiled in"); + return -1; +#endif + conn->conn_state = LDAP_CONN_STATE_BOUND; + } else { + if (db_ldap_bind(conn) < 0) + return -1; + } + if (debug) { + i_gettimeofday(&end); + int msecs = timeval_diff_msecs(&end, &start); + e_debug(storage->event, "db: " + "Initialization took %d msecs", msecs); + } + + if (db_ldap_get_fd(conn) < 0) + return -1; + conn->io = io_add(conn->fd, IO_READ, ldap_input, conn); + return 0; +} + +void db_ldap_enable_input(struct ldap_connection *conn, bool enable) +{ + if (!enable) { + io_remove(&conn->io); + } else { + if (conn->io == NULL && conn->fd != -1) { + conn->io = io_add(conn->fd, IO_READ, ldap_input, conn); + ldap_input(conn); + } + } +} + +static void db_ldap_disconnect_timeout(struct ldap_connection *conn) +{ + db_ldap_abort_requests(conn, UINT_MAX, + DB_LDAP_REQUEST_DISCONNECT_TIMEOUT_SECS, FALSE, + "Aborting (timeout), we're not connected to LDAP server"); + + if (aqueue_count(conn->request_queue) == 0) { + /* no requests left, remove this timeout handler */ + timeout_remove(&conn->to); + } +} + +static void db_ldap_conn_close(struct ldap_connection *conn) +{ + struct ldap_request *const *requests, *request; + unsigned int i; + + conn->conn_state = LDAP_CONN_STATE_DISCONNECTED; + conn->default_bind_msgid = -1; + + timeout_remove(&conn->to); + + if (conn->pending_count != 0) { + requests = array_idx(&conn->request_array, 0); + for (i = 0; i < conn->pending_count; i++) { + request = requests[aqueue_idx(conn->request_queue, i)]; + + i_assert(request->msgid != -1); + request->msgid = -1; + } + conn->pending_count = 0; + } + + if (conn->ld != NULL) { + ldap_unbind(conn->ld); + conn->ld = NULL; + } + conn->fd = -1; + + /* the fd may have already been closed before ldap_unbind(), + so we'll have to use io_remove_closed(). */ + io_remove_closed(&conn->io); + + if (aqueue_count(conn->request_queue) > 0) { + conn->to = timeout_add(DB_LDAP_REQUEST_DISCONNECT_TIMEOUT_SECS * + 1000/2, db_ldap_disconnect_timeout, conn); + } +} + +struct ldap_field_find_context { + ARRAY_TYPE(string) attr_names; + pool_t pool; +}; + +#define IS_LDAP_ESCAPED_CHAR(c) \ + ((c) == '*' || (c) == '(' || (c) == ')' || (c) == '\\') + +const char *ldap_escape(const char *str) +{ + const char *p; + string_t *ret; + + for (p = str; *p != '\0'; p++) { + if (IS_LDAP_ESCAPED_CHAR(*p)) + break; + } + + if (*p == '\0') + return str; + + ret = t_str_new((size_t) (p - str) + 64); + str_append_data(ret, str, (size_t) (p - str)); + + for (; *p != '\0'; p++) { + if (IS_LDAP_ESCAPED_CHAR(*p)) + str_append_c(ret, '\\'); + str_append_c(ret, *p); + } + return str_c(ret); +} + +struct ldap_connection * +sieve_ldap_db_init(struct sieve_ldap_storage *lstorage) +{ + struct ldap_connection *conn; + pool_t pool; + + pool = pool_alloconly_create("ldap_connection", 1024); + conn = p_new(pool, struct ldap_connection, 1); + conn->pool = pool; + conn->refcount = 1; + conn->lstorage = lstorage; + + conn->conn_state = LDAP_CONN_STATE_DISCONNECTED; + conn->default_bind_msgid = -1; + conn->fd = -1; + + i_array_init(&conn->request_array, 512); + conn->request_queue = aqueue_init(&conn->request_array.arr); + + conn->next = ldap_connections; + ldap_connections = conn; + return conn; +} + +void sieve_ldap_db_unref(struct ldap_connection **_conn) +{ + struct ldap_connection *conn = *_conn; + struct ldap_connection **p; + + *_conn = NULL; + i_assert(conn->refcount >= 0); + if (--conn->refcount > 0) + return; + + for (p = &ldap_connections; *p != NULL; p = &(*p)->next) { + if (*p == conn) { + *p = conn->next; + break; + } + } + + db_ldap_abort_requests(conn, UINT_MAX, 0, FALSE, "Shutting down"); + i_assert(conn->pending_count == 0); + db_ldap_conn_close(conn); + i_assert(conn->to == NULL); + + array_free(&conn->request_array); + aqueue_deinit(&conn->request_queue); + + pool_unref(&conn->pool); +} + +static void db_ldap_switch_ioloop(struct ldap_connection *conn) +{ + if (conn->to != NULL) + conn->to = io_loop_move_timeout(&conn->to); + if (conn->io != NULL) + conn->io = io_loop_move_io(&conn->io); +} + +static void db_ldap_wait(struct ldap_connection *conn) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + struct ioloop *prev_ioloop = current_ioloop; + + i_assert(conn->ioloop == NULL); + + if (aqueue_count(conn->request_queue) == 0) + return; + + conn->ioloop = io_loop_create(); + db_ldap_switch_ioloop(conn); + /* either we're waiting for network I/O or we're getting out of a + callback using timeout_add_short(0) */ + i_assert(io_loop_have_ios(conn->ioloop) || + io_loop_have_immediate_timeouts(conn->ioloop)); + + do { + e_debug(storage->event, "db: " + "Waiting for %d requests to finish", + aqueue_count(conn->request_queue) ); + io_loop_run(conn->ioloop); + } while (aqueue_count(conn->request_queue) > 0); + + e_debug(storage->event, "db: All requests finished"); + + current_ioloop = prev_ioloop; + db_ldap_switch_ioloop(conn); + current_ioloop = conn->ioloop; + io_loop_destroy(&conn->ioloop); +} + +static void sieve_ldap_db_script_free(unsigned char *script) +{ + i_free(script); +} + +static int +sieve_ldap_db_get_script_modattr(struct ldap_connection *conn, + LDAPMessage *entry, pool_t pool, const char **modattr_r) +{ + const struct sieve_ldap_storage_settings *set = &conn->lstorage->set; + struct sieve_storage *storage = &conn->lstorage->storage; + char *attr, **vals; + BerElement *ber; + + *modattr_r = NULL; + + attr = ldap_first_attribute(conn->ld, entry, &ber); + while (attr != NULL) { + if (strcmp(attr, set->sieve_ldap_mod_attr) == 0) { + vals = ldap_get_values(conn->ld, entry, attr); + if (vals == NULL || vals[0] == NULL) + return 0; + + if (vals[1] != NULL) { + e_warning(storage->event, "db: " + "Search returned more than one Sieve modified attribute `%s'; " + "using only the first one.", set->sieve_ldap_mod_attr); + } + + *modattr_r = p_strdup(pool, vals[0]); + + ldap_value_free(vals); + ldap_memfree(attr); + return 1; + } + ldap_memfree(attr); + attr = ldap_next_attribute(conn->ld, entry, ber); + } + ber_free(ber, 0); + + return 0; +} + +static int +sieve_ldap_db_get_script(struct ldap_connection *conn, + LDAPMessage *entry, struct istream **script_r) +{ + const struct sieve_ldap_storage_settings *set = &conn->lstorage->set; + struct sieve_storage *storage = &conn->lstorage->storage; + char *attr; + unsigned char *data; + size_t size; + struct berval **vals; + BerElement *ber; + + attr = ldap_first_attribute(conn->ld, entry, &ber); + while (attr != NULL) { + if (strcmp(attr, set->sieve_ldap_script_attr) == 0) { + vals = ldap_get_values_len(conn->ld, entry, attr); + if (vals == NULL || vals[0] == NULL) + return 0; + + if (vals[1] != NULL) { + e_warning(storage->event, "db: " + "Search returned more than one Sieve script attribute `%s'; " + "using only the first one.", set->sieve_ldap_script_attr); + } + + size = vals[0]->bv_len; + data = i_malloc(size); + + e_debug(storage->event, "db: " + "Found script with length %zu", size); + + memcpy(data, vals[0]->bv_val, size); + + ldap_value_free_len(vals); + ldap_memfree(attr); + + *script_r = i_stream_create_from_data(data, size); + i_stream_add_destroy_callback + (*script_r, sieve_ldap_db_script_free, data); + return 1; + } + ldap_memfree(attr); + attr = ldap_next_attribute(conn->ld, entry, ber); + } + ber_free(ber, 0); + + return 0; +} + +const struct var_expand_table +auth_request_var_expand_static_tab[] = { + { 'u', NULL, "user" }, + { 'n', NULL, "username" }, + { 'd', NULL, "domain" }, + { 'h', NULL, "home" }, + { '\0', NULL, "name" }, + { '\0', NULL, NULL } +}; + +static const struct var_expand_table * +db_ldap_get_var_expand_table(struct ldap_connection *conn, + const char *name) +{ + struct sieve_ldap_storage *lstorage = conn->lstorage; + struct sieve_instance *svinst = lstorage->storage.svinst; + const unsigned int auth_count = + N_ELEMENTS(auth_request_var_expand_static_tab); + struct var_expand_table *tab; + + /* keep the extra fields at the beginning. the last static_tab field + contains the ending NULL-fields. */ + tab = t_malloc_no0((auth_count) * sizeof(*tab)); + + memcpy(tab, auth_request_var_expand_static_tab, + auth_count * sizeof(*tab)); + + tab[0].value = ldap_escape(lstorage->username); + tab[1].value = ldap_escape(t_strcut(lstorage->username, '@')); + tab[2].value = strchr(lstorage->username, '@'); + if (tab[2].value != NULL) + tab[2].value = ldap_escape(tab[2].value+1); + tab[3].value = ldap_escape(svinst->home_dir); + tab[4].value = ldap_escape(name); + return tab; +} + +struct sieve_ldap_script_lookup_request { + struct ldap_request request; + + unsigned int entries; + const char *result_dn; + const char *result_modattr; +}; + +static void +sieve_ldap_lookup_script_callback(struct ldap_connection *conn, + struct ldap_request *request, LDAPMessage *res) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + struct sieve_ldap_script_lookup_request *srequest = + (struct sieve_ldap_script_lookup_request *)request; + + if (res == NULL) { + io_loop_stop(conn->ioloop); + return; + } + + if (ldap_msgtype(res) != LDAP_RES_SEARCH_RESULT) { + if (srequest->result_dn == NULL) { + srequest->result_dn = p_strdup + (request->pool, ldap_get_dn(conn->ld, res)); + (void)sieve_ldap_db_get_script_modattr + (conn, res, request->pool, &srequest->result_modattr); + } else if (srequest->entries++ == 0) { + e_warning(storage->event, "db: " + "Search returned more than one entry for Sieve script; " + "using only the first one."); + } + } else { + io_loop_stop(conn->ioloop); + return; + } +} + +int sieve_ldap_db_lookup_script(struct ldap_connection *conn, + const char *name, const char **dn_r, const char **modattr_r) +{ + struct sieve_ldap_storage *lstorage = conn->lstorage; + struct sieve_storage *storage = &lstorage->storage; + const struct sieve_ldap_storage_settings *set = &lstorage->set; + struct sieve_ldap_script_lookup_request *request; + const struct var_expand_table *tab; + char **attr_names; + const char *error; + string_t *str; + + pool_t pool = pool_alloconly_create + ("sieve_ldap_script_lookup_request", 512); + request = p_new(pool, struct sieve_ldap_script_lookup_request, 1); + request->request.pool = pool; + + tab = db_ldap_get_var_expand_table(conn, name); + + str = t_str_new(512); + if (var_expand(str, set->base, tab, &error) <= 0) { + e_error(storage->event, "db: " + "Failed to expand base=%s: %s", + set->base, error); + return -1; + } + request->request.base = p_strdup(pool, str_c(str)); + + attr_names = p_new(pool, char *, 3); + attr_names[0] = p_strdup(pool, set->sieve_ldap_mod_attr); + + str_truncate(str, 0); + if (var_expand(str, set->sieve_ldap_filter, tab, &error) <= 0) { + e_error(storage->event, "db: " + "Failed to expand sieve_ldap_filter=%s: %s", + set->sieve_ldap_filter, error); + return -1; + } + + request->request.scope = lstorage->set.ldap_scope; + request->request.filter = p_strdup(pool, str_c(str)); + request->request.attributes = attr_names; + + e_debug(storage->event, "base=%s scope=%s filter=%s fields=%s", + request->request.base, lstorage->set.scope, + request->request.filter, + t_strarray_join((const char **)attr_names, ",")); + + request->request.callback = sieve_ldap_lookup_script_callback; + db_ldap_request(conn, &request->request); + db_ldap_wait(conn); + + *dn_r = t_strdup(request->result_dn); + *modattr_r = t_strdup(request->result_modattr); + pool_unref(&request->request.pool); + return (*dn_r == NULL ? 0 : 1); +} + +struct sieve_ldap_script_read_request { + struct ldap_request request; + + unsigned int entries; + struct istream *result; +}; + +static void +sieve_ldap_read_script_callback(struct ldap_connection *conn, + struct ldap_request *request, LDAPMessage *res) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + struct sieve_ldap_script_read_request *srequest = + (struct sieve_ldap_script_read_request *)request; + + if (res == NULL) { + io_loop_stop(conn->ioloop); + return; + } + + if (ldap_msgtype(res) != LDAP_RES_SEARCH_RESULT) { + + if (srequest->result == NULL) { + (void)sieve_ldap_db_get_script(conn, res, &srequest->result); + } else { + e_error(storage->event, "db: " + "Search returned more than one entry for Sieve script DN"); + i_stream_unref(&srequest->result); + } + + } else { + io_loop_stop(conn->ioloop); + return; + } +} + +int sieve_ldap_db_read_script(struct ldap_connection *conn, + const char *dn, struct istream **script_r) +{ + struct sieve_ldap_storage *lstorage = conn->lstorage; + struct sieve_storage *storage = &lstorage->storage; + const struct sieve_ldap_storage_settings *set = &lstorage->set; + struct sieve_ldap_script_read_request *request; + char **attr_names; + + pool_t pool = pool_alloconly_create + ("sieve_ldap_script_read_request", 512); + request = p_new(pool, struct sieve_ldap_script_read_request, 1); + request->request.pool = pool; + request->request.base = p_strdup(pool, dn); + + attr_names = p_new(pool, char *, 3); + attr_names[0] = p_strdup(pool, set->sieve_ldap_script_attr); + + request->request.scope = LDAP_SCOPE_BASE; + request->request.filter = "(objectClass=*)"; + request->request.attributes = attr_names; + + e_debug(storage->event, "base=%s scope=base filter=%s fields=%s", + request->request.base, request->request.filter, + t_strarray_join((const char **)attr_names, ",")); + + request->request.callback = sieve_ldap_read_script_callback; + db_ldap_request(conn, &request->request); + db_ldap_wait(conn); + + *script_r = request->result; + pool_unref(&request->request.pool); + return (*script_r == NULL ? 0 : 1); +} + + +#endif diff --git a/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-db.h b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-db.h new file mode 100644 index 0000000..d213026 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-db.h @@ -0,0 +1,140 @@ +#ifndef DB_LDAP_H +#define DB_LDAP_H + +/* Functions like ldap_bind() have been deprecated in OpenLDAP 2.3 + This define enables them until the code here can be refactored */ +#define LDAP_DEPRECATED 1 + +/* Maximum number of pending requests before delaying new requests. */ +#define DB_LDAP_MAX_PENDING_REQUESTS 8 +/* If LDAP connection is down, fail requests after waiting for this long. */ +#define DB_LDAP_REQUEST_DISCONNECT_TIMEOUT_SECS 4 +/* If request is still in queue after this many seconds and other requests + have been replied, assume the request was lost and abort it. */ +#define DB_LDAP_REQUEST_LOST_TIMEOUT_SECS 60 +/* If server disconnects us, don't reconnect if no requests have been sent + for this many seconds. */ +#define DB_LDAP_IDLE_RECONNECT_SECS 60 + +#include <ldap.h> + +#define HAVE_LDAP_SASL +#ifdef HAVE_SASL_SASL_H +# include <sasl/sasl.h> +#elif defined (HAVE_SASL_H) +# include <sasl.h> +#else +# undef HAVE_LDAP_SASL +#endif +#ifdef LDAP_OPT_X_TLS +# define OPENLDAP_TLS_OPTIONS +#endif +#if !defined(SASL_VERSION_MAJOR) || SASL_VERSION_MAJOR < 2 +# undef HAVE_LDAP_SASL +#endif + +#ifndef LDAP_SASL_QUIET +# define LDAP_SASL_QUIET 0 /* Doesn't exist in Solaris LDAP */ +#endif + +/* Older versions may require calling ldap_result() twice */ +#if LDAP_VENDOR_VERSION <= 20112 +# define OPENLDAP_ASYNC_WORKAROUND +#endif + +/* Solaris LDAP library doesn't have LDAP_OPT_SUCCESS */ +#ifndef LDAP_OPT_SUCCESS +# define LDAP_OPT_SUCCESS LDAP_SUCCESS +#endif + +struct ldap_connection; +struct ldap_request; + +typedef void db_search_callback_t(struct ldap_connection *conn, + struct ldap_request *request, + LDAPMessage *res); +struct ldap_request { + pool_t pool; + + /* msgid for sent requests, -1 if not sent */ + int msgid; + /* timestamp when request was created */ + time_t create_time; + + bool failed; + + db_search_callback_t *callback; + + const char *base; + const char *filter; + int scope; + char **attributes; + + struct db_ldap_result *result; +}; + +enum ldap_connection_state { + /* Not connected */ + LDAP_CONN_STATE_DISCONNECTED, + /* Binding - either to default dn or doing auth bind */ + LDAP_CONN_STATE_BINDING, + /* Bound */ + LDAP_CONN_STATE_BOUND +}; + +struct ldap_connection { + struct ldap_connection *next; + + struct sieve_ldap_storage *lstorage; + + pool_t pool; + int refcount; + + LDAP *ld; + enum ldap_connection_state conn_state; + int default_bind_msgid; + + int fd; + struct io *io; + struct timeout *to; + struct ioloop *ioloop; + + /* Request queue contains sent requests at tail (msgid != -1) and + queued requests at head (msgid == -1). */ + struct aqueue *request_queue; + ARRAY(struct ldap_request *) request_array; + /* Number of messages in queue with msgid != -1 */ + unsigned int pending_count; + + /* Timestamp when we last received a reply */ + time_t last_reply_stamp; +}; + + +int ldap_deref_from_str(const char *str, int *deref_r); +int ldap_scope_from_str(const char *str, int *scope_r); +#ifdef OPENLDAP_TLS_OPTIONS +int ldap_tls_require_cert_from_str(const char *str, int *opt_x_tls_r); +#endif + +/* Send/queue request */ +void db_ldap_request(struct ldap_connection *conn, + struct ldap_request *request); + +void db_ldap_enable_input(struct ldap_connection *conn, bool enable); + +const char *ldap_escape(const char *str); +const char *ldap_get_error(struct ldap_connection *conn); + +int sieve_ldap_db_connect(struct ldap_connection *conn); + +struct ldap_connection * +sieve_ldap_db_init(struct sieve_ldap_storage *lstorage); +void sieve_ldap_db_unref(struct ldap_connection **conn); + +int sieve_ldap_db_lookup_script(struct ldap_connection *conn, + const char *name, const char **dn_r, const char **modattr_r); +int sieve_ldap_db_read_script(struct ldap_connection *conn, + const char *dn, struct istream **script_r); + +#endif diff --git a/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-script.c b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-script.c new file mode 100644 index 0000000..1c732db --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-script.c @@ -0,0 +1,369 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "time-util.h" +#include "istream.h" + +#include "sieve-ldap-storage.h" + +#if defined(SIEVE_BUILTIN_LDAP) || defined(PLUGIN_BUILD) + +#include "str.h" +#include "strfuncs.h" + +#include "sieve-error.h" +#include "sieve-dump.h" +#include "sieve-binary.h" + +/* + * Script file implementation + */ + +static struct sieve_ldap_script *sieve_ldap_script_alloc(void) +{ + struct sieve_ldap_script *lscript; + pool_t pool; + + pool = pool_alloconly_create("sieve_ldap_script", 1024); + lscript = p_new(pool, struct sieve_ldap_script, 1); + lscript->script = sieve_ldap_script; + lscript->script.pool = pool; + + return lscript; +} + +struct sieve_ldap_script *sieve_ldap_script_init +(struct sieve_ldap_storage *lstorage, const char *name) +{ + struct sieve_storage *storage = &lstorage->storage; + struct sieve_ldap_script *lscript = NULL; + const char *location; + + if ( name == NULL ) { + name = SIEVE_LDAP_SCRIPT_DEFAULT; + location = storage->location; + } else { + location = t_strconcat + (storage->location, ";name=", name, NULL); + } + + lscript = sieve_ldap_script_alloc(); + sieve_script_init(&lscript->script, + storage, &sieve_ldap_script, location, name); + return lscript; +} + +static int sieve_ldap_script_open +(struct sieve_script *script, enum sieve_error *error_r) +{ + struct sieve_ldap_script *lscript = + (struct sieve_ldap_script *)script; + struct sieve_storage *storage = script->storage; + struct sieve_ldap_storage *lstorage = + (struct sieve_ldap_storage *)storage; + int ret; + + if ( sieve_ldap_db_connect(lstorage->conn) < 0 ) { + sieve_storage_set_critical(storage, + "Failed to connect to LDAP database"); + *error_r = storage->error_code; + return -1; + } + + if ( (ret=sieve_ldap_db_lookup_script(lstorage->conn, + script->name, &lscript->dn, &lscript->modattr)) <= 0 ) { + if ( ret == 0 ) { + e_debug(script->event, "Script entry not found"); + sieve_script_set_error(script, + SIEVE_ERROR_NOT_FOUND, + "Sieve script not found"); + } else { + sieve_script_set_internal_error(script); + } + *error_r = script->storage->error_code; + return -1; + } + + return 0; +} + +static int sieve_ldap_script_get_stream +(struct sieve_script *script, struct istream **stream_r, + enum sieve_error *error_r) +{ + struct sieve_ldap_script *lscript = + (struct sieve_ldap_script *)script; + struct sieve_storage *storage = script->storage; + struct sieve_ldap_storage *lstorage = + (struct sieve_ldap_storage *)storage; + int ret; + + i_assert(lscript->dn != NULL); + + if ( (ret=sieve_ldap_db_read_script( + lstorage->conn, lscript->dn, stream_r)) <= 0 ) { + if ( ret == 0 ) { + e_debug(script->event, "Script attribute not found"); + sieve_script_set_error(script, + SIEVE_ERROR_NOT_FOUND, + "Sieve script not found"); + } else { + sieve_script_set_internal_error(script); + } + *error_r = script->storage->error_code; + return -1; + } + return 0; +} + +static int sieve_ldap_script_binary_read_metadata +(struct sieve_script *script, struct sieve_binary_block *sblock, + sieve_size_t *offset) +{ + struct sieve_ldap_script *lscript = + (struct sieve_ldap_script *)script; + struct sieve_instance *svinst = script->storage->svinst; + struct sieve_ldap_storage *lstorage = + (struct sieve_ldap_storage *)script->storage; + struct sieve_binary *sbin = + sieve_binary_block_get_binary(sblock); + time_t bmtime = sieve_binary_mtime(sbin); + string_t *dn, *modattr; + + /* config file changed? */ + if ( bmtime <= lstorage->set_mtime ) { + if ( svinst->debug ) { + e_debug(script->event, + "Sieve binary `%s' is not newer " + "than the LDAP configuration `%s' (%s <= %s)", + sieve_binary_path(sbin), lstorage->config_file, + t_strflocaltime("%Y-%m-%d %H:%M:%S", bmtime), + t_strflocaltime("%Y-%m-%d %H:%M:%S", lstorage->set_mtime)); + } + return 0; + } + + /* open script if not open already */ + if ( lscript->dn == NULL && + sieve_script_open(script, NULL) < 0 ) + return 0; + + /* if modattr not found, recompile always */ + if ( lscript->modattr == NULL || *lscript->modattr == '\0' ) { + e_error(script->event, + "LDAP entry for script `%s' " + "has no modified attribute `%s'", + sieve_script_location(script), + lstorage->set.sieve_ldap_mod_attr); + return 0; + } + + /* compare DN in binary and from search result */ + if ( !sieve_binary_read_string(sblock, offset, &dn) ) { + e_error(script->event, + "Binary `%s' has invalid metadata for script `%s': " + "Invalid DN", + sieve_binary_path(sbin), sieve_script_location(script)); + return -1; + } + i_assert( lscript->dn != NULL ); + if ( strcmp(str_c(dn), lscript->dn) != 0 ) { + e_debug(script->event, + "Binary `%s' reports different LDAP DN for script `%s' " + "(`%s' rather than `%s')", + sieve_binary_path(sbin), sieve_script_location(script), + str_c(dn), lscript->dn); + return 0; + } + + /* compare modattr in binary and from search result */ + if ( !sieve_binary_read_string(sblock, offset, &modattr) ) { + e_error(script->event, + "Binary `%s' has invalid metadata for script `%s': " + "Invalid modified attribute", + sieve_binary_path(sbin), sieve_script_location(script)); + return -1; + } + if ( strcmp(str_c(modattr), lscript->modattr) != 0 ) { + e_debug(script->event, + "Binary `%s' reports different modified attribute content " + "for script `%s' (`%s' rather than `%s')", + sieve_binary_path(sbin), sieve_script_location(script), + str_c(modattr), lscript->modattr); + return 0; + } + return 1; +} + +static void sieve_ldap_script_binary_write_metadata +(struct sieve_script *script, struct sieve_binary_block *sblock) +{ + struct sieve_ldap_script *lscript = + (struct sieve_ldap_script *)script; + + sieve_binary_emit_cstring(sblock, lscript->dn); + if (lscript->modattr == NULL) + sieve_binary_emit_cstring(sblock, ""); + else + sieve_binary_emit_cstring(sblock, lscript->modattr); +} + +static bool sieve_ldap_script_binary_dump_metadata +(struct sieve_script *script ATTR_UNUSED, struct sieve_dumptime_env *denv, + struct sieve_binary_block *sblock, sieve_size_t *offset) +{ + string_t *dn, *modattr; + + if ( !sieve_binary_read_string(sblock, offset, &dn) ) + return FALSE; + sieve_binary_dumpf(denv, "ldap.dn = %s\n", str_c(dn)); + + if ( !sieve_binary_read_string(sblock, offset, &modattr) ) + return FALSE; + sieve_binary_dumpf(denv, "ldap.mod_attr = %s\n", str_c(modattr)); + + return TRUE; +} + +static const char *sieve_ldap_script_get_binpath +(struct sieve_ldap_script *lscript) +{ + struct sieve_script *script = &lscript->script; + struct sieve_storage *storage = script->storage; + + if ( lscript->binpath == NULL ) { + if ( storage->bin_dir == NULL ) + return NULL; + lscript->binpath = p_strconcat(script->pool, + storage->bin_dir, "/", + sieve_binfile_from_name(script->name), NULL); + } + + return lscript->binpath; +} + +static struct sieve_binary *sieve_ldap_script_binary_load +(struct sieve_script *script, enum sieve_error *error_r) +{ + struct sieve_storage *storage = script->storage; + struct sieve_ldap_script *lscript = + (struct sieve_ldap_script *)script; + + if ( sieve_ldap_script_get_binpath(lscript) == NULL ) + return NULL; + + return sieve_binary_open(storage->svinst, + lscript->binpath, script, error_r); +} + +static int sieve_ldap_script_binary_save +(struct sieve_script *script, struct sieve_binary *sbin, bool update, + enum sieve_error *error_r) +{ + struct sieve_ldap_script *lscript = + (struct sieve_ldap_script *)script; + + if ( sieve_ldap_script_get_binpath(lscript) == NULL ) + return 0; + + if ( sieve_storage_setup_bindir(script->storage, 0700) < 0 ) + return -1; + + return sieve_binary_save + (sbin, lscript->binpath, update, 0600, error_r); +} + +static bool sieve_ldap_script_equals +(const struct sieve_script *script, const struct sieve_script *other) +{ + struct sieve_storage *storage = script->storage; + struct sieve_storage *sother = other->storage; + + if ( strcmp(storage->location, sother->location) != 0 ) + return FALSE; + + i_assert( script->name != NULL && other->name != NULL ); + + return ( strcmp(script->name, other->name) == 0 ); +} + +const struct sieve_script sieve_ldap_script = { + .driver_name = SIEVE_LDAP_STORAGE_DRIVER_NAME, + .v = { + .open = sieve_ldap_script_open, + + .get_stream = sieve_ldap_script_get_stream, + + .binary_read_metadata = sieve_ldap_script_binary_read_metadata, + .binary_write_metadata = sieve_ldap_script_binary_write_metadata, + .binary_dump_metadata = sieve_ldap_script_binary_dump_metadata, + .binary_load = sieve_ldap_script_binary_load, + .binary_save = sieve_ldap_script_binary_save, + + .equals = sieve_ldap_script_equals + } +}; + +/* + * Script sequence + */ + +struct sieve_ldap_script_sequence { + struct sieve_script_sequence seq; + + bool done:1; +}; + +struct sieve_script_sequence *sieve_ldap_storage_get_script_sequence +(struct sieve_storage *storage, enum sieve_error *error_r) +{ + struct sieve_ldap_script_sequence *lsec = NULL; + + if ( error_r != NULL ) + *error_r = SIEVE_ERROR_NONE; + + /* Create sequence object */ + lsec = i_new(struct sieve_ldap_script_sequence, 1); + sieve_script_sequence_init(&lsec->seq, storage); + + return &lsec->seq; +} + +struct sieve_script *sieve_ldap_script_sequence_next +(struct sieve_script_sequence *seq, enum sieve_error *error_r) +{ + struct sieve_ldap_script_sequence *lsec = + (struct sieve_ldap_script_sequence *)seq; + struct sieve_ldap_storage *lstorage = + (struct sieve_ldap_storage *)seq->storage; + struct sieve_ldap_script *lscript; + + if ( error_r != NULL ) + *error_r = SIEVE_ERROR_NONE; + + if ( lsec->done ) + return NULL; + lsec->done = TRUE; + + lscript = sieve_ldap_script_init + (lstorage, seq->storage->script_name); + if ( sieve_script_open(&lscript->script, error_r) < 0 ) { + struct sieve_script *script = &lscript->script; + sieve_script_unref(&script); + return NULL; + } + + return &lscript->script; +} + +void sieve_ldap_script_sequence_destroy +(struct sieve_script_sequence *seq) +{ + struct sieve_ldap_script_sequence *lsec = + (struct sieve_ldap_script_sequence *)seq; + i_free(lsec); +} + + +#endif diff --git a/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage-settings.c b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage-settings.c new file mode 100644 index 0000000..35fe5cb --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage-settings.c @@ -0,0 +1,169 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "env-util.h" +#include "settings.h" + +#include "sieve-common.h" + +#include "sieve-ldap-storage.h" + +#if defined(SIEVE_BUILTIN_LDAP) || defined(PLUGIN_BUILD) + +#include "sieve-error.h" + +#include "sieve-ldap-db.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#define DEF_STR(name) DEF_STRUCT_STR(name, sieve_ldap_storage_settings) +#define DEF_INT(name) DEF_STRUCT_INT(name, sieve_ldap_storage_settings) +#define DEF_BOOL(name) DEF_STRUCT_BOOL(name, sieve_ldap_storage_settings) + +static struct setting_def setting_defs[] = { + DEF_STR(hosts), + DEF_STR(uris), + DEF_STR(dn), + DEF_STR(dnpass), + DEF_BOOL(tls), + DEF_BOOL(sasl_bind), + DEF_STR(sasl_mech), + DEF_STR(sasl_realm), + DEF_STR(sasl_authz_id), + DEF_STR(tls_ca_cert_file), + DEF_STR(tls_ca_cert_dir), + DEF_STR(tls_cert_file), + DEF_STR(tls_key_file), + DEF_STR(tls_cipher_suite), + DEF_STR(tls_require_cert), + DEF_STR(deref), + DEF_STR(scope), + DEF_STR(base), + DEF_INT(ldap_version), + DEF_STR(debug_level), + DEF_STR(ldaprc_path), + DEF_STR(sieve_ldap_script_attr), + DEF_STR(sieve_ldap_mod_attr), + DEF_STR(sieve_ldap_filter), + + { 0, NULL, 0 } +}; + +static struct sieve_ldap_storage_settings default_settings = { + .hosts = NULL, + .uris = NULL, + .dn = NULL, + .dnpass = NULL, + .tls = FALSE, + .sasl_bind = FALSE, + .sasl_mech = NULL, + .sasl_realm = NULL, + .sasl_authz_id = NULL, + .tls_ca_cert_file = NULL, + .tls_ca_cert_dir = NULL, + .tls_cert_file = NULL, + .tls_key_file = NULL, + .tls_cipher_suite = NULL, + .tls_require_cert = NULL, + .deref = "never", + .scope = "subtree", + .base = NULL, + .ldap_version = 3, + .debug_level = "0", + .ldaprc_path = "", + .sieve_ldap_script_attr = "mailSieveRuleSource", + .sieve_ldap_mod_attr = "modifyTimestamp", + .sieve_ldap_filter = "(&(objectClass=posixAccount)(uid=%u))", +}; + +static const char *parse_setting(const char *key, const char *value, + struct sieve_ldap_storage *lstorage) +{ + return parse_setting_from_defs + (lstorage->storage.pool, setting_defs, &lstorage->set, key, value); +} + +int sieve_ldap_storage_read_settings +(struct sieve_ldap_storage *lstorage, const char *config_path) +{ + struct sieve_storage *storage = &lstorage->storage; + const char *str, *error; + struct stat st; + + if ( stat(config_path, &st) < 0 ) { + e_error(storage->event, + "Failed to read LDAP storage config: " + "stat(%s) failed: %m", config_path); + return -1; + } + + lstorage->set = default_settings; + lstorage->set_mtime = st.st_mtime; + + if (!settings_read_nosection + (config_path, parse_setting, lstorage, &error)) { + sieve_storage_set_critical(storage, + "Failed to read LDAP storage config `%s': %s", + config_path, error); + return -1; + } + + if (lstorage->set.base == NULL) { + sieve_storage_set_critical(storage, + "Invalid LDAP storage config `%s': " + "No search base given", config_path); + return -1; + } + + if (lstorage->set.uris == NULL && lstorage->set.hosts == NULL) { + sieve_storage_set_critical(storage, + "Invalid LDAP storage config `%s': " + "No uris or hosts set", config_path); + return -1; + } + + if (*lstorage->set.ldaprc_path != '\0') { + str = getenv("LDAPRC"); + if (str != NULL && strcmp(str, lstorage->set.ldaprc_path) != 0) { + sieve_storage_set_critical(storage, + "Invalid LDAP storage config `%s': " + "Multiple different ldaprc_path settings not allowed " + "(%s and %s)", config_path, str, lstorage->set.ldaprc_path); + return -1; + } + env_put("LDAPRC", lstorage->set.ldaprc_path); + } + + if ( ldap_deref_from_str + (lstorage->set.deref, &lstorage->set.ldap_deref) < 0 ) { + sieve_storage_set_critical(storage, + "Invalid LDAP storage config `%s': " + "Invalid deref option `%s'", + config_path, lstorage->set.deref);; + } + + if ( ldap_scope_from_str + (lstorage->set.scope, &lstorage->set.ldap_scope) < 0 ) { + sieve_storage_set_critical(storage, + "Invalid LDAP storage config `%s': " + "Invalid scope option `%s'", + config_path, lstorage->set.scope);; + } + +#ifdef OPENLDAP_TLS_OPTIONS + if ( lstorage->set.tls_require_cert != NULL && + ldap_tls_require_cert_from_str(lstorage->set.tls_require_cert, + &lstorage->set.ldap_tls_require_cert) < 0) { + sieve_storage_set_critical(storage, + "Invalid LDAP storage config `%s': " + "Invalid tls_require_cert option `%s'", + config_path, lstorage->set.tls_require_cert); + } +#endif + return 0; +} + +#endif diff --git a/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage.c b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage.c new file mode 100644 index 0000000..1f7922a --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage.c @@ -0,0 +1,230 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +//#include "ldap.h" + +#include "sieve-common.h" + +#include "sieve-ldap-storage.h" + +#if defined(SIEVE_BUILTIN_LDAP) || defined(PLUGIN_BUILD) + +#include "sieve-error.h" + +#ifndef PLUGIN_BUILD +const struct sieve_storage sieve_ldap_storage; +#else +const struct sieve_storage sieve_ldap_storage_plugin; +#endif + +/* + * Storage class + */ + +static struct sieve_storage *sieve_ldap_storage_alloc(void) +{ + struct sieve_ldap_storage *lstorage; + pool_t pool; + + pool = pool_alloconly_create("sieve_ldap_storage", 1024); + lstorage = p_new(pool, struct sieve_ldap_storage, 1); +#ifndef PLUGIN_BUILD + lstorage->storage = sieve_ldap_storage; +#else + lstorage->storage = sieve_ldap_storage_plugin; +#endif + lstorage->storage.pool = pool; + + return &lstorage->storage; +} + +static int sieve_ldap_storage_init +(struct sieve_storage *storage, const char *const *options, + enum sieve_error *error_r) +{ + struct sieve_ldap_storage *lstorage = + (struct sieve_ldap_storage *)storage; + struct sieve_instance *svinst = storage->svinst; + const char *username = NULL; + + if ( options != NULL ) { + while ( *options != NULL ) { + const char *option = *options; + + if ( strncasecmp(option, "user=", 5) == 0 && option[5] != '\0' ) { + username = option+5; + } else { + sieve_storage_set_critical(storage, + "Invalid option `%s'", option); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + + options++; + } + } + + if ( username == NULL ) { + if ( svinst->username == NULL ) { + sieve_storage_set_critical(storage, + "No username specified"); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + username = svinst->username; + } + + e_debug(storage->event, "user=%s, config=%s", + username, storage->location); + + if ( sieve_ldap_storage_read_settings(lstorage, storage->location) < 0 ) + return -1; + + lstorage->username = p_strdup(storage->pool, username); + lstorage->config_file = p_strdup(storage->pool, storage->location); + lstorage->conn = sieve_ldap_db_init(lstorage); + + storage->location = p_strconcat(storage->pool, + SIEVE_LDAP_STORAGE_DRIVER_NAME, ":", storage->location, + ";user=", username, NULL); + + return 0; +} + +static void sieve_ldap_storage_destroy +(struct sieve_storage *storage) +{ + struct sieve_ldap_storage *lstorage = + (struct sieve_ldap_storage *)storage; + + if ( lstorage->conn != NULL ) + sieve_ldap_db_unref(&lstorage->conn); +} + +/* + * Script access + */ + +static struct sieve_script *sieve_ldap_storage_get_script +(struct sieve_storage *storage, const char *name) +{ + struct sieve_ldap_storage *lstorage = + (struct sieve_ldap_storage *)storage; + struct sieve_ldap_script *lscript; + + T_BEGIN { + lscript = sieve_ldap_script_init(lstorage, name); + } T_END; + + return &lscript->script; +} + +/* + * Active script + */ + +struct sieve_script *sieve_ldap_storage_active_script_open +(struct sieve_storage *storage) +{ + struct sieve_ldap_storage *lstorage = + (struct sieve_ldap_storage *)storage; + struct sieve_ldap_script *lscript; + + lscript = sieve_ldap_script_init + (lstorage, storage->script_name); + if ( sieve_script_open(&lscript->script, NULL) < 0 ) { + struct sieve_script *script = &lscript->script; + sieve_script_unref(&script); + return NULL; + } + + return &lscript->script; +} + +int sieve_ldap_storage_active_script_get_name +(struct sieve_storage *storage, const char **name_r) +{ + if ( storage->script_name != NULL ) + *name_r = storage->script_name; + else + *name_r = SIEVE_LDAP_SCRIPT_DEFAULT; + return 0; +} + +/* + * Driver definition + */ + +#ifndef PLUGIN_BUILD +const struct sieve_storage sieve_ldap_storage = { +#else +const struct sieve_storage sieve_ldap_storage_plugin = { +#endif + .driver_name = SIEVE_LDAP_STORAGE_DRIVER_NAME, + .version = 0, + .v = { + .alloc = sieve_ldap_storage_alloc, + .init = sieve_ldap_storage_init, + .destroy = sieve_ldap_storage_destroy, + + .get_script = sieve_ldap_storage_get_script, + + .get_script_sequence = sieve_ldap_storage_get_script_sequence, + .script_sequence_next = sieve_ldap_script_sequence_next, + .script_sequence_destroy = sieve_ldap_script_sequence_destroy, + + .active_script_get_name = sieve_ldap_storage_active_script_get_name, + .active_script_open = sieve_ldap_storage_active_script_open, + + // FIXME: impement management interface + } +}; + +#ifndef SIEVE_BUILTIN_LDAP +/* Building a plugin */ + +const char *sieve_storage_ldap_plugin_version = PIGEONHOLE_ABI_VERSION; + +void sieve_storage_ldap_plugin_load +(struct sieve_instance *svinst, void **context); +void sieve_storage_ldap_plugin_unload +(struct sieve_instance *svinst, void *context); +void sieve_storage_ldap_plugin_init(void); +void sieve_storage_ldap_plugin_deinit(void); + +void sieve_storage_ldap_plugin_load +(struct sieve_instance *svinst, void **context ATTR_UNUSED) +{ + sieve_storage_class_register + (svinst, &sieve_ldap_storage_plugin); + + e_debug(svinst->event, + "Sieve LDAP storage plugin for %s version %s loaded", + PIGEONHOLE_NAME, PIGEONHOLE_VERSION_FULL); +} + +void sieve_storage_ldap_plugin_unload +(struct sieve_instance *svinst ATTR_UNUSED, + void *context ATTR_UNUSED) +{ + sieve_storage_class_unregister + (svinst, &sieve_ldap_storage_plugin); +} + +void sieve_storage_ldap_plugin_init(void) +{ + /* Nothing */ +} + +void sieve_storage_ldap_plugin_deinit(void) +{ + /* Nothing */ +} +#endif + +#else /* !defined(SIEVE_BUILTIN_LDAP) && !defined(PLUGIN_BUILD) */ +const struct sieve_storage sieve_ldap_storage = { + .driver_name = SIEVE_LDAP_STORAGE_DRIVER_NAME +}; +#endif diff --git a/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage.h b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage.h new file mode 100644 index 0000000..f97ceba --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage.h @@ -0,0 +1,108 @@ +#ifndef SIEVE_LDAP_STORAGE_H +#define SIEVE_LDAP_STORAGE_H + +#include "sieve.h" +#include "sieve-script-private.h" +#include "sieve-storage-private.h" + +#define SIEVE_LDAP_SCRIPT_DEFAULT "default" + +#if defined(SIEVE_BUILTIN_LDAP) || defined(PLUGIN_BUILD) + +#include "sieve-ldap-db.h" + +struct sieve_ldap_storage; + +/* + * LDAP settings + */ + +struct sieve_ldap_storage_settings { + const char *hosts; + const char *uris; + const char *dn; + const char *dnpass; + + bool tls; + bool sasl_bind; + const char *sasl_mech; + const char *sasl_realm; + const char *sasl_authz_id; + + const char *tls_ca_cert_file; + const char *tls_ca_cert_dir; + const char *tls_cert_file; + const char *tls_key_file; + const char *tls_cipher_suite; + const char *tls_require_cert; + + const char *deref; + const char *scope; + const char *base; + unsigned int ldap_version; + + const char *ldaprc_path; + const char *debug_level; + + const char *sieve_ldap_script_attr; + const char *sieve_ldap_mod_attr; + const char *sieve_ldap_filter; + + /* ... */ + int ldap_deref, ldap_scope, ldap_tls_require_cert; +}; + +int sieve_ldap_storage_read_settings + (struct sieve_ldap_storage *lstorage, const char *config_path); + +/* + * Storage class + */ + +struct sieve_ldap_storage { + struct sieve_storage storage; + + struct sieve_ldap_storage_settings set; + time_t set_mtime; + + const char *config_file; + const char *username; // FIXME: needed? + + struct ldap_connection *conn; +}; + +struct sieve_script *sieve_ldap_storage_active_script_open + (struct sieve_storage *storage); +int sieve_ldap_storage_active_script_get_name + (struct sieve_storage *storage, const char **name_r); + +/* + * Script class + */ + +struct sieve_ldap_script { + struct sieve_script script; + + const char *dn; + const char *modattr; + + const char *binpath; +}; + +struct sieve_ldap_script *sieve_ldap_script_init + (struct sieve_ldap_storage *lstorage, const char *name); + +/* + * Script sequence + */ + +struct sieve_script_sequence *sieve_ldap_storage_get_script_sequence + (struct sieve_storage *storage, enum sieve_error *error_r); + +struct sieve_script *sieve_ldap_script_sequence_next + (struct sieve_script_sequence *seq, enum sieve_error *error_r); +void sieve_ldap_script_sequence_destroy(struct sieve_script_sequence *seq); + +#endif + +#endif diff --git a/pigeonhole/src/lib-sieve/tst-address.c b/pigeonhole/src/lib-sieve/tst-address.c new file mode 100644 index 0000000..086679d --- /dev/null +++ b/pigeonhole/src/lib-sieve/tst-address.c @@ -0,0 +1,280 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-message.h" +#include "sieve-address.h" +#include "sieve-address-parts.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include <stdio.h> + +/* + * Address test + * + * Syntax: + * address [ADDRESS-PART] [COMPARATOR] [MATCH-TYPE] + * <header-list: string-list> <key-list: string-list> + */ + +static bool tst_address_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool tst_address_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_address_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def tst_address = { + .identifier = "address", + .type = SCT_TEST, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_address_registered, + .validate = tst_address_validate, + .generate = tst_address_generate +}; + +/* + * Address operation + */ + +static bool tst_address_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_address_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def tst_address_operation = { + .mnemonic = "ADDRESS", + .code = SIEVE_OPERATION_ADDRESS, + .dump = tst_address_operation_dump, + .execute = tst_address_operation_execute +}; + +/* + * Test registration + */ + +static bool tst_address_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag + (valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR ); + sieve_match_types_link_tags + (valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + sieve_address_parts_link_tags + (valdtr, cmd_reg, SIEVE_AM_OPT_ADDRESS_PART); + return TRUE; +} + +/* + * Validation + */ + +/* List of valid headers: + * Implementations MUST restrict the address test to headers that + * contain addresses, but MUST include at least From, To, Cc, Bcc, + * Sender, Resent-From, and Resent-To, and it SHOULD include any other + * header that utilizes an "address-list" structured header body. + * + * This list explicitly does not contain the envelope-to and return-path + * headers. The envelope test must be used to test against these addresses. + * + * FIXME: this restriction is somewhat odd. Sieve list advises to allow + * any other header as long as its content matches the address-list + * grammar. + */ +static const char * const _allowed_headers[] = { + /* Required */ + "from", "to", "cc", "bcc", "sender", "resent-from", "resent-to", + + /* Additional (RFC 822 / RFC 2822) */ + "reply-to", "resent-reply-to", "resent-sender", "resent-cc", "resent-bcc", + + /* Non-standard (RFC 2076, draft-palme-mailext-headers-08.txt) */ + "for-approval", "for-handling", "for-comment", "apparently-to", "errors-to", + "delivered-to", "return-receipt-to", "x-admin", "read-receipt-to", + "x-confirm-reading-to", "return-receipt-requested", + "registered-mail-reply-requested-by", "mail-followup-to", "mail-reply-to", + "abuse-reports-to", "x-complaints-to", "x-report-abuse-to", + + /* Undocumented */ + "x-beenthere", "x-original-to", + + NULL +}; + +static int _header_is_allowed +(void *context ATTR_UNUSED, struct sieve_ast_argument *arg) +{ + if ( sieve_argument_is_string_literal(arg) ) { + const char *header = sieve_ast_strlist_strc(arg); + + const char * const *hdsp = _allowed_headers; + while ( *hdsp != NULL ) { + if ( strcasecmp( *hdsp, header ) == 0 ) + return 1; + + hdsp++; + } + + return 0; + } + + return 1; +} + +static bool tst_address_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + struct sieve_ast_argument *header; + struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "header list", 1, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + if ( !sieve_command_verify_headers_argument(valdtr, arg) ) + return FALSE; + + /* Check if supplied header names are allowed + * FIXME: verify dynamic header names at runtime + */ + header = arg; + if ( sieve_ast_stringlist_map + (&header, NULL, _header_is_allowed) <= 0 ) { + i_assert(header != NULL); + sieve_argument_validate_error(valdtr, header, + "specified header '%s' is not allowed for the address test", + str_sanitize(sieve_ast_strlist_strc(header), 64)); + return FALSE; + } + + /* Check key list */ + + arg = sieve_ast_argument_next(arg); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "key list", 2, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate + (valdtr, tst, arg, &mcht_default, &cmp_default); +} + +/* + * Code generation + */ + +static bool tst_address_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *tst) +{ + sieve_operation_emit(cgenv->sblock, NULL, &tst_address_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool tst_address_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "ADDRESS"); + sieve_code_descend(denv); + + /* Handle any optional arguments */ + if ( sieve_message_opr_optional_dump(denv, address, NULL) != 0 ) + return FALSE; + + return + sieve_opr_stringlist_dump(denv, address, "header list") && + sieve_opr_stringlist_dump(denv, address, "key list"); +} + +/* + * Code execution + */ + +static int tst_address_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + struct sieve_address_part addrp = + SIEVE_ADDRESS_PART_DEFAULT(all_address_part); + struct sieve_stringlist *hdr_list, *hdr_value_list, *value_list, *key_list; + struct sieve_address_list *addr_list; + ARRAY_TYPE(sieve_message_override) svmos; + int match, ret; + + /* Read optional operands */ + i_zero(&svmos); + if ( sieve_message_opr_optional_read + (renv, address, NULL, &ret, &addrp, &mcht, &cmp, &svmos) < 0 ) + return ret; + + /* Read header-list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "header-list", &hdr_list)) + <= 0 ) + return ret; + + /* Read key-list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "address test"); + + /* Get header */ + sieve_runtime_trace_descend(renv); + if ( (ret=sieve_message_get_header_fields + (renv, hdr_list, &svmos, FALSE, &hdr_value_list)) <= 0 ) + return ret; + sieve_runtime_trace_ascend(renv); + + /* Create value stringlist */ + addr_list = sieve_header_address_list_create(renv, hdr_value_list); + value_list = sieve_address_part_stringlist_create(renv, &addrp, addr_list); + + /* Perform match */ + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/tst-allof.c b/pigeonhole/src/lib-sieve/tst-allof.c new file mode 100644 index 0000000..6d278b9 --- /dev/null +++ b/pigeonhole/src/lib-sieve/tst-allof.c @@ -0,0 +1,108 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-binary.h" + +/* + * Allof test + * + * Syntax + * allof <tests: test-list> + */ + +static bool tst_allof_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx, + struct sieve_jumplist *jumps, bool jump_true); +static bool tst_allof_validate_const + (struct sieve_validator *valdtr, struct sieve_command *tst, + int *const_current, int const_new); + +const struct sieve_command_def tst_allof = { + .identifier = "allof", + .type = SCT_TEST, + .positional_args = 0, + .subtests = 2, + .block_allowed = FALSE, + .block_required = FALSE, + .validate_const = tst_allof_validate_const, + .control_generate = tst_allof_generate +}; + +/* + * Code validation + */ + +static bool tst_allof_validate_const +(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *tst ATTR_UNUSED, int *const_current, int const_next) +{ + if ( const_next == 0 ) { + *const_current = 0; + return FALSE; + } + + if ( *const_current != -1 ) + *const_current = const_next; + return TRUE; +} + +/* + * Code generation + */ + +static bool tst_allof_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *ctx, + struct sieve_jumplist *jumps, bool jump_true) +{ + struct sieve_binary_block *sblock = cgenv->sblock; + struct sieve_ast_node *test; + struct sieve_jumplist false_jumps; + + if ( sieve_ast_test_count(ctx->ast_node) > 1 ) { + if ( jump_true ) { + /* Prepare jumplist */ + sieve_jumplist_init_temp(&false_jumps, sblock); + } + + test = sieve_ast_test_first(ctx->ast_node); + while ( test != NULL ) { + bool result; + + /* If this test list must jump on false, all sub-tests can simply add their jumps + * to the caller's jump list, otherwise this test redirects all false jumps to the + * end of the currently generated code. This is just after a final jump to the true + * case + */ + if ( jump_true ) + result = sieve_generate_test(cgenv, test, &false_jumps, FALSE); + else + result = sieve_generate_test(cgenv, test, jumps, FALSE); + + if ( !result ) return FALSE; + + test = sieve_ast_test_next(test); + } + + if ( jump_true ) { + /* All tests succeeded, jump to case TRUE */ + sieve_operation_emit(cgenv->sblock, NULL, &sieve_jmp_operation); + sieve_jumplist_add(jumps, sieve_binary_emit_offset(sblock, 0)); + + /* All false exits jump here */ + sieve_jumplist_resolve(&false_jumps); + } + } else { + /* Script author is being inefficient; we can optimize the allof test away */ + test = sieve_ast_test_first(ctx->ast_node); + sieve_generate_test(cgenv, test, jumps, jump_true); + } + + return TRUE; +} + diff --git a/pigeonhole/src/lib-sieve/tst-anyof.c b/pigeonhole/src/lib-sieve/tst-anyof.c new file mode 100644 index 0000000..84bfedd --- /dev/null +++ b/pigeonhole/src/lib-sieve/tst-anyof.c @@ -0,0 +1,107 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-generator.h" +#include "sieve-validator.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-binary.h" + +/* + * Anyof test + * + * Syntax + * anyof <tests: test-list> + */ + +static bool tst_anyof_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx, + struct sieve_jumplist *jumps, bool jump_true); +static bool tst_anyof_validate_const + (struct sieve_validator *valdtr, struct sieve_command *tst, + int *const_current, int const_next); + +const struct sieve_command_def tst_anyof = { + .identifier = "anyof", + .type = SCT_TEST, + .positional_args = 0, + .subtests = 2, + .block_allowed = FALSE, + .block_required = FALSE, + .validate_const = tst_anyof_validate_const, + .control_generate = tst_anyof_generate +}; + +/* + * Code validation + */ + +static bool tst_anyof_validate_const +(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *tst ATTR_UNUSED, int *const_current, int const_next) +{ + if ( const_next > 0 ) { + *const_current = 1; + return FALSE; + } + + if ( *const_current != -1 ) + *const_current = const_next; + return TRUE; +} + +/* + * Code generation + */ + +static bool tst_anyof_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx, + struct sieve_jumplist *jumps, bool jump_true) +{ + struct sieve_binary_block *sblock = cgenv->sblock; + struct sieve_ast_node *test; + struct sieve_jumplist true_jumps; + + if ( sieve_ast_test_count(ctx->ast_node) > 1 ) { + if ( !jump_true ) { + /* Prepare jumplist */ + sieve_jumplist_init_temp(&true_jumps, sblock); + } + + test = sieve_ast_test_first(ctx->ast_node); + while ( test != NULL ) { + bool result; + + /* If this test list must jump on true, all sub-tests can simply add their jumps + * to the caller's jump list, otherwise this test redirects all true jumps to the + * end of the currently generated code. This is just after a final jump to the false + * case + */ + if ( !jump_true ) + result = sieve_generate_test(cgenv, test, &true_jumps, TRUE); + else + result = sieve_generate_test(cgenv, test, jumps, TRUE); + + if ( !result ) return FALSE; + + test = sieve_ast_test_next(test); + } + + if ( !jump_true ) { + /* All tests failed, jump to case FALSE */ + sieve_operation_emit(sblock, NULL, &sieve_jmp_operation); + sieve_jumplist_add(jumps, sieve_binary_emit_offset(sblock, 0)); + + /* All true exits jump here */ + sieve_jumplist_resolve(&true_jumps); + } + } else { + /* Script author is being inefficient; we can optimize the allof test away */ + test = sieve_ast_test_first(ctx->ast_node); + sieve_generate_test(cgenv, test, jumps, jump_true); + } + + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/tst-exists.c b/pigeonhole/src/lib-sieve/tst-exists.c new file mode 100644 index 0000000..0668c30 --- /dev/null +++ b/pigeonhole/src/lib-sieve/tst-exists.c @@ -0,0 +1,179 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-code-dumper.h" + +/* + * Exists test + * + * Syntax: + * exists <header-names: string-list> + */ + +static bool tst_exists_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_exists_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *tst); + +const struct sieve_command_def tst_exists = { + .identifier = "exists", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = tst_exists_validate, + .generate = tst_exists_generate +}; + +/* + * Exists operation + */ + +static bool tst_exists_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_exists_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def tst_exists_operation = { + .mnemonic = "EXISTS", + .code = SIEVE_OPERATION_EXISTS, + .dump = tst_exists_operation_dump, + .execute = tst_exists_operation_execute +}; + +/* + * Validation + */ + +static bool tst_exists_validate + (struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "header names", 1, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + return sieve_command_verify_headers_argument(valdtr, arg); +} + +/* + * Code generation + */ + +static bool tst_exists_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *tst) +{ + sieve_operation_emit(cgenv->sblock, NULL, &tst_exists_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool tst_exists_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "EXISTS"); + sieve_code_descend(denv); + + /* Optional operands */ + if ( sieve_message_opr_optional_dump(denv, address, NULL) != 0 ) + return FALSE; + + return sieve_opr_stringlist_dump(denv, address, "header names"); +} + +/* + * Code execution + */ + +static int tst_exists_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_stringlist *hdr_list; + ARRAY_TYPE(sieve_message_override) svmos; + string_t *hdr_item; + bool matched; + int ret; + + /* + * Read operands + */ + + /* Optional operands */ + i_zero(&svmos); + if ( sieve_message_opr_optional_read + (renv, address, NULL, &ret, NULL, NULL, NULL, &svmos) < 0 ) + return ret; + + /* Read header-list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "header-list", &hdr_list)) + <= 0 ) + return ret; + + /* + * Perfrom test + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "exists test"); + sieve_runtime_trace_descend(renv); + + /* Iterate through all requested headers to match (must find all specified) */ + hdr_item = NULL; + matched = TRUE; + while ( matched && + (ret=sieve_stringlist_next_item(hdr_list, &hdr_item)) > 0 ) { + struct sieve_stringlist *value_list; + string_t *dummy; + + /* Get header */ + if ( (ret=sieve_message_get_header_fields + (renv, sieve_single_stringlist_create(renv, hdr_item, FALSE), + &svmos, FALSE, &value_list)) <= 0 ) + return ret; + + if ( (ret=sieve_stringlist_next_item(value_list, &dummy)) < 0) + return value_list->exec_status; + + if ( ret == 0 ) + matched = FALSE; + + sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, + "header `%s' %s", str_sanitize(str_c(hdr_item), 80), + ( matched ? "exists" : "is missing" )); + } + + if ( matched ) + sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, "all headers exist"); + else + sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, "headers are missing"); + + /* Set test result for subsequent conditional jump */ + if ( ret >= 0 ) { + sieve_interpreter_set_test_result(renv->interp, matched); + return SIEVE_EXEC_OK; + } + + sieve_runtime_trace_error(renv, "invalid header-list item"); + return SIEVE_EXEC_BIN_CORRUPT; +} diff --git a/pigeonhole/src/lib-sieve/tst-header.c b/pigeonhole/src/lib-sieve/tst-header.c new file mode 100644 index 0000000..6e553a2 --- /dev/null +++ b/pigeonhole/src/lib-sieve/tst-header.c @@ -0,0 +1,204 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +/* + * Header test + * + * Syntax: + * header [COMPARATOR] [MATCH-TYPE] + * <header-names: string-list> <key-list: string-list> + */ + +static bool tst_header_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool tst_header_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_header_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *tst); + +const struct sieve_command_def tst_header = { + .identifier = "header", + .type = SCT_TEST, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_header_registered, + .validate = tst_header_validate, + .generate = tst_header_generate +}; + +/* + * Header operation + */ + +static bool tst_header_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_header_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def tst_header_operation = { + .mnemonic = "HEADER", + .code = SIEVE_OPERATION_HEADER, + .dump = tst_header_operation_dump, + .execute = tst_header_operation_execute +}; + +/* + * Test registration + */ + +static bool tst_header_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + + return TRUE; +} + +/* + * Validation + */ + +static bool tst_header_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "header names", 1, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + if ( !sieve_command_verify_headers_argument(valdtr, arg) ) + return FALSE; + + arg = sieve_ast_argument_next(arg); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "key list", 2, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate + (valdtr, tst, arg, &mcht_default, &cmp_default); +} + +/* + * Code generation + */ + +static bool tst_header_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *tst) +{ + sieve_operation_emit(cgenv->sblock, NULL, &tst_header_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool tst_header_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "HEADER"); + sieve_code_descend(denv); + + /* Optional operands */ + if ( sieve_message_opr_optional_dump(denv, address, NULL) != 0 ) + return FALSE; + + return + sieve_opr_stringlist_dump(denv, address, "header names") && + sieve_opr_stringlist_dump(denv, address, "key list"); +} + +/* + * Code execution + */ + +static int tst_header_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + struct sieve_stringlist *hdr_list, *key_list, *value_list; + ARRAY_TYPE(sieve_message_override) svmos; + int match, ret; + + /* + * Read operands + */ + + /* Optional operands */ + i_zero(&svmos); + if ( sieve_message_opr_optional_read + (renv, address, NULL, &ret, NULL, &mcht, &cmp, &svmos) < 0 ) + return ret; + + /* Read header-list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "header-list", &hdr_list)) + <= 0 ) + return ret; + + /* Read key-list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; + + /* + * Perform test + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "header test"); + + /* Get header */ + sieve_runtime_trace_descend(renv); + if ( (ret=sieve_message_get_header_fields + (renv, hdr_list, &svmos, TRUE, &value_list)) <= 0 ) + return ret; + sieve_runtime_trace_ascend(renv); + + /* Perform match */ + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/tst-not.c b/pigeonhole/src/lib-sieve/tst-not.c new file mode 100644 index 0000000..9687d49 --- /dev/null +++ b/pigeonhole/src/lib-sieve/tst-not.c @@ -0,0 +1,67 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" + +/* + * Not test + * + * Syntax: + * not <tests: test-list> + */ + +static bool tst_not_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx, + struct sieve_jumplist *jumps, bool jump_true); +static bool tst_not_validate_const + (struct sieve_validator *valdtr, struct sieve_command *tst, + int *const_current, int const_next); + +const struct sieve_command_def tst_not = { + .identifier = "not", + .type = SCT_TEST, + .positional_args = 0, + .subtests = 1, + .block_allowed = FALSE, + .block_required = FALSE, + .validate_const = tst_not_validate_const, + .control_generate = tst_not_generate +}; + +/* + * Code validation + */ + +static bool tst_not_validate_const +(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *tst ATTR_UNUSED, int *const_current, int const_next) +{ + if ( const_next < 0 ) + *const_current = -1; + else if ( const_next > 0 ) + *const_current = 0; + else + *const_current = 1; + + return TRUE; +} + +/* + * Code generation + */ + +static bool tst_not_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *ctx, + struct sieve_jumplist *jumps, bool jump_true) +{ + struct sieve_ast_node *test; + + /* Validator verified the existance of the single test already */ + test = sieve_ast_test_first(ctx->ast_node); + + return sieve_generate_test(cgenv, test, jumps, !jump_true); +} + diff --git a/pigeonhole/src/lib-sieve/tst-size.c b/pigeonhole/src/lib-sieve/tst-size.c new file mode 100644 index 0000000..1ed101b --- /dev/null +++ b/pigeonhole/src/lib-sieve/tst-size.c @@ -0,0 +1,318 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "mail-storage.h" + +#include "sieve-common.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +/* + * Size test + * + * Syntax: + * size <":over" / ":under"> <limit: number> + */ + +static bool +tst_size_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool +tst_size_pre_validate(struct sieve_validator *valdtr, + struct sieve_command *tst); +static bool +tst_size_validate(struct sieve_validator *valdtr, struct sieve_command *tst); +static bool +tst_size_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def tst_size = { + .identifier = "size", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_size_registered, + .pre_validate = tst_size_pre_validate, + .validate = tst_size_validate, + .generate = tst_size_generate +}; + +/* + * Size operations + */ + +static bool +tst_size_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +tst_size_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def tst_size_over_operation = { + .mnemonic = "SIZE-OVER", + .code = SIEVE_OPERATION_SIZE_OVER, + .dump = tst_size_operation_dump, + .execute = tst_size_operation_execute +}; + +const struct sieve_operation_def tst_size_under_operation = { + .mnemonic = "SIZE-UNDER", + .code = SIEVE_OPERATION_SIZE_UNDER, + .dump = tst_size_operation_dump, + .execute = tst_size_operation_execute +}; + +/* + * Context data + */ + +struct tst_size_context_data { + enum { SIZE_UNASSIGNED, SIZE_UNDER, SIZE_OVER } type; +}; + +#define TST_SIZE_ERROR_DUP_TAG \ + "exactly one of the ':under' or ':over' tags must be specified " \ + "for the size test, but more were found" + +/* + * Tag validation + */ + +static bool +tst_size_validate_over_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *tst) +{ + struct tst_size_context_data *ctx_data = + (struct tst_size_context_data *)tst->data; + + if (ctx_data->type != SIZE_UNASSIGNED) { + sieve_argument_validate_error(valdtr, *arg, + TST_SIZE_ERROR_DUP_TAG); + return FALSE; + } + + ctx_data->type = SIZE_OVER; + + /* Delete this tag */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + return TRUE; +} + +static bool +tst_size_validate_under_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg ATTR_UNUSED, + struct sieve_command *tst) +{ + struct tst_size_context_data *ctx_data = + (struct tst_size_context_data *)tst->data; + + if (ctx_data->type != SIZE_UNASSIGNED) { + sieve_argument_validate_error(valdtr, *arg, + TST_SIZE_ERROR_DUP_TAG); + return FALSE; + } + + ctx_data->type = SIZE_UNDER; + + /* Delete this tag */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + return TRUE; +} + +/* + * Test registration + */ + +static const struct sieve_argument_def size_over_tag = { + .identifier = "over", + .validate = tst_size_validate_over_tag +}; + +static const struct sieve_argument_def size_under_tag = { + .identifier = "under", + .validate = tst_size_validate_under_tag, +}; + +static bool +tst_size_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_command_registration *cmd_reg) +{ + /* Register our tags */ + sieve_validator_register_tag(valdtr, cmd_reg, NULL, &size_over_tag, 0); + sieve_validator_register_tag(valdtr, cmd_reg, NULL, &size_under_tag, 0); + + return TRUE; +} + +/* + * Test validation + */ + +static bool +tst_size_pre_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *tst) +{ + struct tst_size_context_data *ctx_data; + + /* Assign context */ + ctx_data = p_new(sieve_command_pool(tst), + struct tst_size_context_data, 1); + ctx_data->type = SIZE_UNASSIGNED; + tst->data = ctx_data; + + return TRUE; +} + +static bool +tst_size_validate(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct tst_size_context_data *ctx_data = + (struct tst_size_context_data *)tst->data; + struct sieve_ast_argument *arg = tst->first_positional; + + if (ctx_data->type == SIZE_UNASSIGNED) { + sieve_command_validate_error(valdtr, tst, + "the size test requires either the :under or the :over tag " + "to be specified"); + return FALSE; + } + + if (!sieve_validate_positional_argument(valdtr, tst, arg, "limit", 1, + SAAT_NUMBER)) + return FALSE; + + return sieve_validator_argument_activate(valdtr, tst, arg, FALSE); +} + +/* + * Code generation + */ + +bool tst_size_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *tst) +{ + struct tst_size_context_data *ctx_data = + (struct tst_size_context_data *)tst->data; + + if (ctx_data->type == SIZE_OVER) { + sieve_operation_emit(cgenv->sblock, NULL, + &tst_size_over_operation); + } else { + sieve_operation_emit(cgenv->sblock, NULL, + &tst_size_under_operation); + } + + /* Generate arguments */ + if (!sieve_generate_arguments(cgenv, tst, NULL)) + return FALSE; + + return TRUE; +} + +/* + * Code dump + */ + +static bool +tst_size_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(denv->oprtn)); + sieve_code_descend(denv); + + return sieve_opr_number_dump(denv, address, "limit"); +} + +/* + * Code execution + */ + +static inline bool +tst_size_get(const struct sieve_runtime_env *renv, sieve_number_t *size) +{ + struct mail *mail = sieve_message_get_mail(renv->msgctx); + uoff_t psize; + + if (mail_get_physical_size(mail, &psize) < 0) + return FALSE; + + *size = psize; + return TRUE; +} + +static int +tst_size_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + sieve_number_t mail_size, limit; + int ret; + + /* + * Read operands + */ + + /* Read size limit */ + if ((ret = sieve_opr_number_read(renv, address, "limit", &limit)) <= 0) + return ret; + + /* + * Perform test + */ + + /* Get the size of the message */ + if (!tst_size_get(renv, &mail_size)) { + /* FIXME: improve this error */ + e_error(renv->event, "failed to assess message size"); + return SIEVE_EXEC_FAILURE; + } + + /* Perform the test */ + if (sieve_operation_is(renv->oprtn, tst_size_over_operation)) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "size :over test"); + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING)) { + sieve_runtime_trace_descend(renv); + + sieve_runtime_trace( + renv, 0, "comparing message size %llu", + (unsigned long long)mail_size); + sieve_runtime_trace( + renv, 0, "with upper limit %llu", + (unsigned long long)limit); + } + + sieve_interpreter_set_test_result(renv->interp, + (mail_size > limit)); + } else { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "size :under test"); + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING)) { + sieve_runtime_trace_descend(renv); + + sieve_runtime_trace( + renv, 0, "comparing message size %llu", + (unsigned long long)mail_size); + sieve_runtime_trace( + renv, 0, "with lower limit %llu", + (unsigned long long)limit); + } + + sieve_interpreter_set_test_result(renv->interp, + (mail_size < limit)); + } + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/tst-truefalse.c b/pigeonhole/src/lib-sieve/tst-truefalse.c new file mode 100644 index 0000000..6373ce3 --- /dev/null +++ b/pigeonhole/src/lib-sieve/tst-truefalse.c @@ -0,0 +1,104 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-ast.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" + +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-interpreter.h" + +/* + * True/False test command + */ + +static bool tst_false_validate_const + (struct sieve_validator *valdtr, struct sieve_command *tst, + int *const_current, int const_next); +static bool tst_false_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd, + struct sieve_jumplist *jumps, bool jump_true); + +const struct sieve_command_def tst_false = { + .identifier = "false", + .type = SCT_TEST, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate_const = tst_false_validate_const, + .control_generate = tst_false_generate +}; + +static bool tst_true_validate_const + (struct sieve_validator *valdtr, struct sieve_command *tst, + int *const_current, int const_next); +static bool tst_true_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd, + struct sieve_jumplist *jumps, bool jump_true); + +const struct sieve_command_def tst_true = { + .identifier = "true", + .type = SCT_TEST, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate_const = tst_true_validate_const, + .control_generate = tst_true_generate +}; + +/* + * Code validation + */ + +static bool tst_false_validate_const +(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *tst ATTR_UNUSED, int *const_current, + int const_next ATTR_UNUSED) +{ + *const_current = 0; + return TRUE; +} + +static bool tst_true_validate_const +(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *tst ATTR_UNUSED, int *const_current, + int const_next ATTR_UNUSED) +{ + *const_current = 1; + return TRUE; +} + +/* + * Code generation + */ + +static bool tst_false_generate +(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd ATTR_UNUSED, + struct sieve_jumplist *jumps, bool jump_true) +{ + if ( !jump_true ) { + sieve_operation_emit(cgenv->sblock, NULL, &sieve_jmp_operation); + sieve_jumplist_add(jumps, sieve_binary_emit_offset(cgenv->sblock, 0)); + } + + return TRUE; +} + +static bool tst_true_generate +(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd ATTR_UNUSED, + struct sieve_jumplist *jumps, bool jump_true) +{ + if ( jump_true ) { + sieve_operation_emit(cgenv->sblock, NULL, &sieve_jmp_operation); + sieve_jumplist_add(jumps, sieve_binary_emit_offset(cgenv->sblock, 0)); + } + + return TRUE; +} + diff --git a/pigeonhole/src/lib-sieve/util/Makefile.am b/pigeonhole/src/lib-sieve/util/Makefile.am new file mode 100644 index 0000000..36cad8a --- /dev/null +++ b/pigeonhole/src/lib-sieve/util/Makefile.am @@ -0,0 +1,51 @@ +noinst_LTLIBRARIES = libsieve_util.la + +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_SERVICE_INCLUDE) \ + -DMODULEDIR=\""$(dovecot_moduledir)"\" + +libsieve_util_la_DEPENDENCIES = $(LIBDOVECOT_STORAGE_DEPS) $(LIBDOVECOT_DEPS) + +libsieve_util_la_SOURCES = \ + mail-raw.c \ + edit-mail.c \ + rfc2822.c + +headers = \ + mail-raw.h \ + edit-mail.h \ + rfc2822.h + +pkginc_libdir=$(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(headers) + +test_programs = \ + test-edit-mail \ + test-rfc2822 + +noinst_PROGRAMS = $(test_programs) + +test_libs = \ + libsieve_util.la \ + $(LIBDOVECOT_STORAGE) \ + $(LIBDOVECOT) +test_deps = \ + libsieve_util.la \ + $(LIBDOVECOT_STORAGE_DEPS) \ + $(LIBDOVECOT_DEPS) + +test_edit_mail_SOURCES = test-edit-mail.c +test_edit_mail_LDADD = $(test_libs) +test_edit_mail_DEPENDENCIES = $(test_deps) + +test_rfc2822_SOURCES = test-rfc2822.c +test_rfc2822_LDADD = $(test_libs) +test_rfc2822_DEPENDENCIES = $(test_deps) + +check: check-am check-test +check-test: all-am + for bin in $(test_programs); do \ + if ! $(RUN_TEST) ./$$bin; then exit 1; fi; \ + done + diff --git a/pigeonhole/src/lib-sieve/util/Makefile.in b/pigeonhole/src/lib-sieve/util/Makefile.in new file mode 100644 index 0000000..a62ac20 --- /dev/null +++ b/pigeonhole/src/lib-sieve/util/Makefile.in @@ -0,0 +1,810 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = $(am__EXEEXT_1) +subdir = src/lib-sieve/util +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(pkginc_lib_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__EXEEXT_1 = test-edit-mail$(EXEEXT) test-rfc2822$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_util_la_LIBADD = +am_libsieve_util_la_OBJECTS = mail-raw.lo edit-mail.lo rfc2822.lo +libsieve_util_la_OBJECTS = $(am_libsieve_util_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +am_test_edit_mail_OBJECTS = test-edit-mail.$(OBJEXT) +test_edit_mail_OBJECTS = $(am_test_edit_mail_OBJECTS) +am__DEPENDENCIES_1 = +am__DEPENDENCIES_2 = libsieve_util.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_test_rfc2822_OBJECTS = test-rfc2822.$(OBJEXT) +test_rfc2822_OBJECTS = $(am_test_rfc2822_OBJECTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/edit-mail.Plo \ + ./$(DEPDIR)/mail-raw.Plo ./$(DEPDIR)/rfc2822.Plo \ + ./$(DEPDIR)/test-edit-mail.Po ./$(DEPDIR)/test-rfc2822.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libsieve_util_la_SOURCES) $(test_edit_mail_SOURCES) \ + $(test_rfc2822_SOURCES) +DIST_SOURCES = $(libsieve_util_la_SOURCES) $(test_edit_mail_SOURCES) \ + $(test_rfc2822_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkginc_libdir)" +HEADERS = $(pkginc_lib_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_util.la +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_SERVICE_INCLUDE) \ + -DMODULEDIR=\""$(dovecot_moduledir)"\" + +libsieve_util_la_DEPENDENCIES = $(LIBDOVECOT_STORAGE_DEPS) $(LIBDOVECOT_DEPS) +libsieve_util_la_SOURCES = \ + mail-raw.c \ + edit-mail.c \ + rfc2822.c + +headers = \ + mail-raw.h \ + edit-mail.h \ + rfc2822.h + +pkginc_libdir = $(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(headers) +test_programs = \ + test-edit-mail \ + test-rfc2822 + +test_libs = \ + libsieve_util.la \ + $(LIBDOVECOT_STORAGE) \ + $(LIBDOVECOT) + +test_deps = \ + libsieve_util.la \ + $(LIBDOVECOT_STORAGE_DEPS) \ + $(LIBDOVECOT_DEPS) + +test_edit_mail_SOURCES = test-edit-mail.c +test_edit_mail_LDADD = $(test_libs) +test_edit_mail_DEPENDENCIES = $(test_deps) +test_rfc2822_SOURCES = test-rfc2822.c +test_rfc2822_LDADD = $(test_libs) +test_rfc2822_DEPENDENCIES = $(test_deps) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/util/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/util/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libsieve_util.la: $(libsieve_util_la_OBJECTS) $(libsieve_util_la_DEPENDENCIES) $(EXTRA_libsieve_util_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_util_la_OBJECTS) $(libsieve_util_la_LIBADD) $(LIBS) + +test-edit-mail$(EXEEXT): $(test_edit_mail_OBJECTS) $(test_edit_mail_DEPENDENCIES) $(EXTRA_test_edit_mail_DEPENDENCIES) + @rm -f test-edit-mail$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_edit_mail_OBJECTS) $(test_edit_mail_LDADD) $(LIBS) + +test-rfc2822$(EXEEXT): $(test_rfc2822_OBJECTS) $(test_rfc2822_DEPENDENCIES) $(EXTRA_test_rfc2822_DEPENDENCIES) + @rm -f test-rfc2822$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_rfc2822_OBJECTS) $(test_rfc2822_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edit-mail.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mail-raw.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rfc2822.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-edit-mail.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-rfc2822.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkginc_libHEADERS: $(pkginc_lib_HEADERS) + @$(NORMAL_INSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkginc_libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkginc_libdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkginc_libdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkginc_libdir)" || exit $$?; \ + done + +uninstall-pkginc_libHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkginc_libdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(pkginc_libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/edit-mail.Plo + -rm -f ./$(DEPDIR)/mail-raw.Plo + -rm -f ./$(DEPDIR)/rfc2822.Plo + -rm -f ./$(DEPDIR)/test-edit-mail.Po + -rm -f ./$(DEPDIR)/test-rfc2822.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pkginc_libHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/edit-mail.Plo + -rm -f ./$(DEPDIR)/mail-raw.Plo + -rm -f ./$(DEPDIR)/rfc2822.Plo + -rm -f ./$(DEPDIR)/test-edit-mail.Po + -rm -f ./$(DEPDIR)/test-rfc2822.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkginc_libHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkginc_libHEADERS \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am \ + uninstall-pkginc_libHEADERS + +.PRECIOUS: Makefile + + +check: check-am check-test +check-test: all-am + for bin in $(test_programs); do \ + if ! $(RUN_TEST) ./$$bin; then exit 1; fi; \ + done + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/util/edit-mail.c b/pigeonhole/src/lib-sieve/util/edit-mail.c new file mode 100644 index 0000000..31d941e --- /dev/null +++ b/pigeonhole/src/lib-sieve/util/edit-mail.c @@ -0,0 +1,2254 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "str.h" +#include "mempool.h" +#include "llist.h" +#include "istream-private.h" +#include "master-service.h" +#include "master-service-settings.h" +#include "message-parser.h" +#include "message-header-encode.h" +#include "message-header-decode.h" +#include "mail-user.h" +#include "mail-storage-private.h" +#include "index-mail.h" +#include "raw-storage.h" + +#include "rfc2822.h" + +#include "edit-mail.h" + +/* + * Forward declarations + */ + +struct _header_field_index; +struct _header_field; +struct _header_index; +struct _header; + +static struct mail_vfuncs edit_mail_vfuncs; + +struct edit_mail_istream; +struct istream *edit_mail_istream_create(struct edit_mail *edmail); + +static struct _header_index * +edit_mail_header_clone(struct edit_mail *edmail, struct _header *header); + +/* + * Raw storage + */ + +static struct mail_user *edit_mail_user = NULL; +static unsigned int edit_mail_refcount = 0; + +static struct mail_user *edit_mail_raw_storage_get(struct mail_user *mail_user) +{ + if (edit_mail_user == NULL) { + void **sets = + master_service_settings_get_others(master_service); + + edit_mail_user = raw_storage_create_from_set( + mail_user->set_info, sets[0]); + } + + edit_mail_refcount++; + + return edit_mail_user; +} + +static void edit_mail_raw_storage_drop(void) +{ + i_assert(edit_mail_refcount > 0); + + if (--edit_mail_refcount != 0) + return; + + mail_user_unref(&edit_mail_user); + edit_mail_user = NULL; +} + +/* + * Headers + */ + +struct _header_field { + struct _header *header; + + unsigned int refcount; + + char *data; + size_t size; + size_t virtual_size; + uoff_t offset; + unsigned int lines; + + uoff_t body_offset; + + char *utf8_value; +}; + +struct _header_field_index { + struct _header_field_index *prev, *next; + + struct _header_field *field; + struct _header_index *header; +}; + +struct _header { + unsigned int refcount; + + char *name; +}; + +struct _header_index { + struct _header_index *prev, *next; + + struct _header *header; + + struct _header_field_index *first, *last; + + unsigned int count; +}; + +static inline struct _header *_header_create(const char *name) +{ + struct _header *header; + + header = i_new(struct _header, 1); + header->name = i_strdup(name); + header->refcount = 1; + + return header; +} + +static inline void _header_ref(struct _header *header) +{ + header->refcount++; +} + +static inline void _header_unref(struct _header *header) +{ + i_assert(header->refcount > 0); + if (--header->refcount != 0) + return; + + i_free(header->name); + i_free(header); +} + +static inline struct _header_field *_header_field_create(struct _header *header) +{ + struct _header_field *hfield; + + hfield = i_new(struct _header_field, 1); + hfield->refcount = 1; + hfield->header = header; + if (header != NULL) + _header_ref(header); + + return hfield; +} + +static inline void _header_field_ref(struct _header_field *hfield) +{ + hfield->refcount++; +} + +static inline void _header_field_unref(struct _header_field *hfield) +{ + i_assert(hfield->refcount > 0); + if (--hfield->refcount != 0) + return; + + if (hfield->header != NULL) + _header_unref(hfield->header); + + if (hfield->data != NULL) + i_free(hfield->data); + if (hfield->utf8_value != NULL) + i_free(hfield->utf8_value); + i_free(hfield); +} + +/* + * Edit mail object + */ + +struct edit_mail { + struct mail_private mail; + struct mail_private *wrapped; + + struct edit_mail *parent; + unsigned int refcount; + + struct istream *wrapped_stream; + struct istream *stream; + + struct _header_index *headers_head, *headers_tail; + struct _header_field_index *header_fields_head, *header_fields_tail; + struct message_size hdr_size, body_size; + + struct message_size wrapped_hdr_size, wrapped_body_size; + + struct _header_field_index *header_fields_appended; + struct message_size appended_hdr_size; + + bool modified:1; + bool snapshot_modified:1; + bool crlf:1; + bool eoh_crlf:1; + bool headers_parsed:1; + bool destroying_stream:1; +}; + +struct edit_mail *edit_mail_wrap(struct mail *mail) +{ + struct mail_private *mailp = (struct mail_private *) mail; + struct edit_mail *edmail; + struct mail_user *raw_mail_user; + struct mailbox *raw_box = NULL; + struct mailbox_transaction_context *raw_trans; + struct message_size hdr_size, body_size; + struct istream *wrapped_stream; + uoff_t size_diff; + pool_t pool; + + if (mail_get_stream(mail, &hdr_size, &body_size, &wrapped_stream) < 0) + return NULL; + + /* Create dummy raw mailbox for our wrapper */ + + raw_mail_user = edit_mail_raw_storage_get(mail->box->storage->user); + + if (raw_mailbox_alloc_stream(raw_mail_user, wrapped_stream, (time_t)-1, + "editor@example.com", &raw_box) < 0) { + i_error("edit-mail: failed to open raw box: %s", + mailbox_get_last_internal_error(raw_box, NULL)); + mailbox_free(&raw_box); + edit_mail_raw_storage_drop(); + return NULL; + } + + raw_trans = mailbox_transaction_begin(raw_box, 0, __func__); + + /* Create the wrapper mail */ + + pool = pool_alloconly_create("edit_mail", 1024); + edmail = p_new(pool, struct edit_mail, 1); + edmail->refcount = 1; + edmail->mail.pool = pool; + + edmail->wrapped = mailp; + edmail->wrapped_hdr_size = hdr_size; + edmail->wrapped_body_size = body_size; + + edmail->wrapped_stream = wrapped_stream; + i_stream_ref(edmail->wrapped_stream); + + /* Determine whether we should use CRLF or LF for the physical message + */ + size_diff = ((hdr_size.virtual_size + body_size.virtual_size) - + (hdr_size.physical_size + body_size.physical_size)); + if (size_diff == 0 || size_diff <= (hdr_size.lines + body_size.lines)/2) + edmail->crlf = edmail->eoh_crlf = TRUE; + + array_create(&edmail->mail.module_contexts, pool, sizeof(void *), 5); + + edmail->mail.v = edit_mail_vfuncs; + edmail->mail.mail.seq = 1; + edmail->mail.mail.box = raw_box; + edmail->mail.mail.transaction = raw_trans; + edmail->mail.wanted_fields = mailp->wanted_fields; + edmail->mail.wanted_headers = mailp->wanted_headers; + + return edmail; +} + +struct edit_mail *edit_mail_snapshot(struct edit_mail *edmail) +{ + struct _header_field_index *field_idx, *field_idx_new; + struct edit_mail *edmail_new; + pool_t pool; + + if (!edmail->snapshot_modified) + return edmail; + + pool = pool_alloconly_create("edit_mail", 1024); + edmail_new = p_new(pool, struct edit_mail, 1); + edmail_new->refcount = 1; + edmail_new->mail.pool = pool; + + edmail_new->wrapped = edmail->wrapped; + edmail_new->wrapped_hdr_size = edmail->wrapped_hdr_size; + edmail_new->wrapped_body_size = edmail->wrapped_body_size; + edmail_new->hdr_size = edmail->hdr_size; + edmail_new->body_size = edmail->body_size; + edmail_new->appended_hdr_size = edmail->appended_hdr_size; + + edmail_new->wrapped_stream = edmail->wrapped_stream; + i_stream_ref(edmail_new->wrapped_stream); + + edmail_new->crlf = edmail->crlf; + edmail_new->eoh_crlf = edmail->eoh_crlf; + + array_create(&edmail_new->mail.module_contexts, pool, + sizeof(void *), 5); + + edmail_new->mail.v = edit_mail_vfuncs; + edmail_new->mail.mail.seq = 1; + edmail_new->mail.mail.box = edmail->mail.mail.box; + edmail_new->mail.mail.transaction = edmail->mail.mail.transaction; + edmail_new->mail.wanted_fields = edmail->mail.wanted_fields; + edmail_new->mail.wanted_headers = edmail->mail.wanted_headers; + + edmail_new->stream = NULL; + + if (edmail->modified) { + field_idx = edmail->header_fields_head; + while (field_idx != NULL) { + struct _header_field_index *next = field_idx->next; + + field_idx_new = i_new(struct _header_field_index, 1); + + field_idx_new->header = edit_mail_header_clone( + edmail_new, field_idx->header->header); + + field_idx_new->field = field_idx->field; + _header_field_ref(field_idx_new->field); + + DLLIST2_APPEND(&edmail_new->header_fields_head, + &edmail_new->header_fields_tail, + field_idx_new); + + field_idx_new->header->count++; + if (field_idx->header->first == field_idx) + field_idx_new->header->first = field_idx_new; + if (field_idx->header->last == field_idx) + field_idx_new->header->last = field_idx_new; + + if (field_idx == edmail->header_fields_appended) { + edmail_new->header_fields_appended = + field_idx_new; + } + + field_idx = next; + } + + edmail_new->modified = TRUE; + } + + edmail_new->headers_parsed = edmail->headers_parsed; + edmail_new->parent = edmail; + + return edmail_new; +} + +void edit_mail_reset(struct edit_mail *edmail) +{ + struct _header_index *header_idx; + struct _header_field_index *field_idx; + + i_stream_unref(&edmail->stream); + + field_idx = edmail->header_fields_head; + while (field_idx != NULL) { + struct _header_field_index *next = field_idx->next; + + _header_field_unref(field_idx->field); + i_free(field_idx); + + field_idx = next; + } + + header_idx = edmail->headers_head; + while (header_idx != NULL) { + struct _header_index *next = header_idx->next; + + _header_unref(header_idx->header); + i_free(header_idx); + + header_idx = next; + } + + edmail->modified = FALSE; +} + +void edit_mail_unwrap(struct edit_mail **edmail) +{ + struct edit_mail *parent; + + i_assert((*edmail)->refcount > 0); + if (--(*edmail)->refcount != 0) + return; + + edit_mail_reset(*edmail); + i_stream_unref(&(*edmail)->wrapped_stream); + + parent = (*edmail)->parent; + + if (parent == NULL) { + mailbox_transaction_rollback(&(*edmail)->mail.mail.transaction); + mailbox_free(&(*edmail)->mail.mail.box); + edit_mail_raw_storage_drop(); + } + + pool_unref(&(*edmail)->mail.pool); + *edmail = NULL; + + if (parent != NULL) + edit_mail_unwrap(&parent); +} + +struct mail *edit_mail_get_mail(struct edit_mail *edmail) +{ + /* Return wrapped mail when nothing is modified yet */ + if (!edmail->modified) + return &edmail->wrapped->mail; + + return &edmail->mail.mail; +} + +/* + * Editing + */ + +static inline void edit_mail_modify(struct edit_mail *edmail) +{ + edmail->mail.mail.seq++; + edmail->modified = TRUE; + edmail->snapshot_modified = TRUE; +} + +/* Header modification */ + +static inline char *_header_value_unfold(const char *value) +{ + string_t *out; + unsigned int i; + + for (i = 0; value[i] != '\0'; i++) { + if (value[i] == '\r' || value[i] == '\n') + break; + } + if (value[i] == '\0') + return i_strdup(value); + + out = t_str_new(i + strlen(value+i) + 10); + str_append_data(out, value, i); + for (; value[i] != '\0'; i++) { + if (value[i] == '\n') { + i++; + if (value[i] == '\0') + break; + + switch (value[i]) { + case ' ': + str_append_c(out, ' '); + break; + case '\t': + default: + str_append_c(out, '\t'); + } + } else { + if (value[i] != '\r') + str_append_c(out, value[i]); + } + } + + return i_strndup(str_c(out), str_len(out)); +} + +static struct _header_index * +edit_mail_header_find(struct edit_mail *edmail, const char *field_name) +{ + struct _header_index *header_idx; + + header_idx = edmail->headers_head; + while (header_idx != NULL) { + if (strcasecmp(header_idx->header->name, field_name) == 0) + return header_idx; + + header_idx = header_idx->next; + } + + return NULL; +} + +static struct _header_index * +edit_mail_header_create(struct edit_mail *edmail, const char *field_name) +{ + struct _header_index *header_idx; + + header_idx = edit_mail_header_find(edmail, field_name); + if (header_idx == NULL) { + header_idx = i_new(struct _header_index, 1); + header_idx->header = _header_create(field_name); + + DLLIST2_APPEND(&edmail->headers_head, &edmail->headers_tail, + header_idx); + } + + return header_idx; +} + +static struct _header_index * +edit_mail_header_clone(struct edit_mail *edmail, struct _header *header) +{ + struct _header_index *header_idx; + + header_idx = edmail->headers_head; + while (header_idx != NULL) { + if (header_idx->header == header) + return header_idx; + + header_idx = header_idx->next; + } + + header_idx = i_new(struct _header_index, 1); + header_idx->header = header; + _header_ref(header); + DLLIST2_APPEND(&edmail->headers_head, &edmail->headers_tail, + header_idx); + + return header_idx; +} + +static struct _header_field_index * +edit_mail_header_field_create(struct edit_mail *edmail, const char *field_name, + const char *value) +{ + struct _header_index *header_idx; + struct _header *header; + struct _header_field_index *field_idx; + struct _header_field *field; + unsigned int lines; + + /* Get/create header index item */ + header_idx = edit_mail_header_create(edmail, field_name); + header = header_idx->header; + + /* Create new field index item */ + field_idx = i_new(struct _header_field_index, 1); + field_idx->header = header_idx; + field_idx->field = field = _header_field_create(header); + + /* Create header field data (folded if necessary) */ + T_BEGIN { + string_t *enc_value, *data; + + enc_value = t_str_new(strlen(field_name) + strlen(value) + 64); + data = t_str_new(strlen(field_name) + strlen(value) + 128); + + message_header_encode(value, enc_value); + + lines = rfc2822_header_append(data, field_name, + str_c(enc_value), edmail->crlf, + &field->body_offset); + + /* Copy to new field */ + field->data = i_strndup(str_data(data), str_len(data)); + field->size = str_len(data); + field->virtual_size = (edmail->crlf ? + field->size : field->size + lines); + field->lines = lines; + } T_END; + + /* Record original (utf8) value */ + field->utf8_value = _header_value_unfold(value); + + return field_idx; +} + +static void +edit_mail_header_field_delete(struct edit_mail *edmail, + struct _header_field_index *field_idx, + bool update_index) +{ + struct _header_index *header_idx = field_idx->header; + struct _header_field *field = field_idx->field; + + i_assert(header_idx != NULL); + + edmail->hdr_size.physical_size -= field->size; + edmail->hdr_size.virtual_size -= field->virtual_size; + edmail->hdr_size.lines -= field->lines; + + header_idx->count--; + if (update_index) { + if (header_idx->count == 0) { + DLLIST2_REMOVE(&edmail->headers_head, + &edmail->headers_tail, header_idx); + _header_unref(header_idx->header); + i_free(header_idx); + } else if (header_idx->first == field_idx) { + struct _header_field_index *hfield = + header_idx->first->next; + + while (hfield != NULL && hfield->header != header_idx) + hfield = hfield->next; + + i_assert(hfield != NULL); + header_idx->first = hfield; + } else if (header_idx->last == field_idx) { + struct _header_field_index *hfield = + header_idx->last->prev; + + while (hfield != NULL && hfield->header != header_idx) + hfield = hfield->prev; + + i_assert(hfield != NULL); + header_idx->last = hfield; + } + } + + DLLIST2_REMOVE(&edmail->header_fields_head, &edmail->header_fields_tail, + field_idx); + _header_field_unref(field_idx->field); + i_free(field_idx); +} + +static struct _header_field_index * +edit_mail_header_field_replace(struct edit_mail *edmail, + struct _header_field_index *field_idx, + const char *newname, const char *newvalue, + bool update_index) +{ + struct _header_field_index *field_idx_new; + struct _header_index *header_idx = field_idx->header, *header_idx_new; + struct _header_field *field = field_idx->field, *field_new; + + i_assert(header_idx != NULL); + i_assert(newname != NULL || newvalue != NULL); + + if (newname == NULL) + newname = header_idx->header->name; + if (newvalue == NULL) + newvalue = field_idx->field->utf8_value; + field_idx_new = edit_mail_header_field_create( + edmail, newname, newvalue); + field_new = field_idx_new->field; + header_idx_new = field_idx_new->header; + + edmail->hdr_size.physical_size -= field->size; + edmail->hdr_size.virtual_size -= field->virtual_size; + edmail->hdr_size.lines -= field->lines; + + edmail->hdr_size.physical_size += field_new->size; + edmail->hdr_size.virtual_size += field_new->virtual_size; + edmail->hdr_size.lines += field_new->lines; + + /* Replace header field index */ + field_idx_new->prev = field_idx->prev; + field_idx_new->next = field_idx->next; + if (field_idx->prev != NULL) + field_idx->prev->next = field_idx_new; + if (field_idx->next != NULL) + field_idx->next->prev = field_idx_new; + if (edmail->header_fields_head == field_idx) + edmail->header_fields_head = field_idx_new; + if (edmail->header_fields_tail == field_idx) + edmail->header_fields_tail = field_idx_new; + + if (header_idx_new == header_idx) { + if (header_idx->first == field_idx) + header_idx->first = field_idx_new; + if (header_idx->last == field_idx) + header_idx->last = field_idx_new; + } else { + header_idx->count--; + header_idx_new->count++; + + if (update_index) { + if (header_idx->count == 0) { + DLLIST2_REMOVE(&edmail->headers_head, + &edmail->headers_tail, + header_idx); + _header_unref(header_idx->header); + i_free(header_idx); + } else if (header_idx->first == field_idx) { + struct _header_field_index *hfield = + header_idx->first->next; + + while (hfield != NULL && + hfield->header != header_idx) + hfield = hfield->next; + + i_assert(hfield != NULL); + header_idx->first = hfield; + } else if (header_idx->last == field_idx) { + struct _header_field_index *hfield = + header_idx->last->prev; + + while (hfield != NULL && + hfield->header != header_idx) + hfield = hfield->prev; + + i_assert(hfield != NULL); + header_idx->last = hfield; + } + if (header_idx_new->count > 0) { + struct _header_field_index *hfield; + + hfield = edmail->header_fields_head; + while (hfield != NULL && + hfield->header != header_idx_new) + hfield = hfield->next; + + i_assert(hfield != NULL); + header_idx_new->first = hfield; + + hfield = edmail->header_fields_tail; + while (hfield != NULL && + hfield->header != header_idx_new) + hfield = hfield->prev; + + i_assert(hfield != NULL); + header_idx_new->last = hfield; + } + } + } + + _header_field_unref(field_idx->field); + i_free(field_idx); + return field_idx_new; +} + +static inline char * +_header_decode(const unsigned char *hdr_data, size_t hdr_data_len) +{ + string_t *str = t_str_new(512); + + /* hdr_data is already unfolded */ + + /* Decode MIME encoded-words. */ + message_header_decode_utf8((const unsigned char *)hdr_data, + hdr_data_len, str, NULL); + return i_strdup(str_c(str)); +} + +static int edit_mail_headers_parse(struct edit_mail *edmail) +{ + struct message_header_parser_ctx *hparser; + enum message_header_parser_flags hparser_flags = + MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP | + MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE; + struct message_header_line *hdr; + struct _header_index *header_idx; + struct _header_field_index *head = NULL, *tail = NULL, *current; + string_t *hdr_data; + uoff_t offset = 0, body_offset = 0, vsize_diff = 0; + unsigned int lines = 0; + int ret; + + if (edmail->headers_parsed) + return 1; + + i_stream_seek(edmail->wrapped_stream, 0); + hparser = message_parse_header_init(edmail->wrapped_stream, NULL, + hparser_flags); + + T_BEGIN { + hdr_data = t_str_new(1024); + while ((ret = message_parse_header_next(hparser, &hdr)) > 0) { + struct _header_field_index *field_idx_new; + struct _header_field *field; + + if (hdr->eoh) { + /* Record whether header ends in CRLF or LF */ + edmail->eoh_crlf = hdr->crlf_newline; + } + + if (hdr == NULL || hdr->eoh) + break; + + /* Skip bad headers */ + if (hdr->name_len == 0) + continue; + /* We deny the existence of any `Content-Length:' + header. This header is non-standard and it can wreak + havok when the message is modified. + */ + if (strcasecmp(hdr->name, "Content-Length" ) == 0) + continue; + + if (hdr->continued) { + /* Continued line of folded header */ + buffer_append(hdr_data, hdr->value, + hdr->value_len); + } else { + /* First line of header */ + offset = hdr->name_offset; + body_offset = hdr->name_len + hdr->middle_len; + str_truncate(hdr_data, 0); + buffer_append(hdr_data, hdr->name, + hdr->name_len); + buffer_append(hdr_data, hdr->middle, + hdr->middle_len); + buffer_append(hdr_data, hdr->value, + hdr->value_len); + lines = 0; + vsize_diff = 0; + } + + if (!hdr->no_newline) { + lines++; + + if (hdr->crlf_newline) { + buffer_append(hdr_data, "\r\n", 2); + } else { + buffer_append(hdr_data, "\n", 1); + vsize_diff++; + } + } + + if (hdr->continues) { + hdr->use_full_value = TRUE; + continue; + } + + /* Create new header field index entry */ + + field_idx_new = i_new(struct _header_field_index, 1); + + header_idx = edit_mail_header_create(edmail, hdr->name); + header_idx->count++; + field_idx_new->header = header_idx; + field_idx_new->field = field = + _header_field_create(header_idx->header); + + i_assert(body_offset > 0); + field->body_offset = body_offset; + + field->utf8_value = _header_decode(hdr->full_value, + hdr->full_value_len); + + field->size = str_len(hdr_data); + field->virtual_size = field->size + vsize_diff; + field->data = i_strndup(str_data(hdr_data), + field->size); + field->offset = offset; + field->lines = lines; + + DLLIST2_APPEND(&head, &tail, field_idx_new); + + edmail->hdr_size.physical_size += field->size; + edmail->hdr_size.virtual_size += field->virtual_size; + edmail->hdr_size.lines += lines; + } + } T_END; + + message_parse_header_deinit(&hparser); + + /* Blocking i/o required */ + i_assert(ret != 0); + + if (ret < 0 && edmail->wrapped_stream->stream_errno != 0) { + /* Error; clean up */ + i_error("read(%s) failed: %s", + i_stream_get_name(edmail->wrapped_stream), + i_stream_get_error(edmail->wrapped_stream)); + current = head; + while (current != NULL) { + struct _header_field_index *next = current->next; + + _header_field_unref(current->field); + i_free(current); + + current = next; + } + + return ret; + } + + /* Insert header field index items in main list */ + if (head != NULL && tail != NULL) { + if (edmail->header_fields_appended != NULL) { + if (edmail->header_fields_head != + edmail->header_fields_appended) { + edmail->header_fields_appended->prev->next = head; + head->prev = edmail->header_fields_appended->prev; + } else { + edmail->header_fields_head = head; + } + + tail->next = edmail->header_fields_appended; + edmail->header_fields_appended->prev = tail; + } else if (edmail->header_fields_tail != NULL) { + edmail->header_fields_tail->next = head; + head->prev = edmail->header_fields_tail; + edmail->header_fields_tail = tail; + } else { + edmail->header_fields_head = head; + edmail->header_fields_tail = tail; + } + } + + /* Rebuild header index */ + current = edmail->header_fields_head; + while (current != NULL) { + if (current->header->first == NULL) + current->header->first = current; + current->header->last = current; + + current = current->next; + } + + /* Clear appended headers */ + edmail->header_fields_appended = NULL; + edmail->appended_hdr_size.physical_size = 0; + edmail->appended_hdr_size.virtual_size = 0; + edmail->appended_hdr_size.lines = 0; + + /* Do not parse headers again */ + edmail->headers_parsed = TRUE; + + return 1; +} + +void edit_mail_header_add(struct edit_mail *edmail, const char *field_name, + const char *value, bool last) +{ + struct _header_index *header_idx; + struct _header_field_index *field_idx; + struct _header_field *field; + + edit_mail_modify(edmail); + + field_idx = edit_mail_header_field_create(edmail, field_name, value); + header_idx = field_idx->header; + field = field_idx->field; + + /* Add it to the header field index */ + if (last) { + DLLIST2_APPEND(&edmail->header_fields_head, + &edmail->header_fields_tail, field_idx); + + header_idx->last = field_idx; + if (header_idx->first == NULL) + header_idx->first = field_idx; + + if (!edmail->headers_parsed) { + if (edmail->header_fields_appended == NULL) { + /* Record beginning of appended headers */ + edmail->header_fields_appended = field_idx; + } + + edmail->appended_hdr_size.physical_size += field->size; + edmail->appended_hdr_size.virtual_size += field->virtual_size; + edmail->appended_hdr_size.lines += field->lines; + } + } else { + DLLIST2_PREPEND(&edmail->header_fields_head, + &edmail->header_fields_tail, field_idx); + + header_idx->first = field_idx; + if (header_idx->last == NULL) + header_idx->last = field_idx; + } + + header_idx->count++; + + edmail->hdr_size.physical_size += field->size; + edmail->hdr_size.virtual_size += field->virtual_size; + edmail->hdr_size.lines += field->lines; +} + +int edit_mail_header_delete(struct edit_mail *edmail, const char *field_name, + int index) +{ + struct _header_index *header_idx; + struct _header_field_index *field_idx; + int pos = 0; + int ret = 0; + + /* Make sure headers are parsed */ + if (edit_mail_headers_parse(edmail) <= 0) + return -1; + + /* Find the header entry */ + header_idx = edit_mail_header_find(edmail, field_name); + if (header_idx == NULL) { + /* Not found */ + return 0; + } + + /* Signal modification */ + edit_mail_modify(edmail); + + /* Iterate through all header fields and remove those that match */ + field_idx = (index >= 0 ? header_idx->first : header_idx->last); + while (field_idx != NULL) { + struct _header_field_index *next = + (index >= 0 ? field_idx->next : field_idx->prev); + + if (field_idx->field->header == header_idx->header) { + bool final; + + if (index >= 0) { + pos++; + final = (header_idx->last == field_idx); + } else { + pos--; + final = (header_idx->first == field_idx); + } + + if (index == 0 || index == pos) { + if (header_idx->first == field_idx) + header_idx->first = NULL; + if (header_idx->last == field_idx) + header_idx->last = NULL; + edit_mail_header_field_delete( + edmail, field_idx, FALSE); + ret++; + } + + if (final || (index != 0 && index == pos)) + break; + } + + field_idx = next; + } + + if (index == 0 || header_idx->count == 0) { + DLLIST2_REMOVE(&edmail->headers_head, + &edmail->headers_tail, header_idx); + _header_unref(header_idx->header); + i_free(header_idx); + } else if (header_idx->first == NULL || header_idx->last == NULL) { + struct _header_field_index *current = + edmail->header_fields_head; + + while (current != NULL) { + if (current->header == header_idx) { + if (header_idx->first == NULL) + header_idx->first = current; + header_idx->last = current; + } + current = current->next; + } + } + + return ret; +} + +int edit_mail_header_replace(struct edit_mail *edmail, + const char *field_name, int index, + const char *newname, const char *newvalue) +{ + struct _header_index *header_idx, *header_idx_new; + struct _header_field_index *field_idx, *field_idx_new; + int pos = 0; + int ret = 0; + + /* Make sure headers are parsed */ + if (edit_mail_headers_parse(edmail) <= 0) + return -1; + + /* Find the header entry */ + header_idx = edit_mail_header_find(edmail, field_name); + if (header_idx == NULL) { + /* Not found */ + return 0; + } + + /* Signal modification */ + edit_mail_modify(edmail); + + /* Iterate through all header fields and replace those that match */ + field_idx = (index >= 0 ? header_idx->first : header_idx->last); + field_idx_new = NULL; + while (field_idx != NULL) { + struct _header_field_index *next = + (index >= 0 ? field_idx->next : field_idx->prev); + + if (field_idx->field->header == header_idx->header) { + bool final; + + if (index >= 0) { + pos++; + final = (header_idx->last == field_idx); + } else { + pos--; + final = (header_idx->first == field_idx); + } + + if (index == 0 || index == pos) { + if (header_idx->first == field_idx) + header_idx->first = NULL; + if (header_idx->last == field_idx) + header_idx->last = NULL; + field_idx_new = edit_mail_header_field_replace( + edmail, field_idx, newname, newvalue, + FALSE); + ret++; + } + + if (final || (index != 0 && index == pos)) + break; + } + + field_idx = next; + } + + /* Update old header index */ + if (header_idx->count == 0) { + DLLIST2_REMOVE(&edmail->headers_head, &edmail->headers_tail, + header_idx); + _header_unref(header_idx->header); + i_free(header_idx); + } else if (header_idx->first == NULL || header_idx->last == NULL) { + struct _header_field_index *current = + edmail->header_fields_head; + + while (current != NULL) { + if (current->header == header_idx) { + if (header_idx->first == NULL) + header_idx->first = current; + header_idx->last = current; + } + current = current->next; + } + } + + /* Update new header index */ + if (field_idx_new != NULL) { + struct _header_field_index *current = + edmail->header_fields_head; + + header_idx_new = field_idx_new->header; + while (current != NULL) { + if (current->header == header_idx_new) { + if (header_idx_new->first == NULL) + header_idx_new->first = current; + header_idx_new->last = current; + } + current = current->next; + } + } + + return ret; +} + +struct edit_mail_header_iter +{ + struct edit_mail *mail; + struct _header_index *header; + struct _header_field_index *current; + + bool reverse:1; +}; + +int edit_mail_headers_iterate_init(struct edit_mail *edmail, + const char *field_name, bool reverse, + struct edit_mail_header_iter **edhiter_r) +{ + struct edit_mail_header_iter *edhiter; + struct _header_index *header_idx = NULL; + struct _header_field_index *current = NULL; + + /* Make sure headers are parsed */ + if (edit_mail_headers_parse(edmail) <= 0) { + /* Failure */ + return -1; + } + + header_idx = edit_mail_header_find(edmail, field_name); + + if (field_name != NULL && header_idx == NULL) { + current = NULL; + } else if (!reverse) { + current = (header_idx != NULL ? + header_idx->first : edmail->header_fields_head); + } else { + current = (header_idx != NULL ? + header_idx->last : edmail->header_fields_tail); + if (current->header == NULL) + current = current->prev; + } + + if (current == NULL) + return 0; + + edhiter = i_new(struct edit_mail_header_iter, 1); + edhiter->mail = edmail; + edhiter->header = header_idx; + edhiter->reverse = reverse; + edhiter->current = current; + + *edhiter_r = edhiter; + return 1; +} + +void edit_mail_headers_iterate_deinit(struct edit_mail_header_iter **edhiter) +{ + i_free(*edhiter); + *edhiter = NULL; +} + +void edit_mail_headers_iterate_get(struct edit_mail_header_iter *edhiter, + const char **value_r) +{ + const char *raw; + int i; + + i_assert(edhiter->current != NULL && edhiter->current->header != NULL); + + raw = edhiter->current->field->utf8_value; + for (i = strlen(raw)-1; i >= 0; i--) { + if (raw[i] != ' ' && raw[i] != '\t') + break; + } + + *value_r = t_strndup(raw, i+1); +} + +bool edit_mail_headers_iterate_next(struct edit_mail_header_iter *edhiter) +{ + if (edhiter->current == NULL) + return FALSE; + + do { + edhiter->current = (!edhiter->reverse ? + edhiter->current->next : + edhiter->current->prev ); + } while (edhiter->current != NULL && edhiter->current->header != NULL && + edhiter->header != NULL && + edhiter->current->header != edhiter->header); + + return (edhiter->current != NULL && edhiter->current->header != NULL); +} + +bool edit_mail_headers_iterate_remove(struct edit_mail_header_iter *edhiter) +{ + struct _header_field_index *field_idx; + bool next; + + i_assert(edhiter->current != NULL && edhiter->current->header != NULL); + + edit_mail_modify(edhiter->mail); + + field_idx = edhiter->current; + next = edit_mail_headers_iterate_next(edhiter); + edit_mail_header_field_delete(edhiter->mail, field_idx, TRUE); + + return next; +} + +bool edit_mail_headers_iterate_replace(struct edit_mail_header_iter *edhiter, + const char *newname, + const char *newvalue) +{ + struct _header_field_index *field_idx; + bool next; + + i_assert(edhiter->current != NULL && edhiter->current->header != NULL); + + edit_mail_modify(edhiter->mail); + + field_idx = edhiter->current; + next = edit_mail_headers_iterate_next(edhiter); + edit_mail_header_field_replace(edhiter->mail, field_idx, + newname, newvalue, TRUE); + + return next; +} + +/* Body modification */ + +// FIXME: implement + +/* + * Mail API + */ + +static void edit_mail_close(struct mail *mail) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + edmail->wrapped->v.close(&edmail->wrapped->mail); +} + +static void edit_mail_free(struct mail *mail) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + edmail->wrapped->v.free(&edmail->wrapped->mail); + + edit_mail_unwrap(&edmail); +} + +static void +edit_mail_set_seq(struct mail *mail ATTR_UNUSED, uint32_t seq ATTR_UNUSED, + bool saving ATTR_UNUSED) +{ + i_panic("edit_mail_set_seq() not implemented"); +} + +static bool ATTR_NORETURN +edit_mail_set_uid(struct mail *mail ATTR_UNUSED, uint32_t uid ATTR_UNUSED) +{ + i_panic("edit_mail_set_uid() not implemented"); +} + +static void edit_mail_set_uid_cache_updates(struct mail *mail, bool set) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + edmail->wrapped->v.set_uid_cache_updates(&edmail->wrapped->mail, set); +} + +static void +edit_mail_add_temp_wanted_fields( + struct mail *mail ATTR_UNUSED, enum mail_fetch_field fields ATTR_UNUSED, + struct mailbox_header_lookup_ctx *headers ATTR_UNUSED) +{ + /* Nothing */ +} + +static enum mail_flags edit_mail_get_flags(struct mail *mail) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + return edmail->wrapped->v.get_flags(&edmail->wrapped->mail); +} + +static const char *const *edit_mail_get_keywords(struct mail *mail) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + return edmail->wrapped->v.get_keywords(&edmail->wrapped->mail); +} + +static const ARRAY_TYPE(keyword_indexes) * +edit_mail_get_keyword_indexes(struct mail *mail) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + return edmail->wrapped->v.get_keyword_indexes(&edmail->wrapped->mail); +} + +static uint64_t edit_mail_get_modseq(struct mail *mail) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + return edmail->wrapped->v.get_modseq(&edmail->wrapped->mail); +} + +static uint64_t edit_mail_get_pvt_modseq(struct mail *mail) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + return edmail->wrapped->v.get_pvt_modseq(&edmail->wrapped->mail); +} + +static int edit_mail_get_parts(struct mail *mail, struct message_part **parts_r) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + return edmail->wrapped->v.get_parts(&edmail->wrapped->mail, parts_r); +} + +static int +edit_mail_get_date(struct mail *mail, time_t *date_r, int *timezone_r) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + return edmail->wrapped->v.get_date(&edmail->wrapped->mail, + date_r, timezone_r); +} + +static int edit_mail_get_received_date(struct mail *mail, time_t *date_r) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + return edmail->wrapped->v.get_received_date(&edmail->wrapped->mail, + date_r); +} + +static int edit_mail_get_save_date(struct mail *mail, time_t *date_r) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + return edmail->wrapped->v.get_save_date(&edmail->wrapped->mail, date_r); +} + +static int edit_mail_get_virtual_size(struct mail *mail, uoff_t *size_r) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + if (!edmail->headers_parsed) { + *size_r = (edmail->wrapped_hdr_size.virtual_size + + edmail->wrapped_body_size.virtual_size); + + if (!edmail->modified) + return 0; + } else { + *size_r = edmail->wrapped_body_size.virtual_size + 2; + } + + *size_r += (edmail->hdr_size.virtual_size + + edmail->body_size.virtual_size); + return 0; +} + +static int edit_mail_get_physical_size(struct mail *mail, uoff_t *size_r) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + *size_r = 0; + if (!edmail->headers_parsed) { + *size_r = (edmail->wrapped_hdr_size.physical_size + + edmail->wrapped_body_size.physical_size); + + if (!edmail->modified) + return 0; + } else { + *size_r = (edmail->wrapped_body_size.physical_size + + (edmail->eoh_crlf ? 2 : 1)); + } + + *size_r += (edmail->hdr_size.physical_size + + edmail->body_size.physical_size); + return 0; +} + +static int +edit_mail_get_first_header(struct mail *mail, const char *field_name, + bool decode_to_utf8, const char **value_r) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + struct _header_index *header_idx; + struct _header_field *field; + int ret; + + /* Check whether mail headers were modified at all */ + if (!edmail->modified || edmail->headers_head == NULL) { + /* Unmodified */ + return edmail->wrapped->v.get_first_header( + &edmail->wrapped->mail, field_name, decode_to_utf8, + value_r); + } + + /* Try to find modified header */ + header_idx = edit_mail_header_find(edmail, field_name); + if (header_idx == NULL || header_idx->count == 0 ) { + if (!edmail->headers_parsed) { + /* No new header */ + return edmail->wrapped->v.get_first_header( + &edmail->wrapped->mail, field_name, + decode_to_utf8, value_r); + } + + *value_r = NULL; + return 0; + } + + /* Get the first occurrence */ + if (edmail->header_fields_appended == NULL) { + /* There are no appended headers, so first is found directly */ + field = header_idx->first->field; + } else { + struct _header_field_index *field_idx; + + /* Scan prepended headers */ + field_idx = edmail->header_fields_head; + while (field_idx != NULL) { + if (field_idx->header == header_idx) + break; + + if (field_idx == edmail->header_fields_appended) { + field_idx = NULL; + break; + } + field_idx = field_idx->next; + } + + if (field_idx == NULL) { + /* Check original message */ + ret = edmail->wrapped->v.get_first_header( + &edmail->wrapped->mail, field_name, + decode_to_utf8, value_r); + if (ret != 0) + return ret; + + /* Use first (apparently appended) header */ + field = header_idx->first->field; + } else { + field = field_idx->field; + } + } + + if (decode_to_utf8) + *value_r = field->utf8_value; + else + *value_r = (const char *)(field->data + field->body_offset); + return 1; +} + +static int +edit_mail_get_headers(struct mail *mail, const char *field_name, + bool decode_to_utf8, const char *const **value_r) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + struct _header_index *header_idx; + struct _header_field_index *field_idx; + const char *const *headers; + ARRAY(const char *) header_values; + + if (!edmail->modified || edmail->headers_head == NULL) { + /* Unmodified */ + return edmail->wrapped->v.get_headers( + &edmail->wrapped->mail, field_name, decode_to_utf8, + value_r); + } + + header_idx = edit_mail_header_find(edmail, field_name); + if (header_idx == NULL || header_idx->count == 0 ) { + if (!edmail->headers_parsed) { + /* No new header */ + return edmail->wrapped->v.get_headers( + &edmail->wrapped->mail, field_name, + decode_to_utf8, value_r); + } + + p_array_init(&header_values, edmail->mail.pool, 1); + (void)array_append_space(&header_values); + *value_r = array_idx(&header_values, 0); + return 0; + } + + /* Merge */ + + /* Read original headers too if message headers are not parsed */ + headers = NULL; + if (!edmail->headers_parsed && + edmail->wrapped->v.get_headers(&edmail->wrapped->mail, field_name, + decode_to_utf8, &headers) < 0) + return -1; + + /* Fill result array */ + p_array_init(&header_values, edmail->mail.pool, 32); + field_idx = header_idx->first; + while (field_idx != NULL) { + /* If current field is the first appended one, we need to add + original headers first. + */ + if (field_idx == edmail->header_fields_appended && + headers != NULL) { + while (*headers != NULL) { + array_append(&header_values, headers, 1); + headers++; + } + } + + /* Add modified header to the list */ + if (field_idx->field->header == header_idx->header) { + struct _header_field *field = field_idx->field; + + const char *value; + if (decode_to_utf8) + value = field->utf8_value; + else { + value = (const char *)(field->data + + field->body_offset); + } + + array_append(&header_values, &value, 1); + + if (field_idx == header_idx->last) + break; + } + + field_idx = field_idx->next; + } + + /* Add original headers if necessary */ + if (headers != NULL) { + while (*headers != NULL) { + array_append(&header_values, headers, 1); + headers++; + } + } + + (void)array_append_space(&header_values); + *value_r = array_idx(&header_values, 0); + return 1; +} + +static int ATTR_NORETURN +edit_mail_get_header_stream( + struct mail *mail ATTR_UNUSED, + struct mailbox_header_lookup_ctx *headers ATTR_UNUSED, + struct istream **stream_r ATTR_UNUSED) +{ + // FIXME: implement! + i_panic("edit_mail_get_header_stream() not implemented"); +} + +static int +edit_mail_get_stream(struct mail *mail, bool get_body ATTR_UNUSED, + struct message_size *hdr_size, + struct message_size *body_size, struct istream **stream_r) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + if (edmail->stream == NULL) + edmail->stream = edit_mail_istream_create(edmail); + + if (hdr_size != NULL) { + *hdr_size = edmail->wrapped_hdr_size; + hdr_size->physical_size += edmail->hdr_size.physical_size; + hdr_size->virtual_size += edmail->hdr_size.virtual_size; + hdr_size->lines += edmail->hdr_size.lines; + } + + if (body_size != NULL) + *body_size = edmail->wrapped_body_size; + + *stream_r = edmail->stream; + i_stream_seek(edmail->stream, 0); + + return 0; +} + +static int +edit_mail_get_special(struct mail *mail, enum mail_fetch_field field, + const char **value_r) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + if (edmail->modified) { + /* Block certain fields when modified */ + + switch (field) { + case MAIL_FETCH_GUID: + /* This is in essence a new message */ + *value_r = ""; + return 0; + case MAIL_FETCH_STORAGE_ID: + /* Prevent hardlink copying */ + *value_r = ""; + return 0; + default: + break; + } + } + + return edmail->wrapped->v.get_special(&edmail->wrapped->mail, + field, value_r); +} + +static int +edit_mail_get_backend_mail(struct mail *mail, struct mail **real_mail_r) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + *real_mail_r = edit_mail_get_mail(edmail); + return 0; +} + +static void +edit_mail_update_flags(struct mail *mail, enum modify_type modify_type, + enum mail_flags flags) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + edmail->wrapped->v.update_flags(&edmail->wrapped->mail, + modify_type, flags); +} + +static void +edit_mail_update_keywords(struct mail *mail, enum modify_type modify_type, + struct mail_keywords *keywords) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + edmail->wrapped->v.update_keywords(&edmail->wrapped->mail, + modify_type, keywords); +} + +static void edit_mail_update_modseq(struct mail *mail, uint64_t min_modseq) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + edmail->wrapped->v.update_modseq(&edmail->wrapped->mail, min_modseq); +} + +static void +edit_mail_update_pvt_modseq(struct mail *mail, uint64_t min_pvt_modseq) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + edmail->wrapped->v.update_pvt_modseq(&edmail->wrapped->mail, + min_pvt_modseq); +} + +static void edit_mail_update_pop3_uidl(struct mail *mail, const char *uidl) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + if (edmail->wrapped->v.update_pop3_uidl != NULL) { + edmail->wrapped->v.update_pop3_uidl( + &edmail->wrapped->mail, uidl); + } +} + +static void edit_mail_expunge(struct mail *mail ATTR_UNUSED) +{ + /* NOOP */ +} + +static void +edit_mail_set_cache_corrupted(struct mail *mail, enum mail_fetch_field field, + const char *reason) +{ + struct edit_mail *edmail = (struct edit_mail *)mail; + + edmail->wrapped->v.set_cache_corrupted(&edmail->wrapped->mail, + field, reason); +} + +static struct mail_vfuncs edit_mail_vfuncs = { + edit_mail_close, + edit_mail_free, + edit_mail_set_seq, + edit_mail_set_uid, + edit_mail_set_uid_cache_updates, + NULL, + NULL, + edit_mail_add_temp_wanted_fields, + edit_mail_get_flags, + edit_mail_get_keywords, + edit_mail_get_keyword_indexes, + edit_mail_get_modseq, + edit_mail_get_pvt_modseq, + edit_mail_get_parts, + edit_mail_get_date, + edit_mail_get_received_date, + edit_mail_get_save_date, + edit_mail_get_virtual_size, + edit_mail_get_physical_size, + edit_mail_get_first_header, + edit_mail_get_headers, + edit_mail_get_header_stream, + edit_mail_get_stream, + index_mail_get_binary_stream, + edit_mail_get_special, + edit_mail_get_backend_mail, + edit_mail_update_flags, + edit_mail_update_keywords, + edit_mail_update_modseq, + edit_mail_update_pvt_modseq, + edit_mail_update_pop3_uidl, + edit_mail_expunge, + edit_mail_set_cache_corrupted, + NULL, +}; + +/* + * Edit Mail Stream + */ + +struct edit_mail_istream { + struct istream_private istream; + pool_t pool; + + struct edit_mail *mail; + + struct _header_field_index *cur_header; + uoff_t cur_header_v_offset; + + bool parent_buffer:1; + bool header_read:1; + bool eof:1; +}; + +static void edit_mail_istream_destroy(struct iostream_private *stream) +{ + struct edit_mail_istream *edstream = + (struct edit_mail_istream *)stream; + + i_stream_unref(&edstream->istream.parent); + i_stream_free_buffer(&edstream->istream); + pool_unref(&edstream->pool); +} + +static ssize_t +merge_from_parent(struct edit_mail_istream *edstream, uoff_t parent_v_offset, + uoff_t parent_end_v_offset, uoff_t copy_v_offset) +{ + struct istream_private *stream = &edstream->istream; + uoff_t v_offset, append_v_offset; + const unsigned char *data; + size_t pos, cur_pos, parent_bytes_left; + bool parent_buffer = edstream->parent_buffer; + ssize_t ret; + + i_assert(parent_v_offset <= parent_end_v_offset); + edstream->parent_buffer = FALSE; + + v_offset = stream->istream.v_offset; + if (v_offset >= copy_v_offset) { + i_assert((v_offset - copy_v_offset) <= parent_end_v_offset); + if ((v_offset - copy_v_offset) == parent_end_v_offset) { + /* Parent data is all read */ + return 0; + } + } + + /* Determine where we are appending more data to the stream */ + append_v_offset = v_offset + (stream->pos - stream->skip); + + if (v_offset >= copy_v_offset) { + /* Parent buffer used */ + cur_pos = (stream->pos - stream->skip); + parent_v_offset += (v_offset - copy_v_offset); + } else { + cur_pos = 0; + i_assert(append_v_offset >= copy_v_offset); + parent_v_offset += (append_v_offset - copy_v_offset); + } + + /* Seek parent to required position */ + i_stream_seek(stream->parent, parent_v_offset); + + /* Read from parent */ + data = i_stream_get_data(stream->parent, &pos); + if (pos > cur_pos) + ret = 0; + else do { + /* Use normal read here, since parent data can be returned + directly to caller. */ + ret = i_stream_read(stream->parent); + + stream->istream.stream_errno = stream->parent->stream_errno; + stream->istream.eof = stream->parent->eof; + edstream->eof = stream->parent->eof; + data = i_stream_get_data(stream->parent, &pos); + /* Check again, in case the parent stream had been seeked + backwards and the previous read() didn't get us far + enough. */ + } while (pos <= cur_pos && ret > 0); + + /* Don't read beyond parent end offset */ + if (parent_end_v_offset != (uoff_t)-1) { + parent_bytes_left = (size_t)(parent_end_v_offset - + parent_v_offset); + if (pos >= parent_bytes_left) { + pos = parent_bytes_left; + } + } + + if (v_offset < copy_v_offset || ret == -2 || + (parent_buffer && (append_v_offset + 1) >= parent_end_v_offset)) { + /* Merging with our local buffer; copying data from parent */ + if (pos > 0) { + size_t avail; + + if (parent_buffer) { + stream->pos = stream->skip = 0; + stream->buffer = NULL; + } + if (!i_stream_try_alloc(stream, pos, &avail)) + return -2; + pos = (pos > avail ? avail : pos); + + memcpy(stream->w_buffer + stream->pos, data, pos); + stream->pos += pos; + stream->buffer = stream->w_buffer; + + if (cur_pos >= pos) + ret = 0; + else + ret = (ssize_t)(pos - cur_pos); + } else { + ret = (ret == 0 ? 0 : -1); + } + } else { + /* Just passing buffers from parent; no copying */ + ret = (pos > cur_pos ? + (ssize_t)(pos - cur_pos) : (ret == 0 ? 0 : -1)); + stream->buffer = data; + stream->pos = pos; + stream->skip = 0; + edstream->parent_buffer = TRUE; + } + + i_assert(ret != -1 || stream->istream.eof || + stream->istream.stream_errno != 0); + return ret; +} + +static ssize_t merge_modified_headers(struct edit_mail_istream *edstream) +{ + struct istream_private *stream = &edstream->istream; + struct edit_mail *edmail = edstream->mail; + uoff_t v_offset = stream->istream.v_offset, append_v_offset; + size_t appended, written, avail, size; + + if (edstream->cur_header == NULL) { + /* No (more) headers */ + return 0; + } + + /* Caller must already have committed remaining parent data to + our stream buffer. */ + i_assert(!edstream->parent_buffer); + + /* Add modified headers to buffer */ + written = 0; + while (edstream->cur_header != NULL) { + size_t wsize; + + /* Determine what part of the header was already buffered */ + append_v_offset = v_offset + (stream->pos - stream->skip); + i_assert(append_v_offset >= edstream->cur_header_v_offset); + if (append_v_offset >= edstream->cur_header_v_offset) + appended = (size_t)(append_v_offset - + edstream->cur_header_v_offset); + else + appended = 0; + i_assert(appended <= edstream->cur_header->field->size); + + /* Determine how much we want to write */ + size = edstream->cur_header->field->size - appended; + if (size > 0) { + /* Determine how much we can write */ + if (!i_stream_try_alloc(stream, size, &avail)) { + if (written == 0) + return -2; + break; + } + wsize = (size >= avail ? avail : size); + + /* Write (part of) the header to buffer */ + memcpy(stream->w_buffer + stream->pos, + edstream->cur_header->field->data + appended, + wsize); + stream->pos += wsize; + stream->buffer = stream->w_buffer; + written += wsize; + + if (wsize < size) { + /* Could not write whole header; finish here */ + break; + } + } + + /* Skip to next header */ + edstream->cur_header_v_offset += + edstream->cur_header->field->size; + edstream->cur_header = edstream->cur_header->next; + + /* Stop at end of prepended headers if original header is left + unparsed */ + if (!edmail->headers_parsed && + edstream->cur_header == edmail->header_fields_appended) + edstream->cur_header = NULL; + } + + if (edstream->cur_header == NULL) { + /* Clear offset too, just to be tidy */ + edstream->cur_header_v_offset = 0; + } + + i_assert(written > 0); + return (ssize_t)written; +} + +static ssize_t edit_mail_istream_read(struct istream_private *stream) +{ + struct edit_mail_istream *edstream = + (struct edit_mail_istream *)stream; + struct edit_mail *edmail = edstream->mail; + uoff_t v_offset, append_v_offset; + uoff_t parent_v_offset, parent_end_v_offset, copy_v_offset; + uoff_t prep_hdr_size, hdr_size; + ssize_t ret = 0; + + if (edstream->eof) { + stream->istream.eof = TRUE; + return -1; + } + + if (edstream->parent_buffer && stream->skip == stream->pos) { + edstream->parent_buffer = FALSE; + stream->pos = stream->skip = 0; + stream->buffer = NULL; + } + + /* Merge prepended headers */ + if (!edstream->parent_buffer) { + ret = merge_modified_headers(edstream); + if (ret != 0) + return ret; + } + v_offset = stream->istream.v_offset; + append_v_offset = v_offset + (stream->pos - stream->skip); + + if (!edmail->headers_parsed && edmail->header_fields_appended != NULL && + !edstream->header_read) { + /* Output headers from original stream */ + + /* Size of the prepended header */ + i_assert(edmail->hdr_size.physical_size >= + edmail->appended_hdr_size.physical_size); + prep_hdr_size = (edmail->hdr_size.physical_size - + edmail->appended_hdr_size.physical_size); + + /* Calculate offset of header end or appended header. Any final + CR is dealt with later. + */ + hdr_size = (prep_hdr_size + + edmail->wrapped_hdr_size.physical_size); + i_assert(hdr_size > 0); + if (append_v_offset <= (hdr_size - 1) && + edmail->wrapped_hdr_size.physical_size > 0) { + parent_v_offset = stream->parent_start_offset; + parent_end_v_offset = + (stream->parent_start_offset + + edmail->wrapped_hdr_size.physical_size - 1); + copy_v_offset = prep_hdr_size; + + ret = merge_from_parent(edstream, parent_v_offset, + parent_end_v_offset, + copy_v_offset); + if (ret < 0) + return ret; + append_v_offset = (v_offset + + (stream->pos - stream->skip)); + i_assert(append_v_offset <= hdr_size - 1); + + if (append_v_offset == hdr_size - 1) { + /* Strip final CR too when it is present */ + if (stream->buffer != NULL && + stream->buffer[stream->pos-1] == '\r') { + stream->pos--; + append_v_offset--; + ret--; + } + + i_assert(ret >= 0); + edstream->cur_header = + edmail->header_fields_appended; + edstream->cur_header_v_offset = append_v_offset; + if (!edstream->parent_buffer) + edstream->header_read = TRUE; + } + + if (ret != 0) + return ret; + } else { + edstream->header_read = TRUE; + } + + /* Merge appended headers */ + ret = merge_modified_headers(edstream); + if (ret != 0) + return ret; + } + + /* Header does not come from original mail at all */ + if (edmail->headers_parsed) { + parent_v_offset = (stream->parent_start_offset + + edmail->wrapped_hdr_size.physical_size - + (edmail->eoh_crlf ? 2 : 1)); + copy_v_offset = edmail->hdr_size.physical_size; + /* Header comes partially from original mail and headers are added + between header and body. */ + } else if (edmail->header_fields_appended != NULL) { + parent_v_offset = (stream->parent_start_offset + + edmail->wrapped_hdr_size.physical_size - + (edmail->eoh_crlf ? 2 : 1)); + copy_v_offset = (edmail->hdr_size.physical_size + + edmail->wrapped_hdr_size.physical_size - + (edmail->eoh_crlf ? 2 : 1)); + /* Header comes partially from original mail, but headers are only + prepended. */ + } else { + parent_v_offset = stream->parent_start_offset; + copy_v_offset = edmail->hdr_size.physical_size; + } + + return merge_from_parent(edstream, parent_v_offset, (uoff_t)-1, + copy_v_offset); +} + +static void +stream_reset_to(struct edit_mail_istream *edstream, uoff_t v_offset) +{ + edstream->istream.istream.v_offset = v_offset; + edstream->istream.skip = 0; + edstream->istream.pos = 0; + edstream->istream.buffer = NULL; + edstream->parent_buffer = FALSE; + edstream->eof = FALSE; + i_stream_seek(edstream->istream.parent, 0); +} + +static void +edit_mail_istream_seek(struct istream_private *stream, uoff_t v_offset, + bool mark ATTR_UNUSED) +{ + struct edit_mail_istream *edstream = + (struct edit_mail_istream *)stream; + struct _header_field_index *cur_header; + struct edit_mail *edmail = edstream->mail; + uoff_t offset; + + edstream->header_read = FALSE; + edstream->cur_header = NULL; + edstream->cur_header_v_offset = 0; + + /* The beginning */ + if (v_offset == 0) { + stream_reset_to(edstream, 0); + + if (edmail->header_fields_head != + edmail->header_fields_appended) + edstream->cur_header = edmail->header_fields_head; + return; + } + + /* Inside (prepended) headers */ + if (edmail->headers_parsed) { + offset = edmail->hdr_size.physical_size; + } else { + offset = (edmail->hdr_size.physical_size - + edmail->appended_hdr_size.physical_size); + } + + if (v_offset < offset) { + stream_reset_to(edstream, v_offset); + + /* Find the header */ + cur_header = edmail->header_fields_head; + i_assert(cur_header != NULL && + cur_header != edmail->header_fields_appended); + edstream->cur_header_v_offset = 0; + offset = cur_header->field->size; + while (v_offset > offset) { + cur_header = cur_header->next; + i_assert(cur_header != NULL && + cur_header != edmail->header_fields_appended); + + edstream->cur_header_v_offset = offset; + offset += cur_header->field->size; + } + + edstream->cur_header = cur_header; + return; + } + + if (!edmail->headers_parsed) { + /* Inside original header */ + offset = (edmail->hdr_size.physical_size - + edmail->appended_hdr_size.physical_size + + edmail->wrapped_hdr_size.physical_size); + if (v_offset < offset) { + stream_reset_to(edstream, v_offset); + return; + } + + edstream->header_read = TRUE; + + /* Inside appended header */ + offset = (edmail->hdr_size.physical_size + + edmail->wrapped_hdr_size.physical_size); + if (v_offset < offset) { + stream_reset_to(edstream, v_offset); + + offset -= edmail->appended_hdr_size.physical_size; + + cur_header = edmail->header_fields_appended; + i_assert(cur_header != NULL); + edstream->cur_header_v_offset = offset; + offset += cur_header->field->size; + + while (v_offset > offset) { + cur_header = cur_header->next; + i_assert(cur_header != NULL); + + edstream->cur_header_v_offset = offset; + offset += cur_header->field->size; + } + + edstream->cur_header = cur_header; + return; + } + } + + stream_reset_to(edstream, v_offset); + edstream->cur_header = NULL; +} + +static void ATTR_NORETURN +edit_mail_istream_sync(struct istream_private *stream ATTR_UNUSED) +{ + i_panic("edit-mail istream sync() not implemented"); +} + +static int +edit_mail_istream_stat(struct istream_private *stream, bool exact) +{ + struct edit_mail_istream *edstream = + (struct edit_mail_istream *)stream; + struct edit_mail *edmail = edstream->mail; + const struct stat *st; + + /* Stat the original stream */ + if (i_stream_stat(stream->parent, exact, &st) < 0) + return -1; + + stream->statbuf = *st; + if (st->st_size == -1 || !exact) + return 0; + + if (!edmail->headers_parsed) { + if (!edmail->modified) + return 0; + } else { + stream->statbuf.st_size = + (edmail->wrapped_body_size.physical_size + + (edmail->eoh_crlf ? 2 : 1)); + } + + stream->statbuf.st_size += (edmail->hdr_size.physical_size + + edmail->body_size.physical_size); + return 0; +} + +struct istream *edit_mail_istream_create(struct edit_mail *edmail) +{ + struct edit_mail_istream *edstream; + struct istream *wrapped = edmail->wrapped_stream; + + edstream = i_new(struct edit_mail_istream, 1); + edstream->pool = pool_alloconly_create(MEMPOOL_GROWING + "edit mail stream", 4096); + edstream->mail = edmail; + + edstream->istream.max_buffer_size = + wrapped->real_stream->max_buffer_size; + + edstream->istream.iostream.destroy = edit_mail_istream_destroy; + edstream->istream.read = edit_mail_istream_read; + edstream->istream.seek = edit_mail_istream_seek; + edstream->istream.sync = edit_mail_istream_sync; + edstream->istream.stat = edit_mail_istream_stat; + + edstream->istream.istream.readable_fd = FALSE; + edstream->istream.istream.blocking = wrapped->blocking; + edstream->istream.istream.seekable = wrapped->seekable; + + if (edmail->header_fields_head != edmail->header_fields_appended) + edstream->cur_header = edmail->header_fields_head; + + i_stream_seek(wrapped, 0); + + return i_stream_create(&edstream->istream, wrapped, -1, 0); +} diff --git a/pigeonhole/src/lib-sieve/util/edit-mail.h b/pigeonhole/src/lib-sieve/util/edit-mail.h new file mode 100644 index 0000000..14d2eaa --- /dev/null +++ b/pigeonhole/src/lib-sieve/util/edit-mail.h @@ -0,0 +1,47 @@ +#ifndef EDIT_MAIL_H +#define EDIT_MAIL_H + +struct edit_mail; + +struct edit_mail *edit_mail_wrap(struct mail *mail); +void edit_mail_unwrap(struct edit_mail **edmail); +struct edit_mail *edit_mail_snapshot(struct edit_mail *edmail); + +void edit_mail_reset(struct edit_mail *edmail); + +struct mail *edit_mail_get_mail(struct edit_mail *edmail); + +/* + * Header modification + */ + +/* Simple API */ + +void edit_mail_header_add(struct edit_mail *edmail, const char *field_name, + const char *value, bool last); +int edit_mail_header_delete(struct edit_mail *edmail, + const char *field_name, int index); +int edit_mail_header_replace(struct edit_mail *edmail, + const char *field_name, int index, + const char *newname, const char *newvalue); + +/* Iterator */ + +struct edit_mail_header_iter; + +int edit_mail_headers_iterate_init(struct edit_mail *edmail, + const char *field_name, bool reverse, + struct edit_mail_header_iter **edhiter_r); +void edit_mail_headers_iterate_deinit(struct edit_mail_header_iter **edhiter); + +void edit_mail_headers_iterate_get(struct edit_mail_header_iter *edhiter, + const char **value_r); + +bool edit_mail_headers_iterate_next(struct edit_mail_header_iter *edhiter); + +bool edit_mail_headers_iterate_remove(struct edit_mail_header_iter *edhiter); +bool edit_mail_headers_iterate_replace(struct edit_mail_header_iter *edhiter, + const char *newname, + const char *newvalue); + +#endif diff --git a/pigeonhole/src/lib-sieve/util/mail-raw.c b/pigeonhole/src/lib-sieve/util/mail-raw.c new file mode 100644 index 0000000..b357fe1 --- /dev/null +++ b/pigeonhole/src/lib-sieve/util/mail-raw.c @@ -0,0 +1,247 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "istream.h" +#include "istream-seekable.h" +#include "str.h" +#include "str-sanitize.h" +#include "strescape.h" +#include "safe-mkstemp.h" +#include "path-util.h" +#include "message-address.h" +#include "mbox-from.h" +#include "raw-storage.h" +#include "mail-namespace.h" +#include "master-service.h" +#include "master-service-settings.h" +#include "settings-parser.h" +#include "mail-raw.h" + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <pwd.h> + +/* + * Configuration + */ + +#define DEFAULT_ENVELOPE_SENDER "MAILER-DAEMON" + +/* After buffer grows larger than this, create a temporary file to /tmp + where to read the mail. */ +#define MAIL_MAX_MEMORY_BUFFER (1024*128) + +static const char *wanted_headers[] = { + "From", "Message-ID", "Subject", "Return-Path", + NULL +}; + +/* + * Global data + */ + +struct mail_raw_user { + struct mail_namespace *ns; + struct mail_user *mail_user; +}; + +/* + * Raw mail implementation + */ + +static int seekable_fd_callback +(const char **path_r, void *context) +{ + struct mail_user *ruser = (struct mail_user *)context; + string_t *path; + int fd; + + path = t_str_new(128); + mail_user_set_get_temp_prefix(path, ruser->set); + fd = safe_mkstemp(path, 0600, (uid_t)-1, (gid_t)-1); + if (fd == -1) { + i_error("safe_mkstemp(%s) failed: %m", str_c(path)); + return -1; + } + + /* we just want the fd, unlink it */ + if (i_unlink(str_c(path)) < 0) { + /* shouldn't happen.. */ + i_close_fd(&fd); + return -1; + } + + *path_r = str_c(path); + return fd; +} + +static struct istream *mail_raw_create_stream +(struct mail_user *ruser, int fd, time_t *mtime_r, const char **sender) +{ + struct istream *input, *input2, *input_list[2]; + const unsigned char *data; + size_t i, size; + int ret, tz; + char *env_sender = NULL; + + *mtime_r = (time_t)-1; + fd_set_nonblock(fd, FALSE); + + input = i_stream_create_fd(fd, 4096); + input->blocking = TRUE; + /* If input begins with a From-line, drop it */ + ret = i_stream_read_bytes(input, &data, &size, 5); + if (ret > 0 && memcmp(data, "From ", 5) == 0) { + /* skip until the first LF */ + i_stream_skip(input, 5); + while ( i_stream_read_more(input, &data, &size) > 0 ) { + for (i = 0; i < size; i++) { + if (data[i] == '\n') + break; + } + if (i != size) { + (void)mbox_from_parse(data, i, mtime_r, &tz, &env_sender); + i_stream_skip(input, i + 1); + break; + } + i_stream_skip(input, size); + } + } + + if (env_sender != NULL && sender != NULL) { + *sender = t_strdup(env_sender); + } + i_free(env_sender); + + if (input->v_offset == 0) { + input2 = input; + i_stream_ref(input2); + } else { + input2 = i_stream_create_limit(input, (uoff_t)-1); + } + i_stream_unref(&input); + + input_list[0] = input2; input_list[1] = NULL; + input = i_stream_create_seekable(input_list, MAIL_MAX_MEMORY_BUFFER, + seekable_fd_callback, (void*)ruser); + i_stream_unref(&input2); + return input; +} + +/* + * Init/Deinit + */ + +struct mail_user *mail_raw_user_create +(struct master_service *service, struct mail_user *mail_user) +{ + void **sets = master_service_settings_get_others(service); + + return raw_storage_create_from_set(mail_user->set_info, sets[0]); +} + +/* + * Open raw mail data + */ + +static struct mail_raw *mail_raw_create +(struct mail_user *ruser, struct istream *input, + const char *mailfile, const char *sender, time_t mtime) +{ + struct mail_raw *mailr; + struct mailbox_header_lookup_ctx *headers_ctx; + const char *envelope_sender, *error; + int ret; + + if ( mailfile != NULL && *mailfile != '/' ) + if (t_abspath(mailfile, &mailfile, &error) < 0) + i_fatal("t_abspath(%s) failed: %s", + mailfile, error); + + mailr = i_new(struct mail_raw, 1); + + envelope_sender = sender != NULL ? sender : DEFAULT_ENVELOPE_SENDER; + if ( mailfile == NULL ) { + ret = raw_mailbox_alloc_stream(ruser, input, mtime, + envelope_sender, &mailr->box); + } else { + ret = raw_mailbox_alloc_path(ruser, mailfile, (time_t)-1, + envelope_sender, &mailr->box); + } + + if ( ret < 0 ) { + if ( mailfile == NULL ) { + i_fatal("Can't open delivery mail as raw: %s", + mailbox_get_last_internal_error(mailr->box, NULL)); + } else { + i_fatal("Can't open delivery mail as raw (file=%s): %s", + mailfile, mailbox_get_last_internal_error(mailr->box, NULL)); + } + } + + mailr->trans = mailbox_transaction_begin(mailr->box, 0, __func__); + headers_ctx = mailbox_header_lookup_init(mailr->box, wanted_headers); + mailr->mail = mail_alloc(mailr->trans, 0, headers_ctx); + mailbox_header_lookup_unref(&headers_ctx); + mail_set_seq(mailr->mail, 1); + + return mailr; +} + +struct mail_raw *mail_raw_open_stream +(struct mail_user *ruser, struct istream *input) +{ + struct mail_raw *mailr; + + i_assert(input->seekable); + i_stream_set_name(input, "data"); + mailr = mail_raw_create(ruser, input, NULL, NULL, (time_t)-1); + + return mailr; +} + +struct mail_raw *mail_raw_open_data +(struct mail_user *ruser, string_t *mail_data) +{ + struct mail_raw *mailr; + struct istream *input; + + input = i_stream_create_from_data(str_data(mail_data), str_len(mail_data)); + + mailr = mail_raw_open_stream(ruser, input); + + i_stream_unref(&input); + return mailr; +} + +struct mail_raw *mail_raw_open_file +(struct mail_user *ruser, const char *path) +{ + struct mail_raw *mailr; + struct istream *input = NULL; + time_t mtime = (time_t)-1; + const char *sender = NULL; + + if ( path == NULL || strcmp(path, "-") == 0 ) { + path = NULL; + input = mail_raw_create_stream(ruser, 0, &mtime, &sender); + } + + mailr = mail_raw_create(ruser, input, path, sender, mtime); + i_stream_unref(&input); + + return mailr; +} + +void mail_raw_close(struct mail_raw **mailr) +{ + mail_free(&(*mailr)->mail); + mailbox_transaction_rollback(&(*mailr)->trans); + mailbox_free(&(*mailr)->box); + + i_free(*mailr); + *mailr = NULL; +} + diff --git a/pigeonhole/src/lib-sieve/util/mail-raw.h b/pigeonhole/src/lib-sieve/util/mail-raw.h new file mode 100644 index 0000000..a942d06 --- /dev/null +++ b/pigeonhole/src/lib-sieve/util/mail-raw.h @@ -0,0 +1,27 @@ +#ifndef MAIL_RAW_H +#define MAIL_RAW_H + +#include "lib.h" +#include "master-service.h" + +struct mail_raw { + pool_t pool; + struct mail *mail; + + struct mailbox *box; + struct mailbox_transaction_context *trans; +}; + +struct mail_user *mail_raw_user_create + (struct master_service *service, struct mail_user *mail_user); + +struct mail_raw *mail_raw_open_stream + (struct mail_user *ruser, struct istream *input); +struct mail_raw *mail_raw_open_file + (struct mail_user *ruser, const char *path); +struct mail_raw *mail_raw_open_data + (struct mail_user *ruser, string_t *mail_data); +void mail_raw_close(struct mail_raw **mailr); + + +#endif diff --git a/pigeonhole/src/lib-sieve/util/rfc2822.c b/pigeonhole/src/lib-sieve/util/rfc2822.c new file mode 100644 index 0000000..ff3a9ad --- /dev/null +++ b/pigeonhole/src/lib-sieve/util/rfc2822.c @@ -0,0 +1,277 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* NOTE: much of the functionality implemented here should eventually appear + * somewhere in Dovecot itself. + */ + +#include "lib.h" +#include "str.h" +#include "unichar.h" + +#include "rfc2822.h" + +#include "message-header-encode.h" + +#include <stdio.h> +#include <ctype.h> + +bool rfc2822_header_field_name_verify +(const char *field_name, unsigned int len) +{ + const char *p = field_name; + const char *pend = p + len; + + /* field-name = 1*ftext + * ftext = %d33-57 / ; Any character except + * %d59-126 ; controls, SP, and + * ; ":". + */ + + while ( p < pend ) { + if ( *p < 33 || *p == ':' ) + return FALSE; + + p++; + } + + return TRUE; +} + +bool rfc2822_header_field_body_verify +(const char *field_body, unsigned int len, bool allow_crlf, bool allow_utf8) +{ + const unsigned char *p = (const unsigned char *)field_body; + const unsigned char *pend = p + len; + bool is8bit = FALSE; + + /* RFC5322: + * + * unstructured = (*([FWS] VCHAR) *WSP) + * VCHAR = %x21-7E + * FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space + * WSP = SP / HTAB ; White space + */ + + while ( p < pend ) { + if ( *p < 0x20 ) { + if ( (*p == '\r' || *p == '\n') ) { + if ( !allow_crlf ) + return FALSE; + } else if ( *p != '\t' ) { + return FALSE; + } + } + + if ( !is8bit && *p > 127 ) { + if ( !allow_utf8 ) + return FALSE; + + is8bit = TRUE; + } + + p++; + } + + if ( is8bit && !uni_utf8_str_is_valid(field_body) ) { + return FALSE; + } + + return TRUE; +} + +/* + * + */ + +const char *rfc2822_header_field_name_sanitize(const char *name) +{ + char *result = t_strdup_noconst(name); + char *p; + + /* Make the whole name lower case ... */ + result = str_lcase(result); + + /* ... except for the first letter and those that follow '-' */ + p = result; + *p = i_toupper(*p); + while ( *p != '\0' ) { + if ( *p == '-' ) { + p++; + + if ( *p != '\0' ) + *p = i_toupper(*p); + + continue; + } + + p++; + } + + return result; +} + +/* + * Message construction + */ + +/* FIXME: This should be collected into a Dovecot API for composing internet + * mail messages. + */ + +unsigned int rfc2822_header_append +(string_t *header, const char *name, const char *body, bool crlf, + uoff_t *body_offset_r) +{ + static const unsigned int max_line = 80; + + const char *bp = body; /* Pointer */ + const char *sp = body; /* Start pointer */ + const char *wp = NULL; /* Whitespace pointer */ + const char *nlp = NULL; /* New-line pointer */ + unsigned int line_len = strlen(name); + unsigned int lines = 0; + + /* Write header field name first */ + str_append(header, name); + str_append(header, ": "); + + if ( body_offset_r != NULL ) + *body_offset_r = str_len(header); + + line_len += 2; + + /* Add field body; fold it if necessary and account for existing folding */ + while ( *bp != '\0' ) { + bool ws_first = TRUE; + + while ( *bp != '\0' && nlp == NULL && + (wp == NULL || line_len < max_line) ) { + if ( *bp == ' ' || *bp == '\t' ) { + if (ws_first) + wp = bp; + ws_first = FALSE; + } else if ( *bp == '\r' || *bp == '\n' ) { + if (ws_first) + nlp = bp; + else + nlp = wp; + break; + } else { + ws_first = TRUE; + } + + bp++; line_len++; + } + + if ( *bp == '\0' ) break; + + /* Existing newline ? */ + if ( nlp != NULL ) { + /* Replace any consecutive newline and whitespace for + consistency */ + while ( *bp == ' ' || *bp == '\t' || *bp == '\r' || *bp == '\n' ) + bp++; + + str_append_data(header, sp, nlp-sp); + + if ( crlf ) + str_append(header, "\r\n"); + else + str_append(header, "\n"); + + while ( *bp == ' ' || *bp == '\t' ) + bp++; + if ( *bp != '\0' ) { + /* Continued line; replace leading whitespace with single TAB */ + str_append_c(header, '\t'); + } + + sp = bp; + } else { + /* Insert newline at last whitespace within the max_line limit */ + i_assert(wp >= sp); + str_append_data(header, sp, wp-sp); + + /* Force continued line; drop any existing whitespace */ + while ( *wp == ' ' || *wp == '\t' ) + wp++; + + if ( crlf ) + str_append(header, "\r\n"); + else + str_append(header, "\n"); + + /* Insert single TAB instead of the original whitespace */ + str_append_c(header, '\t'); + + sp = wp; + if (sp > bp) + bp = sp; + } + + lines++; + + line_len = bp - sp; + wp = NULL; + nlp = NULL; + } + + if ( bp != sp || lines == 0 ) { + str_append_data(header, sp, bp-sp); + if ( crlf ) + str_append(header, "\r\n"); + else + str_append(header, "\n"); + lines++; + } + + return lines; +} + +void rfc2822_header_printf +(string_t *header, const char *name, const char *fmt, ...) +{ + const char *body; + va_list args; + + va_start(args, fmt); + body = t_strdup_vprintf(fmt, args); + va_end(args); + + rfc2822_header_write(header, name, body); +} + +void rfc2822_header_utf8_printf +(string_t *header, const char *name, const char *fmt, ...) +{ + string_t *body = t_str_new(256); + va_list args; + + va_start(args, fmt); + message_header_encode(t_strdup_vprintf(fmt, args), body); + va_end(args); + + rfc2822_header_write(header, name, str_c(body)); +} + + +void rfc2822_header_write_address(string_t *header, + const char *name, const char *address) +{ + bool has_8bit = FALSE; + const char *p; + + for (p = address; *p != '\0'; p++) { + if ((*p & 0x80) != 0) + has_8bit = TRUE; + } + + if (!has_8bit) { + rfc2822_header_write(header, name, address); + } else { + string_t *body = t_str_new(256); + message_header_encode(address, body); + rfc2822_header_write(header, name, str_c(body)); + } +} diff --git a/pigeonhole/src/lib-sieve/util/rfc2822.h b/pigeonhole/src/lib-sieve/util/rfc2822.h new file mode 100644 index 0000000..02266a9 --- /dev/null +++ b/pigeonhole/src/lib-sieve/util/rfc2822.h @@ -0,0 +1,46 @@ +#ifndef RFC2822_H +#define RFC2822_H + +#include "lib.h" + +#include <stdio.h> + +/* + * Verification + */ + +bool rfc2822_header_field_name_verify + (const char *field_name, unsigned int len); +bool rfc2822_header_field_body_verify + (const char *field_body, unsigned int len, bool allow_crlf, bool allow_utf8); + +/* + * + */ + +const char *rfc2822_header_field_name_sanitize(const char *name); + +/* + * Message composition + */ + +unsigned int rfc2822_header_append + (string_t *header, const char *name, const char *body, bool crlf, + uoff_t *body_offset_r); + +static inline void rfc2822_header_write +(string_t *header, const char *name, const char *body) +{ + (void)rfc2822_header_append(header, name, body, TRUE, NULL); +} + +void rfc2822_header_printf + (string_t *header, const char *name, const char *fmt, ...) ATTR_FORMAT(3, 4); +void rfc2822_header_utf8_printf + (string_t *header, const char *name, const char *fmt, ...) ATTR_FORMAT(3, 4); + +void rfc2822_header_write_address(string_t *header, + const char *name, const char *address); + + +#endif diff --git a/pigeonhole/src/lib-sieve/util/test-edit-mail.c b/pigeonhole/src/lib-sieve/util/test-edit-mail.c new file mode 100644 index 0000000..0e263a2 --- /dev/null +++ b/pigeonhole/src/lib-sieve/util/test-edit-mail.c @@ -0,0 +1,842 @@ +/* Copyright (c) 2018 Pigeonhole authors, see the included COPYING file */ + +#include "lib.h" +#include "test-common.h" +#include "path-util.h" +#include "buffer.h" +#include "str.h" +#include "istream.h" +#include "istream-concat.h" +#include "istream-crlf.h" +#include "unlink-directory.h" +#include "master-service.h" +#include "istream-header-filter.h" +#include "mail-storage.h" +#include "mail-storage-service.h" +#include "mail-user.h" + +#include "mail-raw.h" +#include "edit-mail.h" + +#include <time.h> + +static pool_t test_pool; + +static struct mail_storage_service_ctx *mail_storage_service = NULL; +static struct mail_user *test_mail_user = NULL; +static struct mail_storage_service_user *test_service_user = NULL; +static const char *mail_home; +static char *test_dir; + +static struct mail_user *test_raw_mail_user = NULL; + +static void str_append_no_cr(string_t *str, const char *cstr) +{ + const char *p, *poff; + + poff = p = cstr; + while (*p != '\0') { + if (*p == '\r') { + str_append_data(str, poff, (p - poff)); + poff = p+1; + } + p++; + } + str_append_data(str, poff, (p - poff)); +} + +static int test_init_mail_user(void) +{ + const char *error; + + mail_home = p_strdup_printf(test_pool, "%s/test_user.%ld.%ld", + test_dir, (long)time(NULL), (long)getpid()); + + struct mail_storage_service_input input = { + .userdb_fields = (const char*const[]){ + t_strdup_printf("mail=maildir:~/"), + t_strdup_printf("home=%s", mail_home), + NULL + }, + .username = "test@example.com", + .no_userdb_lookup = TRUE, + .debug = TRUE, + }; + + mail_storage_service = mail_storage_service_init( + master_service, NULL, + (MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS | + MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT | + MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS)); + + if (mail_storage_service_lookup(mail_storage_service, &input, + &test_service_user, &error) < 0) + { + i_error("Cannot lookup test user: %s", error); + return -1; + } + + if (mail_storage_service_next(mail_storage_service, test_service_user, + &test_mail_user, &error) < 0) + { + i_error("Cannot lookup test user: %s", error); + return -1; + } + + return 0; +} + +static void test_deinit_mail_user() +{ + const char *error; + mail_user_unref(&test_mail_user); + mail_storage_service_user_unref(&test_service_user); + mail_storage_service_deinit(&mail_storage_service); + if (unlink_directory(mail_home, UNLINK_DIRECTORY_FLAG_RMDIR, + &error) < 0) + i_error("unlink_directory(%s) failed: %s", mail_home, error); +} + +static void test_init(void) +{ + test_pool = pool_alloconly_create(MEMPOOL_GROWING"test pool", 128); + + test_init_mail_user(); + test_raw_mail_user = + mail_raw_user_create(master_service, test_mail_user); +} + +static void test_deinit(void) +{ + mail_user_unref(&test_raw_mail_user); + test_deinit_mail_user(); + pool_unref(&test_pool); +} + +static void test_stream_data(struct istream *input, buffer_t *buffer) +{ + const unsigned char *data; + size_t size; + + while (i_stream_read_more(input, &data, &size) > 0) { + buffer_append(buffer, data, size); + i_stream_skip(input, size); + } + + test_assert(!i_stream_have_bytes_left(input)); + test_assert(input->stream_errno == 0); +} + +static void test_stream_data_slow(struct istream *input, buffer_t *buffer) +{ + const unsigned char *data; + size_t size; + int ret; + + ret = i_stream_read(input); + while (ret > 0 || i_stream_have_bytes_left(input) || ret == -2) { + data = i_stream_get_data(input, &size); + buffer_append(buffer, data, 1); + i_stream_skip(input, 1); + + ret = i_stream_read(input); + } + + test_assert(!i_stream_have_bytes_left(input)); + test_assert(input->stream_errno == 0); +} + +static void test_edit_mail_concatenated(void) +{ + static const char *hide_headers[] = + { "Return-Path", "X-Sieve", "X-Sieve-Redirected-From" }; + static const char *msg_part1 = + "Received: from example.com ([127.0.0.1] helo=example.com)\r\n" + " by example.org with LMTP (Dovecot)\r\n" + " (envelope-from <frop-bounces@example.com>)\r\n" + " id 1er3e8-0015df-QO\r\n" + " for timo@example.org;\r\n" + " Sat, 03 Mar 2018 10:40:05 +0100\r\n"; + static const char *msg_part2 = + "Return-Path: <stephan@example.com>\r\n"; + static const char *msg_part3 = + "Delivered-To: <timo@example.org>\r\n"; + static const char *msg_part4 = + "From: <stephan@example.com>\r\n" + "To: <timo@example.org>\r\n" + "Subject: Sieve editheader breaks with LMTP\r\n" + "\r\n" + "Hi,\r\n" + "\r\n" + "Sieve editheader seems to be broken when used from LMTP\r\n" + "\r\n" + "Regards,\r\n" + "\r\n" + "Stephan.\r\n"; + static const char *msg_added = + "X-Filter-Junk-Type: NONE\r\n" + "X-Filter-Junk-Flag: NO\r\n"; + struct istream *inputs[5], *input_msg, *input_filt, *input_mail, *input; + buffer_t *buffer; + struct mail_raw *rawmail; + struct edit_mail *edmail; + struct mail *mail; + string_t *expected; + const char *value; + + test_begin("edit-mail - concatenated"); + test_init(); + + /* Compose the message */ + + inputs[0] = i_stream_create_from_data(msg_part1, strlen(msg_part1)); + inputs[1] = i_stream_create_from_data(msg_part2, strlen(msg_part2)); + inputs[2] = i_stream_create_from_data(msg_part3, strlen(msg_part3)); + inputs[3] = i_stream_create_from_data(msg_part4, strlen(msg_part4)); + inputs[4] = NULL; + + input_msg = i_stream_create_concat(inputs); + + i_stream_unref(&inputs[0]); + i_stream_unref(&inputs[1]); + i_stream_unref(&inputs[2]); + i_stream_unref(&inputs[3]); + + rawmail = mail_raw_open_stream(test_raw_mail_user, input_msg); + + /* Add headers */ + + edmail = edit_mail_wrap(rawmail->mail); + + edit_mail_header_add(edmail, "X-Filter-Junk-Flag", "NO", FALSE); + edit_mail_header_add(edmail, "X-Filter-Junk-Type", "NONE", FALSE); + + mail = edit_mail_get_mail(edmail); + + /* Evaluate modified header */ + + test_assert(mail_get_first_header_utf8(mail, "Subject", &value) > 0); + test_assert(strcmp(value, "Sieve editheader breaks with LMTP") == 0); + + test_assert(mail_get_first_header_utf8(mail, "X-Filter-Junk-Flag", + &value) > 0); + test_assert(strcmp(value, "NO") == 0); + test_assert(mail_get_first_header_utf8(mail, "X-Filter-Junk-Type", + &value) > 0); + test_assert(strcmp(value, "NONE") == 0); + + test_assert(mail_get_first_header_utf8(mail, "Delivered-To", + &value) > 0); + + /* Prepare tests */ + + if (mail_get_stream(mail, NULL, NULL, &input_mail) < 0) { + i_fatal("Failed to open mail stream: %s", + mailbox_get_last_internal_error(mail->box, NULL)); + } + + buffer = buffer_create_dynamic(default_pool, 1024); + expected = t_str_new(1024); + + /* Added */ + + i_stream_seek(input_mail, 0); + buffer_set_used_size(buffer, 0); + input = input_mail; + + test_stream_data(input_mail, buffer); + + str_truncate(expected, 0); + str_append(expected, msg_added); + str_append(expected, msg_part1); + str_append(expected, msg_part2); + str_append(expected, msg_part3); + str_append(expected, msg_part4); + + test_out("added", strcmp(str_c(buffer), str_c(expected)) == 0); + + /* Added, slow */ + + i_stream_seek(input_mail, 0); + buffer_set_used_size(buffer, 0); + + test_stream_data_slow(input_mail, buffer); + + str_truncate(expected, 0); + str_append(expected, msg_added); + str_append(expected, msg_part1); + str_append(expected, msg_part2); + str_append(expected, msg_part3); + str_append(expected, msg_part4); + + test_out("added, slow", strcmp(str_c(buffer), str_c(expected)) == 0); + + /* Added, filtered */ + + i_stream_seek(input_mail, 0); + buffer_set_used_size(buffer, 0); + + input_filt = i_stream_create_header_filter( + input_mail, (HEADER_FILTER_EXCLUDE | HEADER_FILTER_NO_CR), + hide_headers, N_ELEMENTS(hide_headers), + *null_header_filter_callback, (void *)NULL); + input = i_stream_create_lf(input_filt); + i_stream_unref(&input_filt); + + test_stream_data(input, buffer); + test_assert(!i_stream_have_bytes_left(input_mail)); + test_assert(input_mail->stream_errno == 0); + + str_truncate(expected, 0); + str_append_no_cr(expected, msg_added); + str_append_no_cr(expected, msg_part1); + str_append_no_cr(expected, msg_part3); + str_append_no_cr(expected, msg_part4); + + test_out("added, filtered", + strcmp(str_c(buffer), str_c(expected)) == 0); + + i_stream_unref(&input); + + /* Added, filtered, slow */ + + i_stream_seek(input_mail, 0); + buffer_set_used_size(buffer, 0); + + input_filt = i_stream_create_header_filter( + input_mail, (HEADER_FILTER_EXCLUDE | HEADER_FILTER_NO_CR), + hide_headers, N_ELEMENTS(hide_headers), + *null_header_filter_callback, (void *)NULL); + input = i_stream_create_lf(input_filt); + i_stream_unref(&input_filt); + + test_stream_data_slow(input, buffer); + test_assert(!i_stream_have_bytes_left(input_mail)); + test_assert(input_mail->stream_errno == 0); + + str_truncate(expected, 0); + str_append_no_cr(expected, msg_added); + str_append_no_cr(expected, msg_part1); + str_append_no_cr(expected, msg_part3); + str_append_no_cr(expected, msg_part4); + + test_out("added, filtered, slow", + strcmp(str_c(buffer), str_c(expected)) == 0); + + i_stream_unref(&input); + + /* Delete header */ + + edit_mail_header_delete(edmail, "Delivered-To", 0); + + /* Evaluate modified header */ + + test_assert(mail_get_first_header_utf8(mail, "Subject", &value) > 0); + test_assert(strcmp(value, "Sieve editheader breaks with LMTP") == 0); + + test_assert(mail_get_first_header_utf8(mail, "X-Filter-Junk-Flag", + &value) > 0); + test_assert(strcmp(value, "NO") == 0); + test_assert(mail_get_first_header_utf8(mail, "X-Filter-Junk-Type", + &value) > 0); + test_assert(strcmp(value, "NONE") == 0); + + test_assert(mail_get_first_header_utf8(mail, "Delivered-To", + &value) == 0); + + /* Deleted */ + + i_stream_seek(input_mail, 0); + buffer_set_used_size(buffer, 0); + input = input_mail; + + test_stream_data(input_mail, buffer); + + str_truncate(expected, 0); + str_append(expected, msg_added); + str_append(expected, msg_part1); + str_append(expected, msg_part2); + str_append(expected, msg_part4); + + test_out("deleted", strcmp(str_c(buffer), str_c(expected)) == 0); + + /* Deleted, slow */ + + i_stream_seek(input_mail, 0); + buffer_set_used_size(buffer, 0); + + test_stream_data_slow(input_mail, buffer); + + str_truncate(expected, 0); + str_append(expected, msg_added); + str_append(expected, msg_part1); + str_append(expected, msg_part2); + str_append(expected, msg_part4); + + test_out("deleted, slow", strcmp(str_c(buffer), str_c(expected)) == 0); + + /* Deleted, filtered */ + + i_stream_seek(input_mail, 0); + buffer_set_used_size(buffer, 0); + + input_filt = i_stream_create_header_filter( + input_mail, (HEADER_FILTER_EXCLUDE | HEADER_FILTER_NO_CR), + hide_headers, N_ELEMENTS(hide_headers), + *null_header_filter_callback, (void *)NULL); + input = i_stream_create_lf(input_filt); + i_stream_unref(&input_filt); + + test_stream_data(input, buffer); + test_assert(!i_stream_have_bytes_left(input_mail)); + test_assert(input_mail->stream_errno == 0); + + str_truncate(expected, 0); + str_append_no_cr(expected, msg_added); + str_append_no_cr(expected, msg_part1); + str_append_no_cr(expected, msg_part4); + + test_out("deleted, filtered", + strcmp(str_c(buffer), str_c(expected)) == 0); + + i_stream_unref(&input); + + /* Deleted, filtered, slow */ + + i_stream_seek(input_mail, 0); + buffer_set_used_size(buffer, 0); + + input_filt = i_stream_create_header_filter(input_mail, + HEADER_FILTER_EXCLUDE | HEADER_FILTER_NO_CR, hide_headers, + N_ELEMENTS(hide_headers), *null_header_filter_callback, + (void *)NULL); + input = i_stream_create_lf(input_filt); + i_stream_unref(&input_filt); + + test_stream_data_slow(input, buffer); + test_assert(!i_stream_have_bytes_left(input_mail)); + test_assert(input_mail->stream_errno == 0); + + str_truncate(expected, 0); + str_append_no_cr(expected, msg_added); + str_append_no_cr(expected, msg_part1); + str_append_no_cr(expected, msg_part4); + + test_out("deleted, filtered, slow", + strcmp(str_c(buffer), str_c(expected)) == 0); + + i_stream_unref(&input); + + /* clean up */ + + buffer_free(&buffer); + edit_mail_unwrap(&edmail); + mail_raw_close(&rawmail); + i_stream_unref(&input_msg); + test_deinit(); + test_end(); +} + +static const char *big_header = + "X-A: AAAA\n" + "X-Big-One: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + " AAAAAAAAAAAAAAAAAAAAAAAAA\n" + "X-B: BBBB\n" + "\n" + "Frop!\n"; + +static void test_edit_mail_big_header(void) +{ + struct istream *input_msg, *input_mail; + buffer_t *buffer; + struct mail_raw *rawmail; + struct edit_mail *edmail; + struct mail *mail; + const char *value; + + test_begin("edit-mail - big header"); + test_init(); + + /* compose the message */ + + input_msg = i_stream_create_from_data(big_header, strlen(big_header)); + + rawmail = mail_raw_open_stream(test_raw_mail_user, input_msg); + + edmail = edit_mail_wrap(rawmail->mail); + + /* delete header */ + + edit_mail_header_delete(edmail, "X-B", 0); + mail = edit_mail_get_mail(edmail); + + /* prepare tests */ + + if (mail_get_stream(mail, NULL, NULL, &input_mail) < 0) { + i_fatal("Failed to open mail stream: %s", + mailbox_get_last_internal_error(mail->box, NULL)); + } + + buffer = buffer_create_dynamic(default_pool, 1024); + + /* evaluate modified header */ + + test_assert(mail_get_first_header_utf8(mail, "X-B", &value) == 0); + + /* deleted */ + + i_stream_seek(input_mail, 0); + buffer_set_used_size(buffer, 0); + + test_stream_data(input_mail, buffer); + + /* clean up */ + + buffer_free(&buffer); + edit_mail_unwrap(&edmail); + mail_raw_close(&rawmail); + i_stream_unref(&input_msg); + test_deinit(); + test_end(); +} + +static void test_edit_mail_small_buffer(void) +{ + static const char *message = + "X-A: AAAA\n" + "X-B: BBBB\n" + "\n" + "Frop!\n"; + struct istream *input_msg, *input_mail; + buffer_t *buffer; + struct mail_raw *rawmail; + struct edit_mail *edmail; + struct mail *mail; + const char *value; + unsigned int i; + + test_begin("edit-mail - small buffer"); + test_init(); + + /* compose the message */ + + input_msg = i_stream_create_from_data(message, strlen(message)); + i_stream_set_max_buffer_size(input_msg, 16); + + rawmail = mail_raw_open_stream(test_raw_mail_user, input_msg); + + edmail = edit_mail_wrap(rawmail->mail); + + /* add headers */ + + for (i = 0; i < 16; i++) { + edit_mail_header_add(edmail, "X-F", "FF", FALSE); + edit_mail_header_add(edmail, "X-L", "LL", TRUE); + } + + mail = edit_mail_get_mail(edmail); + + /* prepare tests */ + + if (mail_get_stream(mail, NULL, NULL, &input_mail) < 0) { + i_fatal("Failed to open mail stream: %s", + mailbox_get_last_internal_error(mail->box, NULL)); + } + + buffer = buffer_create_dynamic(default_pool, 1024); + + /* evaluate modified header */ + + test_assert(mail_get_first_header_utf8(mail, "X-F", &value) > 0); + test_assert(mail_get_first_header_utf8(mail, "X-A", &value) > 0); + test_assert(mail_get_first_header_utf8(mail, "X-B", &value) > 0); + test_assert(mail_get_first_header_utf8(mail, "X-L", &value) > 0); + + /* check stream read */ + + i_stream_seek(input_mail, 0); + buffer_set_used_size(buffer, 0); + + test_stream_data(input_mail, buffer); + + /* clean up */ + + buffer_free(&buffer); + edit_mail_unwrap(&edmail); + mail_raw_close(&rawmail); + i_stream_unref(&input_msg); + test_deinit(); + test_end(); +} + +int main(int argc, char *argv[]) +{ + static void (*test_functions[])(void) = { + test_edit_mail_concatenated, + test_edit_mail_big_header, + test_edit_mail_small_buffer, + NULL + }; + const enum master_service_flags service_flags = + MASTER_SERVICE_FLAG_STANDALONE | + MASTER_SERVICE_FLAG_DONT_SEND_STATS | + MASTER_SERVICE_FLAG_NO_CONFIG_SETTINGS; + const char *cwd, *error; + int ret; + + master_service = master_service_init("test-edit-header", service_flags, + &argc, &argv, ""); + master_service_init_finish(master_service); + + if (t_get_working_dir(&cwd, &error) < 0) + i_fatal("getcwd() failed: %s", error); + test_dir = i_strdup(cwd); + + ret = test_run(test_functions); + + i_free(test_dir); + master_service_deinit(&master_service); + + return ret; +} + diff --git a/pigeonhole/src/lib-sieve/util/test-rfc2822.c b/pigeonhole/src/lib-sieve/util/test-rfc2822.c new file mode 100644 index 0000000..66e8ee5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/util/test-rfc2822.c @@ -0,0 +1,197 @@ +/* Copyright (c) 2018 Pigeonhole authors, see the included COPYING file */ + +#include "lib.h" +#include "test-common.h" +#include "str.h" + +#include "rfc2822.h" + +struct test_header_write { + const char *name; + const char *body; + const char *output; +}; + +static const struct test_header_write header_write_tests[] = { + { + .name = "Frop", + .body = "Bladiebla", + .output = "Frop: Bladiebla\r\n" + },{ + .name = "Subject", + .body = "This is a very long subject that well exceeds the " + "boundary of 80 characters. It should therefore " + "trigger the header folding algorithm.", + .output = + "Subject: This is a very long subject that well " + "exceeds the boundary of 80\r\n" + "\tcharacters. It should therefore trigger the header " + "folding algorithm.\r\n" + },{ + .name = "Subject", + .body = "This\tis\ta\tvery\tlong\tsubject\tthat\twell\texceeds" + "\tthe\tboundary\tof\t80\tcharacters.\tIt\tshould\t" + "therefore\ttrigger\tthe\theader\tfolding\talgorithm.", + .output = + "Subject: This\tis\ta\tvery\tlong\tsubject\tthat\twell" + "\texceeds\tthe\tboundary\tof\t80\r\n" + "\tcharacters.\tIt\tshould\ttherefore\ttrigger\tthe\t" + "header\tfolding\talgorithm.\r\n" + },{ + .name = "Comment", + .body = "This header already contains newlines.\n" + "The header folding algorithm should respect these.\n" + "It also should convert between CRLF and LF when " + "needed.", + .output = "Comment: This header already contains newlines.\r\n" + "\tThe header folding algorithm should respect " + "these.\r\n" + "\tIt also should convert between CRLF and LF when " + "needed.\r\n" + },{ + .name = "References", + .body = "<messageid1@example.com> <messageid2@example.com> " + "<extremelylonglonglonglonglonglonglonglonglonglong" + "longlongmessageid3@example.com> " + "<messageid4@example.com>", + .output = "References: <messageid1@example.com> " + "<messageid2@example.com>\r\n" + "\t<extremelylonglonglonglonglonglonglonglonglonglong" + "longlongmessageid3@example.com>\r\n" + "\t<messageid4@example.com>\r\n", + },{ + .name = "Cc", + .body = "\"Richard Edgar Cipient\" " + "<r.e.cipient@example.com>, \"Albert Buser\" " + "<a.buser@example.com>, \"Steven Pammer\" " + "<s.pammer@example.com>", + .output = "Cc: \"Richard Edgar Cipient\" " + "<r.e.cipient@example.com>, \"Albert Buser\"\r\n" + "\t<a.buser@example.com>, \"Steven Pammer\" " + "<s.pammer@example.com>\r\n" + },{ + .name = "References", + .body = "<00fd01d31b6c$33d98e30$9b8caa90$@karel@aa.example.org" + "> <00f201d31c36$afbfa320$0f3ee960$@karel@aa.example.o" + "rg> <015c01d32023$fe3840c0$faa8c240$@karel@aa.examp" + "le.org> <014601d325a4$ece1ed90$c6a5c8b0$@karel@aa." + "example.org> <012801d32b24$7734c380$659e4a80$@karel" + "@aa.example.org> <00da01d32be9$2d9944b0$88cbce10$@kar" + "el@aa.example.org> <006a01d336ef$6825d5b0$387181" + "10$@karel@aa.example.org> <018501d33880$58b654f0$0a2" + "2fed0$@frederik@aa.example.org> <00e601d33ba3$be50f10" + "0$3af2d300$@frederik@aa.example.org> <016501d341ee$e" + "678e1a0$b36aa4e0$@frederik@aa.example.org> <00ab01" + "d348f9$ae2e1ab0$0a8a5010$@karel@aa.example.org> <0086" + "01d349c1$98ff4ba0$cafde2e0$@frederik@aa.example.org> " + " <019301d357e6$a2190680$e64b1380$@frederik@aa.example" + ".org> <025f01d384b0$24d2c" + "660$6e785320$@karel@aa.example.org> <01cf01d3889e$7" + "280cb90$578262b0$@karel@aa.example.org> <013701d38" + "bc2$9164b950$b42e2bf0$@karel@aa.example.org> " + " <014f01d3a5b1$a51afc80$ef\n" + " \n" + "\t \t \t \t \t \t \t \t5\t0\tf\t5\t8\t0\t$\t@\tk\ta\t" + "r\te\tl\t@\taa.example.org> <01cb01d3af29$dd7d" + "1b40$987751c0$@karel@aa.example.org> " + " <00b401d3f2bc$6ad8c180$408a4480" + "$@karel@aa.example.org> <011a01d3f6ab$0eeb0480$2cc1" + "0d80$@frederik@aa.example.org> <005c01d3f774$37f1b210" + "$a7d51630$@richard@aa.example.org> <01a801d3fc2d$59" + "0f7730$0b2e6590$@frederik@aa.example.org> <007501d3fc" + "f5$23d75ce0$6b8616a0$@frederik@aa.example.org> <015d0" + "1d3fdbf$136da510$3a48ef30$@frederik@aa.example.org> <" + "021a01d3fe87$556d68b0$00483a10$@frederik@aa.example.o" + "rg> <013f01d3ff4e$a2d13d30$e873b790$@frederik@aa.exam" + "ple.org> <001f01d401ab$31e7b090$95b711b0$@frederik@aa" + ".example.org> <017201d40273$a118d200$e34a7600$@freder" + "ik@aa.example.org> <017401d4033e$ca3602e0$5ea208a0$@f" + "rederik@aa.example.org> <02a601d40404$608b9e10$21a2da" + "30$@frederik@aa.example.org> <014301d404d0$b65269b0$2" + "2f73d10$@frederik@aa.example.org> <015901d4072b$b5a1b" + "950$20e52bf0$@frederik@aa.example.org> <01b401d407f3$" + "bef52050$3cdf\n" + " 60 \n" + "\tf0 \t$@ \tfr \ted \teri\tk@aa.example.org> <012801d" + "408bd$6602fce0$3208f6a0$@frederik@aa.example.org> <01" + "c801d40984$ae4b23c0$0ae16b40$@frederik@aa.example.org" + "> <00ec01d40a4d$12859190$3790b4b0$@frederik@aa.exampl" + "e.org> <02af01d40d74$589c9050$09d5b0f0$@frederik@aa.e" + "xample.org> <000d01d40ec8$d3d337b0$7b79a710$@richard@" + "aa.example.org>\n", + .output = "References: <00fd01d31b6c$33d98e30$9b8caa90$@karel@aa.example.org>\r\n" + "\t<00f201d31c36$afbfa320$0f3ee960$@karel@aa.example.org>\r\n" + "\t<015c01d32023$fe3840c0$faa8c240$@karel@aa.example.org>\r\n" + "\t<014601d325a4$ece1ed90$c6a5c8b0$@karel@aa.example.org>\r\n" + "\t<012801d32b24$7734c380$659e4a80$@karel@aa.example.org>\r\n" + "\t<00da01d32be9$2d9944b0$88cbce10$@karel@aa.example.org>\r\n" + "\t<006a01d336ef$6825d5b0$38718110$@karel@aa.example.org>\r\n" + "\t<018501d33880$58b654f0$0a22fed0$@frederik@aa.example.org>\r\n" + "\t<00e601d33ba3$be50f100$3af2d300$@frederik@aa.example.org>\r\n" + "\t<016501d341ee$e678e1a0$b36aa4e0$@frederik@aa.example.org>\r\n" + "\t<00ab01d348f9$ae2e1ab0$0a8a5010$@karel@aa.example.org>\r\n" + "\t<008601d349c1$98ff4ba0$cafde2e0$@frederik@aa.example.org>\r\n" + "\t<019301d357e6$a2190680$e64b1380$@frederik@aa.example.org>\r\n" + "\t<025f01d384b0$24d2c660$6e785320$@karel@aa.example.org>\r\n" + "\t<01cf01d3889e$7280cb90$578262b0$@karel@aa.example.org>\r\n" + "\t<013701d38bc2$9164b950$b42e2bf0$@karel@aa.example.org>\r\n" + "\t<014f01d3a5b1$a51afc80$ef\r\n" + "\t5\t0\tf\t5\t8\t0\t$\t@\tk\ta\tr\te\tl\t@\taa.example.org>\r\n" + "\t<01cb01d3af29$dd7d1b40$987751c0$@karel@aa.example.org>\r\n" + "\t<00b401d3f2bc$6ad8c180$408a4480$@karel@aa.example.org>\r\n" + "\t<011a01d3f6ab$0eeb0480$2cc10d80$@frederik@aa.example.org>\r\n" + "\t<005c01d3f774$37f1b210$a7d51630$@richard@aa.example.org>\r\n" + "\t<01a801d3fc2d$590f7730$0b2e6590$@frederik@aa.example.org>\r\n" + "\t<007501d3fcf5$23d75ce0$6b8616a0$@frederik@aa.example.org>\r\n" + "\t<015d01d3fdbf$136da510$3a48ef30$@frederik@aa.example.org>\r\n" + "\t<021a01d3fe87$556d68b0$00483a10$@frederik@aa.example.org>\r\n" + "\t<013f01d3ff4e$a2d13d30$e873b790$@frederik@aa.example.org>\r\n" + "\t<001f01d401ab$31e7b090$95b711b0$@frederik@aa.example.org>\r\n" + "\t<017201d40273$a118d200$e34a7600$@frederik@aa.example.org>\r\n" + "\t<017401d4033e$ca3602e0$5ea208a0$@frederik@aa.example.org>\r\n" + "\t<02a601d40404$608b9e10$21a2da30$@frederik@aa.example.org>\r\n" + "\t<014301d404d0$b65269b0$22f73d10$@frederik@aa.example.org>\r\n" + "\t<015901d4072b$b5a1b950$20e52bf0$@frederik@aa.example.org>\r\n" + "\t<01b401d407f3$bef52050$3cdf\r\n" + "\t60\r\n" + "\tf0 \t$@ \tfr \ted \teri\tk@aa.example.org>\r\n" + "\t<012801d408bd$6602fce0$3208f6a0$@frederik@aa.example.org>\r\n" + "\t<01c801d40984$ae4b23c0$0ae16b40$@frederik@aa.example.org>\r\n" + "\t<00ec01d40a4d$12859190$3790b4b0$@frederik@aa.example.org>\r\n" + "\t<02af01d40d74$589c9050$09d5b0f0$@frederik@aa.example.org>\r\n" + "\t<000d01d40ec8$d3d337b0$7b79a710$@richard@aa.example.org>\r\n" + } +}; + +static const unsigned int header_write_tests_count = + N_ELEMENTS(header_write_tests); + +static void test_rfc2822_header_write(void) +{ + string_t *header; + unsigned int i; + + test_begin("rfc2822 - header write"); + + header = t_str_new(1024); + for (i = 0; i < header_write_tests_count; i++) { + const struct test_header_write *test = &header_write_tests[i]; + + str_truncate(header, 0); + rfc2822_header_write(header, test->name, test->body); + + test_assert_idx(strcmp(str_c(header), test->output) == 0, i); + } + + test_end(); +} + +int main(void) +{ + static void (*test_functions[])(void) = { + test_rfc2822_header_write, + NULL + }; + return test_run(test_functions); +} + diff --git a/pigeonhole/src/managesieve-login/Makefile.am b/pigeonhole/src/managesieve-login/Makefile.am new file mode 100644 index 0000000..3bfbc75 --- /dev/null +++ b/pigeonhole/src/managesieve-login/Makefile.am @@ -0,0 +1,43 @@ +settingsdir = $(dovecot_moduledir)/settings + +dovecot_pkglibexec_PROGRAMS = managesieve-login + +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_SERVICE_INCLUDE) \ + $(LIBDOVECOT_LOGIN_INCLUDE) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/lib-managesieve + +libmanagesieve_login_settings_la_LDFLAGS = -module -avoid-version + +settings_LTLIBRARIES = \ + libmanagesieve_login_settings.la + +libmanagesieve_login_settings_la_SOURCES = \ + managesieve-login-settings.c \ + managesieve-login-settings-plugin.c + +libmanagesieve_login_settings_la_CFLAGS = \ + $(AM_CFLAGS) $(LIBDOVECOT_CONFIG_INCLUDE) -DPKG_LIBEXECDIR=\""$(dovecot_pkglibexecdir)"\" + +libs = \ + $(top_builddir)/src/lib-managesieve/libmanagesieve.la + +managesieve_login_CPPFLAGS = $(AM_CPPFLAGS) $(BINARY_CFLAGS) +managesieve_login_LDFLAGS = $(BINARY_LDFLAGS) +managesieve_login_LDADD = $(libs) $(LIBDOVECOT_LOGIN) $(LIBDOVECOT) +managesieve_login_DEPENDENCIES = $(libs) $(LIBDOVECOT_LOGIN_DEPS) $(LIBDOVECOT_DEPS) + +managesieve_login_SOURCES = \ + client.c \ + client-authenticate.c \ + managesieve-login-settings.c \ + managesieve-proxy.c + +noinst_HEADERS = \ + client.h \ + client-authenticate.h \ + managesieve-login-settings.h \ + managesieve-login-settings-plugin.h \ + managesieve-proxy.h diff --git a/pigeonhole/src/managesieve-login/Makefile.in b/pigeonhole/src/managesieve-login/Makefile.in new file mode 100644 index 0000000..14d7b78 --- /dev/null +++ b/pigeonhole/src/managesieve-login/Makefile.in @@ -0,0 +1,931 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +dovecot_pkglibexec_PROGRAMS = managesieve-login$(EXEEXT) +subdir = src/managesieve-login +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(dovecot_pkglibexecdir)" \ + "$(DESTDIR)$(settingsdir)" +PROGRAMS = $(dovecot_pkglibexec_PROGRAMS) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +LTLIBRARIES = $(settings_LTLIBRARIES) +libmanagesieve_login_settings_la_LIBADD = +am_libmanagesieve_login_settings_la_OBJECTS = libmanagesieve_login_settings_la-managesieve-login-settings.lo \ + libmanagesieve_login_settings_la-managesieve-login-settings-plugin.lo +libmanagesieve_login_settings_la_OBJECTS = \ + $(am_libmanagesieve_login_settings_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libmanagesieve_login_settings_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libmanagesieve_login_settings_la_CFLAGS) $(CFLAGS) \ + $(libmanagesieve_login_settings_la_LDFLAGS) $(LDFLAGS) -o $@ +am_managesieve_login_OBJECTS = managesieve_login-client.$(OBJEXT) \ + managesieve_login-client-authenticate.$(OBJEXT) \ + managesieve_login-managesieve-login-settings.$(OBJEXT) \ + managesieve_login-managesieve-proxy.$(OBJEXT) +managesieve_login_OBJECTS = $(am_managesieve_login_OBJECTS) +am__DEPENDENCIES_1 = +managesieve_login_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(managesieve_login_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings-plugin.Plo \ + ./$(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings.Plo \ + ./$(DEPDIR)/managesieve_login-client-authenticate.Po \ + ./$(DEPDIR)/managesieve_login-client.Po \ + ./$(DEPDIR)/managesieve_login-managesieve-login-settings.Po \ + ./$(DEPDIR)/managesieve_login-managesieve-proxy.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libmanagesieve_login_settings_la_SOURCES) \ + $(managesieve_login_SOURCES) +DIST_SOURCES = $(libmanagesieve_login_settings_la_SOURCES) \ + $(managesieve_login_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +settingsdir = $(dovecot_moduledir)/settings +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_SERVICE_INCLUDE) \ + $(LIBDOVECOT_LOGIN_INCLUDE) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/lib-managesieve + +libmanagesieve_login_settings_la_LDFLAGS = -module -avoid-version +settings_LTLIBRARIES = \ + libmanagesieve_login_settings.la + +libmanagesieve_login_settings_la_SOURCES = \ + managesieve-login-settings.c \ + managesieve-login-settings-plugin.c + +libmanagesieve_login_settings_la_CFLAGS = \ + $(AM_CFLAGS) $(LIBDOVECOT_CONFIG_INCLUDE) -DPKG_LIBEXECDIR=\""$(dovecot_pkglibexecdir)"\" + +libs = \ + $(top_builddir)/src/lib-managesieve/libmanagesieve.la + +managesieve_login_CPPFLAGS = $(AM_CPPFLAGS) $(BINARY_CFLAGS) +managesieve_login_LDFLAGS = $(BINARY_LDFLAGS) +managesieve_login_LDADD = $(libs) $(LIBDOVECOT_LOGIN) $(LIBDOVECOT) +managesieve_login_DEPENDENCIES = $(libs) $(LIBDOVECOT_LOGIN_DEPS) $(LIBDOVECOT_DEPS) +managesieve_login_SOURCES = \ + client.c \ + client-authenticate.c \ + managesieve-login-settings.c \ + managesieve-proxy.c + +noinst_HEADERS = \ + client.h \ + client-authenticate.h \ + managesieve-login-settings.h \ + managesieve-login-settings-plugin.h \ + managesieve-proxy.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/managesieve-login/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/managesieve-login/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dovecot_pkglibexecPROGRAMS: $(dovecot_pkglibexec_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(dovecot_pkglibexec_PROGRAMS)'; test -n "$(dovecot_pkglibexecdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(dovecot_pkglibexecdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(dovecot_pkglibexecdir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(dovecot_pkglibexecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(dovecot_pkglibexecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-dovecot_pkglibexecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(dovecot_pkglibexec_PROGRAMS)'; test -n "$(dovecot_pkglibexecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(dovecot_pkglibexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(dovecot_pkglibexecdir)" && rm -f $$files + +clean-dovecot_pkglibexecPROGRAMS: + @list='$(dovecot_pkglibexec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +install-settingsLTLIBRARIES: $(settings_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(settings_LTLIBRARIES)'; test -n "$(settingsdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(settingsdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(settingsdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(settingsdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(settingsdir)"; \ + } + +uninstall-settingsLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(settings_LTLIBRARIES)'; test -n "$(settingsdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(settingsdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(settingsdir)/$$f"; \ + done + +clean-settingsLTLIBRARIES: + -test -z "$(settings_LTLIBRARIES)" || rm -f $(settings_LTLIBRARIES) + @list='$(settings_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libmanagesieve_login_settings.la: $(libmanagesieve_login_settings_la_OBJECTS) $(libmanagesieve_login_settings_la_DEPENDENCIES) $(EXTRA_libmanagesieve_login_settings_la_DEPENDENCIES) + $(AM_V_CCLD)$(libmanagesieve_login_settings_la_LINK) -rpath $(settingsdir) $(libmanagesieve_login_settings_la_OBJECTS) $(libmanagesieve_login_settings_la_LIBADD) $(LIBS) + +managesieve-login$(EXEEXT): $(managesieve_login_OBJECTS) $(managesieve_login_DEPENDENCIES) $(EXTRA_managesieve_login_DEPENDENCIES) + @rm -f managesieve-login$(EXEEXT) + $(AM_V_CCLD)$(managesieve_login_LINK) $(managesieve_login_OBJECTS) $(managesieve_login_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings-plugin.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve_login-client-authenticate.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve_login-client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve_login-managesieve-login-settings.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve_login-managesieve-proxy.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libmanagesieve_login_settings_la-managesieve-login-settings.lo: managesieve-login-settings.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmanagesieve_login_settings_la_CFLAGS) $(CFLAGS) -MT libmanagesieve_login_settings_la-managesieve-login-settings.lo -MD -MP -MF $(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings.Tpo -c -o libmanagesieve_login_settings_la-managesieve-login-settings.lo `test -f 'managesieve-login-settings.c' || echo '$(srcdir)/'`managesieve-login-settings.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings.Tpo $(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-login-settings.c' object='libmanagesieve_login_settings_la-managesieve-login-settings.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmanagesieve_login_settings_la_CFLAGS) $(CFLAGS) -c -o libmanagesieve_login_settings_la-managesieve-login-settings.lo `test -f 'managesieve-login-settings.c' || echo '$(srcdir)/'`managesieve-login-settings.c + +libmanagesieve_login_settings_la-managesieve-login-settings-plugin.lo: managesieve-login-settings-plugin.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmanagesieve_login_settings_la_CFLAGS) $(CFLAGS) -MT libmanagesieve_login_settings_la-managesieve-login-settings-plugin.lo -MD -MP -MF $(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings-plugin.Tpo -c -o libmanagesieve_login_settings_la-managesieve-login-settings-plugin.lo `test -f 'managesieve-login-settings-plugin.c' || echo '$(srcdir)/'`managesieve-login-settings-plugin.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings-plugin.Tpo $(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings-plugin.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-login-settings-plugin.c' object='libmanagesieve_login_settings_la-managesieve-login-settings-plugin.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmanagesieve_login_settings_la_CFLAGS) $(CFLAGS) -c -o libmanagesieve_login_settings_la-managesieve-login-settings-plugin.lo `test -f 'managesieve-login-settings-plugin.c' || echo '$(srcdir)/'`managesieve-login-settings-plugin.c + +managesieve_login-client.o: client.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve_login-client.o -MD -MP -MF $(DEPDIR)/managesieve_login-client.Tpo -c -o managesieve_login-client.o `test -f 'client.c' || echo '$(srcdir)/'`client.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve_login-client.Tpo $(DEPDIR)/managesieve_login-client.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client.c' object='managesieve_login-client.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve_login-client.o `test -f 'client.c' || echo '$(srcdir)/'`client.c + +managesieve_login-client.obj: client.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve_login-client.obj -MD -MP -MF $(DEPDIR)/managesieve_login-client.Tpo -c -o managesieve_login-client.obj `if test -f 'client.c'; then $(CYGPATH_W) 'client.c'; else $(CYGPATH_W) '$(srcdir)/client.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve_login-client.Tpo $(DEPDIR)/managesieve_login-client.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client.c' object='managesieve_login-client.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve_login-client.obj `if test -f 'client.c'; then $(CYGPATH_W) 'client.c'; else $(CYGPATH_W) '$(srcdir)/client.c'; fi` + +managesieve_login-client-authenticate.o: client-authenticate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve_login-client-authenticate.o -MD -MP -MF $(DEPDIR)/managesieve_login-client-authenticate.Tpo -c -o managesieve_login-client-authenticate.o `test -f 'client-authenticate.c' || echo '$(srcdir)/'`client-authenticate.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve_login-client-authenticate.Tpo $(DEPDIR)/managesieve_login-client-authenticate.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client-authenticate.c' object='managesieve_login-client-authenticate.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve_login-client-authenticate.o `test -f 'client-authenticate.c' || echo '$(srcdir)/'`client-authenticate.c + +managesieve_login-client-authenticate.obj: client-authenticate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve_login-client-authenticate.obj -MD -MP -MF $(DEPDIR)/managesieve_login-client-authenticate.Tpo -c -o managesieve_login-client-authenticate.obj `if test -f 'client-authenticate.c'; then $(CYGPATH_W) 'client-authenticate.c'; else $(CYGPATH_W) '$(srcdir)/client-authenticate.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve_login-client-authenticate.Tpo $(DEPDIR)/managesieve_login-client-authenticate.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client-authenticate.c' object='managesieve_login-client-authenticate.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve_login-client-authenticate.obj `if test -f 'client-authenticate.c'; then $(CYGPATH_W) 'client-authenticate.c'; else $(CYGPATH_W) '$(srcdir)/client-authenticate.c'; fi` + +managesieve_login-managesieve-login-settings.o: managesieve-login-settings.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve_login-managesieve-login-settings.o -MD -MP -MF $(DEPDIR)/managesieve_login-managesieve-login-settings.Tpo -c -o managesieve_login-managesieve-login-settings.o `test -f 'managesieve-login-settings.c' || echo '$(srcdir)/'`managesieve-login-settings.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve_login-managesieve-login-settings.Tpo $(DEPDIR)/managesieve_login-managesieve-login-settings.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-login-settings.c' object='managesieve_login-managesieve-login-settings.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve_login-managesieve-login-settings.o `test -f 'managesieve-login-settings.c' || echo '$(srcdir)/'`managesieve-login-settings.c + +managesieve_login-managesieve-login-settings.obj: managesieve-login-settings.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve_login-managesieve-login-settings.obj -MD -MP -MF $(DEPDIR)/managesieve_login-managesieve-login-settings.Tpo -c -o managesieve_login-managesieve-login-settings.obj `if test -f 'managesieve-login-settings.c'; then $(CYGPATH_W) 'managesieve-login-settings.c'; else $(CYGPATH_W) '$(srcdir)/managesieve-login-settings.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve_login-managesieve-login-settings.Tpo $(DEPDIR)/managesieve_login-managesieve-login-settings.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-login-settings.c' object='managesieve_login-managesieve-login-settings.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve_login-managesieve-login-settings.obj `if test -f 'managesieve-login-settings.c'; then $(CYGPATH_W) 'managesieve-login-settings.c'; else $(CYGPATH_W) '$(srcdir)/managesieve-login-settings.c'; fi` + +managesieve_login-managesieve-proxy.o: managesieve-proxy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve_login-managesieve-proxy.o -MD -MP -MF $(DEPDIR)/managesieve_login-managesieve-proxy.Tpo -c -o managesieve_login-managesieve-proxy.o `test -f 'managesieve-proxy.c' || echo '$(srcdir)/'`managesieve-proxy.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve_login-managesieve-proxy.Tpo $(DEPDIR)/managesieve_login-managesieve-proxy.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-proxy.c' object='managesieve_login-managesieve-proxy.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve_login-managesieve-proxy.o `test -f 'managesieve-proxy.c' || echo '$(srcdir)/'`managesieve-proxy.c + +managesieve_login-managesieve-proxy.obj: managesieve-proxy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve_login-managesieve-proxy.obj -MD -MP -MF $(DEPDIR)/managesieve_login-managesieve-proxy.Tpo -c -o managesieve_login-managesieve-proxy.obj `if test -f 'managesieve-proxy.c'; then $(CYGPATH_W) 'managesieve-proxy.c'; else $(CYGPATH_W) '$(srcdir)/managesieve-proxy.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve_login-managesieve-proxy.Tpo $(DEPDIR)/managesieve_login-managesieve-proxy.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-proxy.c' object='managesieve_login-managesieve-proxy.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve_login-managesieve-proxy.obj `if test -f 'managesieve-proxy.c'; then $(CYGPATH_W) 'managesieve-proxy.c'; else $(CYGPATH_W) '$(srcdir)/managesieve-proxy.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(dovecot_pkglibexecdir)" "$(DESTDIR)$(settingsdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-dovecot_pkglibexecPROGRAMS clean-generic clean-libtool \ + clean-settingsLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings-plugin.Plo + -rm -f ./$(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings.Plo + -rm -f ./$(DEPDIR)/managesieve_login-client-authenticate.Po + -rm -f ./$(DEPDIR)/managesieve_login-client.Po + -rm -f ./$(DEPDIR)/managesieve_login-managesieve-login-settings.Po + -rm -f ./$(DEPDIR)/managesieve_login-managesieve-proxy.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-settingsLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-dovecot_pkglibexecPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings-plugin.Plo + -rm -f ./$(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings.Plo + -rm -f ./$(DEPDIR)/managesieve_login-client-authenticate.Po + -rm -f ./$(DEPDIR)/managesieve_login-client.Po + -rm -f ./$(DEPDIR)/managesieve_login-managesieve-login-settings.Po + -rm -f ./$(DEPDIR)/managesieve_login-managesieve-proxy.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dovecot_pkglibexecPROGRAMS \ + uninstall-settingsLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-dovecot_pkglibexecPROGRAMS clean-generic clean-libtool \ + clean-settingsLTLIBRARIES cscopelist-am ctags ctags-am \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dovecot_pkglibexecPROGRAMS install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-settingsLTLIBRARIES install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am \ + uninstall-dovecot_pkglibexecPROGRAMS \ + uninstall-settingsLTLIBRARIES + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/managesieve-login/client-authenticate.c b/pigeonhole/src/managesieve-login/client-authenticate.c new file mode 100644 index 0000000..b186f84 --- /dev/null +++ b/pigeonhole/src/managesieve-login/client-authenticate.c @@ -0,0 +1,308 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "login-common.h" +#include "base64.h" +#include "buffer.h" +#include "ioloop.h" +#include "istream.h" +#include "ostream.h" +#include "safe-memset.h" +#include "str.h" +#include "str-sanitize.h" +#include "auth-client.h" + +#include "managesieve-parser.h" +#include "managesieve-quote.h" +#include "client.h" + +#include "client-authenticate.h" +#include "managesieve-proxy.h" + + +const char *client_authenticate_get_capabilities +(struct client *client) +{ + const struct auth_mech_desc *mech; + unsigned int i, count; + string_t *str; + + str = t_str_new(128); + mech = sasl_server_get_advertised_mechs(client, &count); + + for (i = 0; i < count; i++) { + if (i > 0) + str_append_c(str, ' '); + str_append(str, mech[i].name); + } + + return str_c(str); +} + +void managesieve_client_auth_result(struct client *client, + enum client_auth_result result, + const struct client_auth_reply *reply, const char *text) +{ + struct managesieve_client *msieve_client = + (struct managesieve_client *)client; + string_t *referral; + + switch (result) { + case CLIENT_AUTH_RESULT_SUCCESS: + /* nothing to be done for IMAP */ + break; + case CLIENT_AUTH_RESULT_REFERRAL_SUCCESS: + case CLIENT_AUTH_RESULT_REFERRAL_NOLOGIN: + /* MANAGESIEVE referral + + [nologin] referral host=.. [port=..] [destuser=..] + [reason=..] + + NO [REFERRAL sieve://user;AUTH=mech@host:port/] "Can't login." + OK [...] "Logged in, but you should use this server instead." + .. [REFERRAL ..] Reason from auth server + */ + referral = t_str_new(128); + str_printfa(referral, "REFERRAL sieve://%s;AUTH=%s@%s", + reply->destuser, client->auth_mech_name, reply->host); + if ( reply->port != 4190 ) + str_printfa(referral, ":%u", reply->port); + + if ( result == CLIENT_AUTH_RESULT_REFERRAL_SUCCESS ) { + client_send_okresp(client, str_c(referral), text);; + } else { + client_send_noresp(client, str_c(referral), text); + } + break; + case CLIENT_AUTH_RESULT_ABORTED: + case CLIENT_AUTH_RESULT_AUTHFAILED_REASON: + case CLIENT_AUTH_RESULT_AUTHZFAILED: + client_send_no(client, text); + break; + case CLIENT_AUTH_RESULT_TEMPFAIL: + client_send_noresp(client, "TRYLATER", text); + break; + case CLIENT_AUTH_RESULT_SSL_REQUIRED: + client_send_noresp(client, "ENCRYPT-NEEDED", text); + break; + case CLIENT_AUTH_RESULT_AUTHFAILED: + default: + client_send_no(client, text); + break; + } + + msieve_client->auth_response_input = NULL; + managesieve_parser_reset(msieve_client->parser); +} + +void managesieve_client_auth_send_challenge +(struct client *client, const char *data) +{ + struct managesieve_client *msieve_client = + (struct managesieve_client *) client; + + T_BEGIN { + string_t *str = t_str_new(256); + + managesieve_quote_append_string(str, data, TRUE); + str_append(str, "\r\n"); + + client_send_raw_data(client, str_c(str), str_len(str)); + } T_END; + + msieve_client->auth_response_input = NULL; + managesieve_parser_reset(msieve_client->parser); +} + +static int managesieve_client_auth_read_response +(struct managesieve_client *msieve_client, bool initial, const char **error_r) +{ + struct client *client = &msieve_client->common; + const struct managesieve_arg *args; + const char *error; + bool fatal; + const unsigned char *data; + size_t size; + uoff_t resp_size; + int ret; + + *error_r = NULL; + + if ( i_stream_read(client->input) == -1 ) { + /* disconnected */ + client_destroy_iostream_error(client); + return -1; + } + + if ( msieve_client->auth_response_input == NULL ) { + + if ( msieve_client->skip_line ) { + if ( i_stream_next_line(client->input) == NULL ) + return 0; + + msieve_client->skip_line = FALSE; + } + + switch ( managesieve_parser_read_args(msieve_client->parser, 0, + MANAGESIEVE_PARSE_FLAG_STRING_STREAM, &args) ) { + case -1: + error = managesieve_parser_get_error(msieve_client->parser, &fatal); + if (fatal) { + client_send_bye(client, error); + client_destroy(client, t_strconcat( + "parse error during auth: ", error, NULL)); + } else { + *error_r = error; + } + msieve_client->skip_line = TRUE; + return -1; + + case -2: + /* not enough data */ + return 0; + + default: + break; + } + + if ( MANAGESIEVE_ARG_IS_EOL(&args[0]) ) { + if (!initial) { + *error_r = "Received empty AUTHENTICATE client response line."; + msieve_client->skip_line = TRUE; + return -1; + } + msieve_client->skip_line = TRUE; + return 1; + } + + if ( !managesieve_arg_get_string_stream + (&args[0], &msieve_client->auth_response_input) + || !MANAGESIEVE_ARG_IS_EOL(&args[1]) ) { + if ( !initial ) + *error_r = "Invalid AUTHENTICATE client response."; + else + *error_r = "Invalid AUTHENTICATE initial response."; + msieve_client->skip_line = TRUE; + return -1; + } + + if ( i_stream_get_size + (msieve_client->auth_response_input, FALSE, &resp_size) <= 0 ) + resp_size = 0; + + if (client->auth_response == NULL) + client->auth_response = str_new(default_pool, I_MAX(resp_size+1, 256)); + } + + while ( (ret=i_stream_read_more + (msieve_client->auth_response_input, &data, &size) ) > 0 ) { + + if (str_len(client->auth_response) + size > LOGIN_MAX_AUTH_BUF_SIZE) { + client_destroy(client, "Authentication response too large"); + return -1; + } + + str_append_data(client->auth_response, data, size); + i_stream_skip(msieve_client->auth_response_input, size); + } + + if ( ret == 0 ) return 0; + + if ( msieve_client->auth_response_input->stream_errno != 0 ) { + if ( !client->input->eof && + msieve_client->auth_response_input->stream_errno == EINVAL ) { + msieve_client->skip_line = TRUE; + *error_r = t_strconcat + ("Error in AUTHENTICATE response string: ", + i_stream_get_error(msieve_client->auth_response_input), NULL); + return -1; + } + + client_destroy_iostream_error(client); + return -1; + } + + if ( i_stream_next_line(client->input) == NULL ) + return 0; + + return 1; +} + +void managesieve_client_auth_parse_response(struct client *client) +{ + struct managesieve_client *msieve_client = + (struct managesieve_client *) client; + const char *error = NULL; + int ret; + + if ( (ret=managesieve_client_auth_read_response(msieve_client, FALSE, &error)) + < 0 ) { + if ( error != NULL ) + client_auth_fail(client, error); + return; + } + + if ( ret == 0 ) return; + + if ( strcmp(str_c(client->auth_response), "*") == 0 ) { + client_auth_abort(client); + return; + } + + client_auth_respond(client, str_c(client->auth_response)); + + memset(str_c_modifiable(client->auth_response), 0, + str_len(client->auth_response)); +} + +int cmd_authenticate +(struct managesieve_client *msieve_client, const struct managesieve_arg *args) +{ + /* NOTE: This command's input is handled specially because the + SASL-IR can be large. */ + struct client *client = &msieve_client->common; + const char *mech_name, *init_response; + const char *error; + int ret; + + if (!msieve_client->auth_mech_name_parsed) { + i_assert(args != NULL); + + /* one mandatory argument: authentication mechanism name */ + if ( !managesieve_arg_get_string(&args[0], &mech_name) ) + return -1; + + if (*mech_name == '\0') + return -1; + + i_free(client->auth_mech_name); + client->auth_mech_name = i_strdup(mech_name); + msieve_client->auth_mech_name_parsed = TRUE; + + msieve_client->auth_response_input = NULL; + managesieve_parser_reset(msieve_client->parser); + } + + msieve_client->skip_line = FALSE; + if ( (ret=managesieve_client_auth_read_response(msieve_client, TRUE, &error)) + < 0 ) { + msieve_client->auth_mech_name_parsed = FALSE; + if ( error != NULL ) { + client_send_no(client, error); + } + return 1; + } + + if ( ret == 0 ) return 0; + + init_response = ( client->auth_response == NULL ? NULL : + t_strdup(str_c(client->auth_response)) ); + msieve_client->auth_mech_name_parsed = FALSE; + if ( (ret=client_auth_begin + (client, t_strdup(client->auth_mech_name), init_response)) < 0 ) + return ret; + + msieve_client->cmd_finished = TRUE; + return 0; +} + diff --git a/pigeonhole/src/managesieve-login/client-authenticate.h b/pigeonhole/src/managesieve-login/client-authenticate.h new file mode 100644 index 0000000..1280ad5 --- /dev/null +++ b/pigeonhole/src/managesieve-login/client-authenticate.h @@ -0,0 +1,21 @@ +#ifndef CLIENT_AUTHENTICATE_H +#define CLIENT_AUTHENTICATE_H + +struct managesieve_arg; + +const char *client_authenticate_get_capabilities + (struct client *client); + +void managesieve_client_auth_result + (struct client *client, enum client_auth_result result, + const struct client_auth_reply *reply, const char *text); + +void managesieve_client_auth_send_challenge + (struct client *client, const char *data); +void managesieve_client_auth_parse_response + (struct client *client); + +int cmd_authenticate + (struct managesieve_client *client, const struct managesieve_arg *args); + +#endif diff --git a/pigeonhole/src/managesieve-login/client.c b/pigeonhole/src/managesieve-login/client.c new file mode 100644 index 0000000..fe8acff --- /dev/null +++ b/pigeonhole/src/managesieve-login/client.c @@ -0,0 +1,574 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "login-common.h" +#include "buffer.h" +#include "ioloop.h" +#include "istream.h" +#include "ostream.h" +#include "safe-memset.h" +#include "str.h" +#include "strescape.h" +#include "base64.h" +#include "master-service.h" +#include "master-auth.h" +#include "auth-client.h" + +#include "managesieve-parser.h" +#include "managesieve-quote.h" + +#include "client.h" +#include "client-authenticate.h" + +#include "managesieve-login-settings.h" +#include "managesieve-proxy.h" + +/* Disconnect client when it sends too many bad commands */ +#define CLIENT_MAX_BAD_COMMANDS 3 + +struct managesieve_command { + const char *name; + int (*func)(struct managesieve_client *client, + const struct managesieve_arg *args); + int preparsed_args; +}; + +/* Skip incoming data until newline is found, + returns TRUE if newline was found. */ +bool client_skip_line(struct managesieve_client *client) +{ + const unsigned char *data; + size_t i, data_size; + + data = i_stream_get_data(client->common.input, &data_size); + + for (i = 0; i < data_size; i++) { + if (data[i] == '\n') { + i_stream_skip(client->common.input, i+1); + return TRUE; + } + } + + return FALSE; +} + +static void client_send_capabilities(struct client *client) +{ + struct managesieve_client *msieve_client = + (struct managesieve_client *)client; + const char *saslcap; + + T_BEGIN { + saslcap = client_authenticate_get_capabilities(client); + + /* Default capabilities */ + client_send_raw(client, t_strconcat( + "\"IMPLEMENTATION\" \"", + msieve_client->set->managesieve_implementation_string, + "\"\r\n", NULL)); + client_send_raw(client, t_strconcat( + "\"SIEVE\" \"", + msieve_client->set->managesieve_sieve_capability, + "\"\r\n", NULL)); + if (msieve_client->set->managesieve_notify_capability != NULL) { + client_send_raw(client, t_strconcat( + "\"NOTIFY\" \"", + msieve_client->set->managesieve_notify_capability, + "\"\r\n", NULL)); + } + client_send_raw(client, t_strconcat("\"SASL\" \"", saslcap, + "\"\r\n", NULL)); + + /* STARTTLS */ + if (login_ssl_initialized && !client->tls) + client_send_raw(client, "\"STARTTLS\"\r\n"); + + /* Protocol version */ + client_send_raw(client, "\"VERSION\" \"1.0\"\r\n"); + + /* XCLIENT */ + if (client->trusted) + client_send_raw(client, "\"XCLIENT\"\r\n"); + } T_END; +} + +static int +cmd_capability(struct managesieve_client *client, + const struct managesieve_arg *args ATTR_UNUSED) +{ + o_stream_cork(client->common.output); + + client_send_capabilities(&client->common); + client_send_ok(&client->common, "Capability completed."); + + o_stream_uncork(client->common.output); + + return 1; +} + +static int +cmd_starttls(struct managesieve_client *client, + const struct managesieve_arg *args ATTR_UNUSED) +{ + client_cmd_starttls(&client->common); + return 1; +} + +static void +managesieve_client_notify_starttls(struct client *client, bool success, + const char *text) +{ + if (success) + client_send_ok(client, text); + else + client_send_no(client, text); +} + +static int +cmd_noop(struct managesieve_client *client, const struct managesieve_arg *args) +{ + const char *text; + string_t *resp_code; + + if (MANAGESIEVE_ARG_IS_EOL(&args[0])) { + client_send_ok(&client->common, "NOOP Completed"); + return 1; + } + if (!MANAGESIEVE_ARG_IS_EOL(&args[1])) + return -1; + if (!managesieve_arg_get_string(&args[0], &text)) { + client_send_no(&client->common, "Invalid echo tag."); + return 1; + } + + resp_code = t_str_new(256); + str_append(resp_code, "TAG "); + managesieve_quote_append_string(resp_code, text, FALSE); + + client_send_okresp(&client->common, str_c(resp_code), "Done"); + return 1; +} + +static int +cmd_logout(struct managesieve_client *client, + const struct managesieve_arg *args ATTR_UNUSED) +{ + client_send_ok(&client->common, "Logout completed."); + client_destroy(&client->common, CLIENT_UNAUTHENTICATED_LOGOUT_MSG); + return 1; +} + +static int +cmd_xclient_parse_forward(struct managesieve_client *client, const char *value) +{ + size_t value_len = strlen(value); + + if (client->common.forward_fields != NULL) + str_truncate(client->common.forward_fields, 0); + else { + client->common.forward_fields = str_new( + client->common.preproxy_pool, + MAX_BASE64_DECODED_SIZE(value_len)); + } + + if (base64_decode(value, value_len, NULL, + client->common.forward_fields) < 0) + return -1; + + return 0; +} + +static int +cmd_xclient(struct managesieve_client *client, + const struct managesieve_arg *args) +{ + const char *arg; + bool args_ok = TRUE; + + if (!client->common.trusted) { + client_send_no(&client->common, "You are not from trusted IP"); + return 1; + } + while (!MANAGESIEVE_ARG_IS_EOL(&args[0]) && + managesieve_arg_get_atom(&args[0], &arg)) { + if (strncasecmp(arg, "ADDR=", 5) == 0) { + if (net_addr2ip(arg + 5, &client->common.ip) < 0) + args_ok = FALSE; + } else if (strncasecmp(arg, "FORWARD=", 8) == 0) { + if (cmd_xclient_parse_forward(client, arg + 8) < 0) + args_ok = FALSE; + } else if (strncasecmp(arg, "PORT=", 5) == 0) { + if (net_str2port(arg + 5, + &client->common.remote_port) < 0) + args_ok = FALSE; + } else if (strncasecmp(arg, "SESSION=", 8) == 0) { + const char *value = arg + 8; + + if (strlen(value) <= LOGIN_MAX_SESSION_ID_LEN) { + client->common.session_id = + p_strdup(client->common.pool, value); + } + } else if (strncasecmp(arg, "TTL=", 4) == 0) { + if (str_to_uint(arg + 4, &client->common.proxy_ttl) < 0) + args_ok = FALSE; + } + args++; + } + if (!args_ok || !MANAGESIEVE_ARG_IS_EOL(&args[0])) + return -1; + + client_send_ok(&client->common, "Updated"); + return 1; +} + +static struct managesieve_command commands[] = { + { "AUTHENTICATE", cmd_authenticate, 1 }, + { "CAPABILITY", cmd_capability, -1 }, + { "STARTTLS", cmd_starttls, -1 }, + { "NOOP", cmd_noop, 0 }, + { "LOGOUT", cmd_logout, -1 }, + { "XCLIENT", cmd_xclient, 0 }, + { NULL, NULL, 0 } +}; + +static bool client_handle_input(struct managesieve_client *client) +{ + i_assert(!client->common.authenticating); + + if (client->cmd_finished) { + /* Clear the previous command from memory */ + client->cmd_name = NULL; + client->cmd_parsed_args = FALSE; + client->cmd = NULL; + managesieve_parser_reset(client->parser); + + /* Remove \r\n */ + if (client->skip_line) { + if (!client_skip_line(client)) + return FALSE; + client->skip_line = FALSE; + } + + client->cmd_finished = FALSE; + } + + if (client->cmd == NULL) { + struct managesieve_command *cmd; + const char *cmd_name; + + client->cmd_name = managesieve_parser_read_word(client->parser); + if (client->cmd_name == NULL) + return FALSE; /* Need more data */ + + cmd_name = t_str_ucase(client->cmd_name); + cmd = commands; + while (cmd->name != NULL) { + if (strcmp(cmd->name, cmd_name) == 0) + break; + cmd++; + } + + if (cmd->name != NULL) + client->cmd = cmd; + else + client->skip_line = TRUE; + } + return client->common.v.input_next_cmd(&client->common); +} + +static bool managesieve_client_input_next_cmd(struct client *_client) +{ + struct managesieve_client *client = + (struct managesieve_client *)_client; + const struct managesieve_arg *args = NULL; + const char *msg; + int ret = 1; + bool fatal; + + if (client->cmd == NULL) { + /* Unknown command */ + ret = -1; + } else if (!client->cmd_parsed_args) { + unsigned int arg_count = + (client->cmd->preparsed_args > 0 ? + client->cmd->preparsed_args : 0); + + switch (managesieve_parser_read_args(client->parser, arg_count, + 0, &args)) { + case -1: + /* Error */ + msg = managesieve_parser_get_error(client->parser, + &fatal); + if (fatal) { + client_send_bye(&client->common, msg); + client_destroy(&client->common, msg); + return FALSE; + } + client_send_no(&client->common, msg); + client->cmd_finished = TRUE; + client->skip_line = TRUE; + return TRUE; + case -2: + /* Not enough data */ + return FALSE; + } + i_assert(args != NULL); + + if (arg_count == 0) { + /* We read the entire line - skip over the CRLF */ + if (!client_skip_line(client)) + i_unreached(); + } else { + /* Get rid of it later */ + client->skip_line = TRUE; + } + + client->cmd_parsed_args = TRUE; + + if (client->cmd->preparsed_args == -1) { + /* Check absence of arguments */ + if (args[0].type != MANAGESIEVE_ARG_EOL) + ret = -1; + } + } + if (ret > 0) { + i_assert(client->cmd != NULL); + ret = client->cmd->func(client, args); + } + + if (ret != 0) + client->cmd_finished = TRUE; + if (ret < 0) { + if (++client->common.bad_counter >= CLIENT_MAX_BAD_COMMANDS) { + client_send_bye(&client->common, + "Too many invalid MANAGESIEVE commands."); + client_destroy(&client->common, + "Too many invalid commands."); + return FALSE; + } + client_send_no(&client->common, + "Error in MANAGESIEVE command received by server."); + } + + return ret != 0 && !client->common.destroyed; +} + +static void managesieve_client_input(struct client *client) +{ + struct managesieve_client *managesieve_client = + (struct managesieve_client *)client; + + if (!client_read(client)) + return; + + client_ref(client); + o_stream_cork(managesieve_client->common.output); + for (;;) { + if (!auth_client_is_connected(auth_client)) { + /* We're not currently connected to auth process - + don't allow any commands */ + /* FIXME: Can't do untagged responses with managesieve. + Any other ways? + client_send_ok(client, AUTH_SERVER_WAITING_MSG); + */ + timeout_remove(&client->to_auth_waiting); + + client->input_blocked = TRUE; + break; + } else { + if (!client_handle_input(managesieve_client)) + break; + } + } + o_stream_uncork(managesieve_client->common.output); + client_unref(&client); +} + +static struct client *managesieve_client_alloc(pool_t pool) +{ + struct managesieve_client *msieve_client; + + msieve_client = p_new(pool, struct managesieve_client, 1); + return &msieve_client->common; +} + +static void managesieve_client_create(struct client *client, void **other_sets) +{ + struct managesieve_client *msieve_client = + (struct managesieve_client *)client; + + msieve_client->set = other_sets[0]; + msieve_client->parser = managesieve_parser_create( + msieve_client->common.input, MAX_MANAGESIEVE_LINE); + client->io = io_add(client->fd, IO_READ, client_input, client); +} + +static void managesieve_client_destroy(struct client *client) +{ + struct managesieve_client *managesieve_client = + (struct managesieve_client *)client; + + managesieve_parser_destroy(&managesieve_client->parser); +} + +static void managesieve_client_notify_auth_ready(struct client *client) +{ + /* Cork the stream to send the capability data as a single tcp frame + Some naive clients break if we don't. + */ + o_stream_cork(client->output); + + /* Send initial capabilities */ + client_send_capabilities(client); + client_send_ok(client, client->set->login_greeting); + + o_stream_uncork(client->output); + + client->banner_sent = TRUE; +} + +static void managesieve_client_starttls(struct client *client) +{ + struct managesieve_client *msieve_client = + (struct managesieve_client *)client; + + managesieve_parser_destroy(&msieve_client->parser); + msieve_client->parser = managesieve_parser_create( + msieve_client->common.input, MAX_MANAGESIEVE_LINE); + + /* CRLF is lost from buffer when streams are reopened. */ + msieve_client->skip_line = FALSE; + + /* Cork the stream to send the capability data as a single tcp frame + Some naive clients break if we don't. + */ + o_stream_cork(client->output); + + client_send_capabilities(client); + client_send_ok(client, "TLS negotiation successful."); + + o_stream_uncork(client->output); +} + +static void +client_send_reply_raw(struct client *client, const char *prefix, + const char *resp_code, const char *text) +{ + T_BEGIN { + string_t *line = t_str_new(256); + + str_append(line, prefix); + + if (resp_code != NULL) { + str_append(line, " ("); + str_append(line, resp_code); + str_append_c(line, ')'); + } + + if (text != NULL) { + str_append_c(line, ' '); + managesieve_quote_append_string(line, text, TRUE); + } + + str_append(line, "\r\n"); + + client_send_raw_data(client, str_data(line), str_len(line)); + } T_END; +} + +void client_send_reply_code(struct client *client, + enum managesieve_cmd_reply reply, + const char *resp_code, const char *text) +{ + const char *prefix = "NO"; + + switch (reply) { + case MANAGESIEVE_CMD_REPLY_OK: + prefix = "OK"; + break; + case MANAGESIEVE_CMD_REPLY_NO: + break; + case MANAGESIEVE_CMD_REPLY_BYE: + prefix = "BYE"; + break; + } + + client_send_reply_raw(client, prefix, resp_code, text); +} + +void client_send_reply(struct client *client, enum managesieve_cmd_reply reply, + const char *text) +{ + client_send_reply_code(client, reply, NULL, text); +} + +static void +managesieve_client_notify_disconnect(struct client *client, + enum client_disconnect_reason reason, + const char *text) +{ + if (reason == CLIENT_DISCONNECT_SYSTEM_SHUTDOWN) { + client_send_reply_code(client, MANAGESIEVE_CMD_REPLY_BYE, + "TRYLATER", text); + } else { + client_send_reply_code(client, MANAGESIEVE_CMD_REPLY_BYE, + NULL, text); + } +} + +static void managesieve_login_preinit(void) +{ + login_set_roots = managesieve_login_settings_set_roots; +} + +static void managesieve_login_init(void) +{ +} + +static void managesieve_login_deinit(void) +{ + clients_destroy_all(); +} + +static struct client_vfuncs managesieve_client_vfuncs = { + .alloc = managesieve_client_alloc, + .create = managesieve_client_create, + .destroy = managesieve_client_destroy, + .notify_auth_ready = managesieve_client_notify_auth_ready, + .notify_disconnect = managesieve_client_notify_disconnect, + .notify_starttls = managesieve_client_notify_starttls, + .starttls = managesieve_client_starttls, + .input = managesieve_client_input, + .auth_send_challenge = managesieve_client_auth_send_challenge, + .auth_parse_response = managesieve_client_auth_parse_response, + .auth_result = managesieve_client_auth_result, + .proxy_reset = managesieve_proxy_reset, + .proxy_parse_line = managesieve_proxy_parse_line, + .proxy_failed = managesieve_proxy_failed, + .proxy_get_state = managesieve_proxy_get_state, + .send_raw_data = client_common_send_raw_data, + .input_next_cmd = managesieve_client_input_next_cmd, + .free = client_common_default_free, +}; + +static struct login_binary managesieve_login_binary = { + .protocol = "sieve", + .process_name = "managesieve-login", + .default_port = 4190, + + .event_category = { + .name = "managesieve", + }, + + .client_vfuncs = &managesieve_client_vfuncs, + .preinit = managesieve_login_preinit, + .init = managesieve_login_init, + .deinit = managesieve_login_deinit, + + .anonymous_login_acceptable = FALSE, +}; + +int main(int argc, char *argv[]) +{ + return login_binary_run(&managesieve_login_binary, argc, argv); +} diff --git a/pigeonhole/src/managesieve-login/client.h b/pigeonhole/src/managesieve-login/client.h new file mode 100644 index 0000000..a04190d --- /dev/null +++ b/pigeonhole/src/managesieve-login/client.h @@ -0,0 +1,76 @@ +#ifndef CLIENT_H +#define CLIENT_H + +#include "net.h" +#include "client-common.h" + +/* maximum length for managesieve command line. */ +#define MAX_MANAGESIEVE_LINE 8192 + +enum managesieve_proxy_state { + MSIEVE_PROXY_STATE_NONE, + MSIEVE_PROXY_STATE_TLS_START, + MSIEVE_PROXY_STATE_TLS_READY, + MSIEVE_PROXY_STATE_XCLIENT, + MSIEVE_PROXY_STATE_AUTH, + + MSIEVE_PROXY_STATE_COUNT +}; +struct managesieve_command; + +struct managesieve_client { + struct client common; + + const struct managesieve_login_settings *set; + struct managesieve_parser *parser; + + enum managesieve_proxy_state proxy_state; + + const char *cmd_name; + struct managesieve_command *cmd; + + struct istream *auth_response_input; + + bool cmd_finished:1; + bool cmd_parsed_args:1; + bool skip_line:1; + bool auth_mech_name_parsed:1; + + bool proxy_starttls:1; + bool proxy_sasl:1; + bool proxy_xclient:1; +}; + +bool client_skip_line(struct managesieve_client *client); + +enum managesieve_cmd_reply { + MANAGESIEVE_CMD_REPLY_OK, + MANAGESIEVE_CMD_REPLY_NO, + MANAGESIEVE_CMD_REPLY_BYE +}; + +void client_send_reply(struct client *client, enum managesieve_cmd_reply reply, + const char *text); + +void client_send_reply_code(struct client *client, + enum managesieve_cmd_reply reply, + const char *resp_code, const char *text); + +#define client_send_ok(client, text) \ + client_send_reply(client, MANAGESIEVE_CMD_REPLY_OK, text) +#define client_send_no(client, text) \ + client_send_reply(client, MANAGESIEVE_CMD_REPLY_NO, text) +#define client_send_bye(client, text) \ + client_send_reply(client, MANAGESIEVE_CMD_REPLY_BYE, text) + +#define client_send_okresp(client, resp_code, text) \ + client_send_reply_code(client, MANAGESIEVE_CMD_REPLY_OK, \ + resp_code, text) +#define client_send_noresp(client, resp_code, text) \ + client_send_reply_code(client, MANAGESIEVE_CMD_REPLY_NO, \ + resp_code, text) +#define client_send_byeresp(client, resp_code, text) \ + client_send_reply_code(client, MANAGESIEVE_CMD_REPLY_BYE, \ + resp_code, text) + +#endif diff --git a/pigeonhole/src/managesieve-login/managesieve-login-settings-plugin.c b/pigeonhole/src/managesieve-login/managesieve-login-settings-plugin.c new file mode 100644 index 0000000..12515cd --- /dev/null +++ b/pigeonhole/src/managesieve-login/managesieve-login-settings-plugin.c @@ -0,0 +1,223 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "buffer.h" +#include "env-util.h" +#include "execv-const.h" +#include "master-service.h" +#include "settings-parser.h" +#include "config-parser-private.h" +#include "managesieve-login-settings-plugin.h" + +#include <stddef.h> +#include <unistd.h> +#include <sys/wait.h> +#include <sysexits.h> + +typedef enum { CAP_SIEVE, CAP_NOTIFY } capability_type_t; + +bool capability_dumped = FALSE; +static char *capability_sieve = NULL; +static char *capability_notify = NULL; + +static void (*next_hook_config_parser_begin)(struct config_parser_context *ctx) = NULL; + +static void managesieve_login_config_parser_begin(struct config_parser_context *ctx); + +const char *managesieve_login_settings_version = DOVECOT_ABI_VERSION; + +void managesieve_login_settings_init(struct module *module ATTR_UNUSED) +{ + next_hook_config_parser_begin = hook_config_parser_begin; + hook_config_parser_begin = managesieve_login_config_parser_begin; +} + +void managesieve_login_settings_deinit(void) +{ + hook_config_parser_begin = next_hook_config_parser_begin; + + if ( capability_sieve != NULL ) + i_free(capability_sieve); + + if ( capability_notify != NULL ) + i_free(capability_notify); +} + +static void capability_store(capability_type_t cap_type, const char *value) +{ + switch ( cap_type ) { + case CAP_SIEVE: + capability_sieve = i_strdup(value); + break; + case CAP_NOTIFY: + capability_notify = i_strdup(value); + break; + } +} + +static void capability_parse(const char *cap_string) +{ + capability_type_t cap_type = CAP_SIEVE; + const char *p = cap_string; + string_t *part = t_str_new(256); + + if ( cap_string == NULL || *cap_string == '\0' ) { + i_warning("managesieve-login: capability string is empty."); + return; + } + + while ( *p != '\0' ) { + if ( *p == '\\' ) { + p++; + if ( *p != '\0' ) { + str_append_c(part, *p); + p++; + } else break; + } else if ( *p == ':' ) { + if ( strcasecmp(str_c(part), "SIEVE") == 0 ) + cap_type = CAP_SIEVE; + else if ( strcasecmp(str_c(part), "NOTIFY") == 0 ) + cap_type = CAP_NOTIFY; + else + i_warning("managesieve-login: unknown capability '%s' listed in " + "capability string (ignored).", str_c(part)); + str_truncate(part, 0); + } else if ( *p == ',' ) { + capability_store(cap_type, str_c(part)); + str_truncate(part, 0); + } else { + /* Append character, but omit leading spaces */ + if ( str_len(part) > 0 || *p != ' ' ) + str_append_c(part, *p); + } + p++; + } + + if ( str_len(part) > 0 ) { + capability_store(cap_type, str_c(part)); + } +} + +static bool capability_dump(void) +{ + char buf[4096]; + int fd[2], status = 0; + ssize_t ret; + unsigned int pos; + pid_t pid; + + if ( getenv("DUMP_CAPABILITY") != NULL ) + return TRUE; + + if ( pipe(fd) < 0 ) { + i_error("managesieve-login: dump-capability pipe() failed: %m"); + return FALSE; + } + fd_close_on_exec(fd[0], TRUE); + fd_close_on_exec(fd[1], TRUE); + + if ( (pid = fork()) == (pid_t)-1 ) { + (void)close(fd[0]); (void)close(fd[1]); + i_error("managesieve-login: dump-capability fork() failed: %m"); + return FALSE; + } + + if ( pid == 0 ) { + const char *argv[5]; + + /* Child */ + (void)close(fd[0]); + + if (dup2(fd[1], STDOUT_FILENO) < 0) + i_fatal("managesieve-login: dump-capability dup2() failed: %m"); + + env_put("DUMP_CAPABILITY", "1"); + + argv[0] = PKG_LIBEXECDIR"/managesieve"; + argv[1] = "-k"; + argv[2] = "-c"; + argv[3] = master_service_get_config_path(master_service); + argv[4] = NULL; + execv_const(argv[0], argv); + + i_fatal("managesieve-login: dump-capability execv(%s) failed: %m", argv[0]); + } + + (void)close(fd[1]); + + alarm(60); + if (wait(&status) == -1) { + i_error("managesieve-login: dump-capability failed: process %d got stuck", + (int)pid); + return FALSE; + } + alarm(0); + + if (status != 0) { + (void)close(fd[0]); + if (WIFSIGNALED(status)) { + i_error("managesieve-login: dump-capability process " + "killed with signal %d", WTERMSIG(status)); + } else { + i_error("managesieve-login: dump-capability process returned %d", + WIFEXITED(status) ? WEXITSTATUS(status) : status); + } + return FALSE; + } + + pos = 0; + while ((ret = read(fd[0], buf + pos, sizeof(buf) - pos)) > 0) + pos += ret; + + if (ret < 0) { + i_error("managesieve-login: read(dump-capability process) failed: %m"); + (void)close(fd[0]); + return FALSE; + } + (void)close(fd[0]); + + if (pos == 0 || buf[pos-1] != '\n') { + i_error("managesieve-login: dump-capability: Couldn't read capability " + "(got %u bytes)", pos); + return FALSE; + } + buf[pos-1] = '\0'; + + capability_parse(buf); + + return TRUE; +} + +static void managesieve_login_config_set +(struct config_parser_context *ctx, const char *key, const char *value) +{ + config_apply_line(ctx, key, t_strdup_printf("%s=%s", key, value), NULL); +} + +static void managesieve_login_config_parser_begin(struct config_parser_context *ctx) +{ + const char *const *module = ctx->modules; + + if ( module != NULL && *module != NULL ) { + while ( *module != NULL ) { + if ( strcmp(*module, "managesieve-login") == 0 ) + break; + module++; + } + if ( *module == NULL ) + return; + } + + if ( !capability_dumped ) { + (void)capability_dump(); + capability_dumped = TRUE; + } + + if ( capability_sieve != NULL ) + managesieve_login_config_set(ctx, "managesieve_sieve_capability", capability_sieve); + + if ( capability_notify != NULL ) + managesieve_login_config_set(ctx, "managesieve_notify_capability", capability_notify); +} diff --git a/pigeonhole/src/managesieve-login/managesieve-login-settings-plugin.h b/pigeonhole/src/managesieve-login/managesieve-login-settings-plugin.h new file mode 100644 index 0000000..ebefe1a --- /dev/null +++ b/pigeonhole/src/managesieve-login/managesieve-login-settings-plugin.h @@ -0,0 +1,9 @@ +#ifndef MANAGESIEVE_LOGIN_SETTINGS_PLUGIN_H +#define MANAGESIEVE_LOGIN_SETTINGS_PLUGIN_H + +#include "lib.h" + +void managesieve_login_settings_init(struct module *module); +void managesieve_login_settings_deinit(void); + +#endif diff --git a/pigeonhole/src/managesieve-login/managesieve-login-settings.c b/pigeonhole/src/managesieve-login/managesieve-login-settings.c new file mode 100644 index 0000000..9146d03 --- /dev/null +++ b/pigeonhole/src/managesieve-login/managesieve-login-settings.c @@ -0,0 +1,104 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "buffer.h" +#include "env-util.h" +#include "execv-const.h" +#include "settings-parser.h" +#include "service-settings.h" +#include "login-settings.h" + +#include "pigeonhole-config.h" + +#include "managesieve-login-settings.h" + +#include <stddef.h> +#include <unistd.h> +#include <sys/wait.h> +#include <sysexits.h> + +/* <settings checks> */ + +static struct inet_listener_settings managesieve_login_inet_listeners_array[] = { + { .name = "sieve", .address = "", .port = 4190 }, +}; +static struct inet_listener_settings *managesieve_login_inet_listeners[] = { + &managesieve_login_inet_listeners_array[0] +}; +static buffer_t managesieve_login_inet_listeners_buf = { + { { managesieve_login_inet_listeners, + sizeof(managesieve_login_inet_listeners) } } +}; +/* </settings checks> */ + +struct service_settings managesieve_login_settings_service_settings = { + .name = "managesieve-login", + .protocol = "sieve", + .type = "login", + .executable = "managesieve-login", + .user = "$default_login_user", + .group = "", + .privileged_group = "", + .extra_groups = "", + .chroot = "login", + + .drop_priv_before_exec = FALSE, + + .process_min_avail = 0, + .process_limit = 0, + .client_limit = 0, + .service_count = 1, + .idle_kill = 0, + .vsz_limit = (uoff_t)-1, + + .unix_listeners = ARRAY_INIT, + .fifo_listeners = ARRAY_INIT, + .inet_listeners = { { &managesieve_login_inet_listeners_buf, + sizeof(managesieve_login_inet_listeners[0]) } } +}; + +#undef DEF +#define DEF(type, name) \ + SETTING_DEFINE_STRUCT_##type(#name, name, struct managesieve_login_settings) + +static const struct setting_define managesieve_login_setting_defines[] = { + DEF(STR, managesieve_implementation_string), + DEF(STR, managesieve_sieve_capability), + DEF(STR, managesieve_notify_capability), + + SETTING_DEFINE_LIST_END +}; + +static const struct managesieve_login_settings managesieve_login_default_settings = { + .managesieve_implementation_string = DOVECOT_NAME " " PIGEONHOLE_NAME, + .managesieve_sieve_capability = "", + .managesieve_notify_capability = NULL +}; + +static const struct setting_parser_info *managesieve_login_setting_dependencies[] = { + &login_setting_parser_info, + NULL +}; + +static const struct setting_parser_info managesieve_login_setting_parser_info = { + .module_name = "managesieve-login", + .defines = managesieve_login_setting_defines, + .defaults = &managesieve_login_default_settings, + + .type_offset = (size_t)-1, + .struct_size = sizeof(struct managesieve_login_settings), + + .parent_offset = (size_t)-1, + .parent = NULL, + + .dependencies = managesieve_login_setting_dependencies +}; + +const struct setting_parser_info *managesieve_login_settings_set_roots[] = { + &login_setting_parser_info, + &managesieve_login_setting_parser_info, + NULL +}; + diff --git a/pigeonhole/src/managesieve-login/managesieve-login-settings.h b/pigeonhole/src/managesieve-login/managesieve-login-settings.h new file mode 100644 index 0000000..c6f4826 --- /dev/null +++ b/pigeonhole/src/managesieve-login/managesieve-login-settings.h @@ -0,0 +1,17 @@ +#ifndef MANAGESIEVE_LOGIN_SETTINGS_H +#define MANAGESIEVE_LOGIN_SETTINGS_H + +struct managesieve_login_settings { + const char *managesieve_implementation_string; + const char *managesieve_sieve_capability; + const char *managesieve_notify_capability; +}; + +extern const struct setting_parser_info *managesieve_login_settings_set_roots[]; + +#ifdef _CONFIG_PLUGIN +void managesieve_login_settings_init(void); +void managesieve_login_settings_deinit(void); +#endif + +#endif diff --git a/pigeonhole/src/managesieve-login/managesieve-proxy.c b/pigeonhole/src/managesieve-login/managesieve-proxy.c new file mode 100644 index 0000000..50e31ae --- /dev/null +++ b/pigeonhole/src/managesieve-login/managesieve-proxy.c @@ -0,0 +1,686 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include <string.h> +#include "login-common.h" +#include "ioloop.h" +#include "istream.h" +#include "ostream.h" +#include "str.h" +#include "str-sanitize.h" +#include "strescape.h" +#include "safe-memset.h" +#include "buffer.h" +#include "base64.h" +#include "dsasl-client.h" + +#include "client.h" +#include "client-authenticate.h" + +#include "managesieve-quote.h" +#include "managesieve-proxy.h" +#include "managesieve-parser.h" + +typedef enum { + MANAGESIEVE_RESPONSE_NONE, + MANAGESIEVE_RESPONSE_OK, + MANAGESIEVE_RESPONSE_NO, + MANAGESIEVE_RESPONSE_BYE +} managesieve_response_t; + +static const char *managesieve_proxy_state_names[MSIEVE_PROXY_STATE_COUNT] = { + "none", "tls-start", "tls-ready", "xclient", "auth" +}; + +static string_t * +proxy_compose_xclient_forward(struct managesieve_client *client) +{ + const char *const *arg; + string_t *str; + + if (*client->common.auth_passdb_args == NULL) + return NULL; + + str = t_str_new(128); + for (arg = client->common.auth_passdb_args; *arg != NULL; arg++) { + if (strncasecmp(*arg, "forward_", 8) == 0) { + if (str_len(str) > 0) + str_append_c(str, '\t'); + str_append_tabescaped(str, (*arg)+8); + } + } + if (str_len(str) == 0) + return NULL; + + return str; +} + +static void +proxy_write_xclient(struct managesieve_client *client, string_t *str) +{ + string_t *fwd = proxy_compose_xclient_forward(client); + + str_printfa(str, "XCLIENT ADDR=%s PORT=%u SESSION=%s TTL=%u", + net_ip2addr(&client->common.ip), client->common.remote_port, + client_get_session_id(&client->common), + client->common.proxy_ttl - 1); + if (fwd != NULL) { + str_append(str, " FORWARD="); + base64_encode(str_data(fwd), str_len(fwd), str); + } + str_append(str, "\r\n"); +} + +static void +proxy_write_auth_data(const unsigned char *data, unsigned int data_len, + string_t *str) +{ + if (data_len == 0) + str_append(str, "\"\""); + else { + string_t *data_str = t_str_new(128); + base64_encode(data, data_len, data_str); + managesieve_quote_append_string(str, str_c(data_str), FALSE); + } +} + +static int +proxy_write_auth(struct managesieve_client *client, string_t *str) +{ + struct dsasl_client_settings sasl_set; + const unsigned char *output; + size_t len; + const char *mech_name, *error; + + i_assert(client->common.proxy_ttl > 1); + + if (!client->proxy_sasl) { + /* Prevent sending credentials to a server that has login + disabled; i.e., due to the lack of TLS */ + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_REMOTE_CONFIG, + "Server has disabled authentication (TLS required?)"); + return -1; + } + + if (client->common.proxy_mech == NULL) + client->common.proxy_mech = &dsasl_client_mech_plain; + + i_assert(client->common.proxy_sasl_client == NULL); + i_zero(&sasl_set); + sasl_set.authid = (client->common.proxy_master_user != NULL ? + client->common.proxy_master_user : + client->common.proxy_user); + sasl_set.authzid = client->common.proxy_user; + sasl_set.password = client->common.proxy_password; + client->common.proxy_sasl_client = + dsasl_client_new(client->common.proxy_mech, &sasl_set); + mech_name = dsasl_client_mech_get_name(client->common.proxy_mech); + + str_append(str, "AUTHENTICATE "); + managesieve_quote_append_string(str, mech_name, FALSE); + if (dsasl_client_output(client->common.proxy_sasl_client, + &output, &len, &error) < 0) { + const char *reason = t_strdup_printf( + "SASL mechanism %s init failed: %s", + mech_name, error); + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_INTERNAL, reason); + return -1; + } + if (len > 0) { + str_append_c(str, ' '); + proxy_write_auth_data(output, len, str); + } + str_append(str, "\r\n"); + return 0; +} + +static int +proxy_input_auth_challenge(struct managesieve_client *client, const char *line, + const char **challenge_r) +{ + struct istream *input; + struct managesieve_parser *parser; + const struct managesieve_arg *args; + const char *challenge; + bool fatal = FALSE; + int ret; + + i_assert(client->common.proxy_sasl_client != NULL); + *challenge_r = NULL; + + /* Build an input stream for the managesieve parser. + FIXME: Ugly, see proxy_input_capability(). + */ + line = t_strconcat(line, "\r\n", NULL); + input = i_stream_create_from_data(line, strlen(line)); + parser = managesieve_parser_create(input, MAX_MANAGESIEVE_LINE); + managesieve_parser_reset(parser); + + (void)i_stream_read(input); + ret = managesieve_parser_read_args(parser, 1, 0, &args); + + if (ret >= 0) { + if (ret > 0 && + managesieve_arg_get_string(&args[0], &challenge)) { + *challenge_r = t_strdup(challenge); + } else { + const char *reason = t_strdup_printf( + "Server sent invalid SASL challenge line: %s", + str_sanitize(line,160)); + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, reason); + fatal = TRUE; + } + + } else if (ret == -2) { + /* Parser needs more data (not possible on mem stream) */ + i_unreached(); + + } else { + const char *error_str = + managesieve_parser_get_error(parser, &fatal); + error_str = (error_str != NULL ? error_str : "unknown (bug)"); + + /* Do not accept faulty server */ + const char *reason = t_strdup_printf( + "Protocol parse error(%d) int SASL challenge line: %s " + "(line=`%s')", ret, error_str, line); + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, reason); + fatal = TRUE; + } + + + /* Cleanup parser */ + managesieve_parser_destroy(&parser); + i_stream_destroy(&input); + + /* Time to exit if greeting was not accepted */ + if (fatal) + return -1; + return 0; +} + +static int +proxy_write_auth_response(struct managesieve_client *client, + const char *challenge, string_t *str) +{ + const unsigned char *data; + size_t data_len; + const char *error; + int ret; + + if (base64_decode(challenge, strlen(challenge), NULL, str) < 0) { + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, + "Server sent invalid base64 data in AUTHENTICATE response"); + return -1; + } + ret = dsasl_client_input(client->common.proxy_sasl_client, + str_data(str), str_len(str), &error); + if (ret == 0) { + ret = dsasl_client_output(client->common.proxy_sasl_client, + &data, &data_len, &error); + } + if (ret < 0) { + const char *reason = t_strdup_printf( + "Server sent invalid authentication data: %s", error); + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, reason); + return -1; + } + i_assert(ret == 0); + + str_truncate(str, 0); + proxy_write_auth_data(data, data_len, str); + str_append(str, "\r\n"); + return 0; +} + +static managesieve_response_t +proxy_read_response(const struct managesieve_arg *args) +{ + const char *response; + + if (managesieve_arg_get_atom(&args[0], &response)) { + if (strcasecmp(response, "OK") == 0) { + /* Received OK response; greeting is finished */ + return MANAGESIEVE_RESPONSE_OK; + + } else if (strcasecmp(response, "NO") == 0) { + /* Received OK response; greeting is finished */ + return MANAGESIEVE_RESPONSE_NO; + + } else if (strcasecmp(response, "BYE") == 0) { + /* Received OK response; greeting is finished */ + return MANAGESIEVE_RESPONSE_BYE; + } + } + return MANAGESIEVE_RESPONSE_NONE; +} + +static int +proxy_input_capability(struct managesieve_client *client, const char *line, + managesieve_response_t *resp_r) +{ + struct istream *input; + struct managesieve_parser *parser; + const struct managesieve_arg *args; + const char *capability; + int ret; + bool fatal = FALSE; + + *resp_r = MANAGESIEVE_RESPONSE_NONE; + + /* Build an input stream for the managesieve parser + + FIXME: It would be nice if the line-wise parsing could be substituded + by something similar to the command line interpreter. However, + the current login_proxy structure does not make streams known + until inside proxy_input handler. + */ + line = t_strconcat(line, "\r\n", NULL); + input = i_stream_create_from_data(line, strlen(line)); + parser = managesieve_parser_create(input, MAX_MANAGESIEVE_LINE); + managesieve_parser_reset(parser); + + /* Parse input + + FIXME: Theoretically the OK response could include a response code + which could be rejected by the parser. + */ + (void)i_stream_read(input); + ret = managesieve_parser_read_args(parser, 2, 0, &args); + + if (ret == 0) { + const char *reason = t_strdup_printf( + "Remote returned with invalid capability/greeting line: %s", + str_sanitize(line,160)); + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, reason); + fatal = TRUE; + } else if (ret > 0) { + if (args[0].type == MANAGESIEVE_ARG_ATOM) { + *resp_r = proxy_read_response(args); + + if (*resp_r == MANAGESIEVE_RESPONSE_NONE) { + const char *reason = t_strdup_printf( + "Remote sent invalid response: %s", + str_sanitize(line,160)); + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, + reason); + + fatal = TRUE; + } + } else if (managesieve_arg_get_string(&args[0], &capability)) { + if (strcasecmp(capability, "SASL") == 0) { + const char *sasl_mechs; + + /* Check whether the server supports the SASL mechanism + we are going to use (currently only PLAIN supported). + */ + if (ret == 2 && + managesieve_arg_get_string(&args[1], &sasl_mechs)) { + const char *const *mechs = t_strsplit(sasl_mechs, " "); + + if (*mechs != NULL) { + /* At least one SASL mechanism is supported */ + client->proxy_sasl = TRUE; + } + + } else { + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, + "Server returned erroneous SASL capability"); + fatal = TRUE; + } + + } else if (strcasecmp(capability, "STARTTLS") == 0) { + client->proxy_starttls = TRUE; + } else if (strcasecmp(capability, "XCLIENT") == 0) { + client->proxy_xclient = TRUE; + } + + } else { + /* Do not accept faulty server */ + const char *reason = t_strdup_printf( + "Remote returned with invalid capability/greeting line: %s", + str_sanitize(line,160)); + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, reason); + fatal = TRUE; + } + + } else if (ret == -2) { + /* Parser needs more data (not possible on mem stream) */ + i_unreached(); + + } else { + const char *error_str = + managesieve_parser_get_error(parser, &fatal); + error_str = (error_str != NULL ? error_str : "unknown (bug)"); + + /* Do not accept faulty server */ + const char *reason = t_strdup_printf( + "Protocol parse error(%d) in capability/greeting line: %s " + "(line=`%s')", ret, error_str, line); + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, reason); + fatal = TRUE; + } + + /* Cleanup parser */ + managesieve_parser_destroy(&parser); + i_stream_destroy(&input); + + /* Time to exit if greeting was not accepted */ + if (fatal) + return -1; + + /* Wait until greeting is received completely */ + if (*resp_r == MANAGESIEVE_RESPONSE_NONE) + return 1; + + return 0; +} + +static void +managesieve_proxy_parse_auth_reply(const char *line, + const char **reason_r, bool *trylater_r) +{ + struct managesieve_parser *parser; + const struct managesieve_arg *args; + struct istream *input; + const char *reason; + int ret; + + *trylater_r = FALSE; + + if (strncasecmp(line, "NO ", 3) != 0) { + *reason_r = line; + return; + } + line += 3; + *reason_r = line; + + if (line[0] == '(') { + /* Parse optional resp-code. FIXME: The current + managesieve-parser can't really handle this properly, so + we'll just assume that there aren't any strings with ')' + in them. */ + if (strncasecmp(line, "(TRYLATER) ", 11) == 0) { + *trylater_r = TRUE; + line += 11; + } else { + line = strstr(line, ") "); + if (line == NULL) + return; + line += 2; + } + } + + /* Parse the string */ + input = i_stream_create_from_data(line, strlen(line)); + parser = managesieve_parser_create(input, (size_t)-1); + (void)i_stream_read(input); + ret = managesieve_parser_finish_line(parser, 0, 0, &args); + if (ret == 1 && managesieve_arg_get_string(&args[0], &reason)) + *reason_r = t_strdup(reason); + managesieve_parser_destroy(&parser); + i_stream_destroy(&input); +} + +int managesieve_proxy_parse_line(struct client *client, const char *line) +{ + struct managesieve_client *msieve_client = + (struct managesieve_client *)client; + struct ostream *output; + enum login_proxy_ssl_flags ssl_flags; + managesieve_response_t response = MANAGESIEVE_RESPONSE_NONE; + string_t *command; + int ret = 0; + + i_assert(!client->destroyed); + + output = login_proxy_get_ostream(client->login_proxy); + switch (msieve_client->proxy_state) { + case MSIEVE_PROXY_STATE_NONE: + ret = proxy_input_capability(msieve_client, line, &response); + if (ret < 0) + return -1; + if (ret == 0) { + if (response != MANAGESIEVE_RESPONSE_OK) { + login_proxy_failed(client->login_proxy, + login_proxy_get_event(client->login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, + "Remote sent unexpected NO/BYE instead of capability response"); + return -1; + } + + command = t_str_new(128); + + ssl_flags = login_proxy_get_ssl_flags(client->login_proxy); + if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) != 0) { + if (!msieve_client->proxy_starttls) { + login_proxy_failed(client->login_proxy, + login_proxy_get_event(client->login_proxy), + LOGIN_PROXY_FAILURE_TYPE_REMOTE_CONFIG, + "Remote doesn't support STARTTLS"); + return -1; + } + + str_append(command, "STARTTLS\r\n"); + msieve_client->proxy_state = MSIEVE_PROXY_STATE_TLS_START; + } else if (msieve_client->proxy_xclient) { + proxy_write_xclient(msieve_client, command); + msieve_client->proxy_state = MSIEVE_PROXY_STATE_XCLIENT; + } else { + if (proxy_write_auth(msieve_client, command) < 0) + return -1; + msieve_client->proxy_state = MSIEVE_PROXY_STATE_AUTH; + } + + o_stream_nsend(output, str_data(command), str_len(command)); + } + return 0; + case MSIEVE_PROXY_STATE_TLS_START: + if (strncasecmp(line, "OK", 2) == 0 && + (strlen(line) == 2 || line[2] == ' ')) { + /* STARTTLS successful, begin TLS negotiation. */ + if (login_proxy_starttls(client->login_proxy) < 0) + return -1; + + msieve_client->proxy_sasl = FALSE; + msieve_client->proxy_xclient = FALSE; + msieve_client->proxy_state = MSIEVE_PROXY_STATE_TLS_READY; + return 1; + } + + login_proxy_failed(client->login_proxy, + login_proxy_get_event(client->login_proxy), + LOGIN_PROXY_FAILURE_TYPE_REMOTE, + "Remote refused STARTTLS command"); + return -1; + case MSIEVE_PROXY_STATE_TLS_READY: + ret = proxy_input_capability(msieve_client, line, &response); + if (ret < 0) + return -1; + if (ret == 0) { + if (response != MANAGESIEVE_RESPONSE_OK) { + /* STARTTLS failed */ + const char *reason = t_strdup_printf( + "Remote STARTTLS failed: %s", + str_sanitize(line, 160)); + login_proxy_failed(client->login_proxy, + login_proxy_get_event(client->login_proxy), + LOGIN_PROXY_FAILURE_TYPE_REMOTE, reason); + return -1; + } + + command = t_str_new(128); + if (msieve_client->proxy_xclient) { + proxy_write_xclient(msieve_client, command); + msieve_client->proxy_state = MSIEVE_PROXY_STATE_XCLIENT; + } else { + if (proxy_write_auth(msieve_client, command) < 0) + return -1; + msieve_client->proxy_state = MSIEVE_PROXY_STATE_AUTH; + } + o_stream_nsend(output, str_data(command), str_len(command)); + } + return 0; + case MSIEVE_PROXY_STATE_XCLIENT: + if (strncasecmp(line, "OK", 2) == 0 && + (strlen(line) == 2 || line[2] == ' ')) { + command = t_str_new(128); + if (proxy_write_auth(msieve_client, command) < 0) + return -1; + o_stream_nsend(output, str_data(command), str_len(command)); + msieve_client->proxy_state = MSIEVE_PROXY_STATE_AUTH; + return 0; + } + + const char *reason = t_strdup_printf( + "Remote XCLIENT failed: %s", + str_sanitize(line, 160)); + login_proxy_failed(client->login_proxy, + login_proxy_get_event(client->login_proxy), + LOGIN_PROXY_FAILURE_TYPE_REMOTE, reason); + return -1; + case MSIEVE_PROXY_STATE_AUTH: + /* Challenge? */ + if (*line == '"') { + const char *challenge; + + if (proxy_input_auth_challenge(msieve_client, line, + &challenge) < 0) + return -1; + command = t_str_new(128); + if (proxy_write_auth_response(msieve_client, challenge, + command) < 0) + return -1; + o_stream_nsend(output, str_data(command), + str_len(command)); + return 0; + } + + /* Check login status */ + if (strncasecmp(line, "OK", 2) == 0 && + (strlen(line) == 2 || line[2] == ' ')) { + string_t *str = t_str_new(128); + + /* Login successful */ + + /* FIXME: Some SASL mechanisms cause a capability + response to be sent. + */ + + /* Send this line to client. */ + str_append(str, line); + str_append(str, "\r\n"); + o_stream_nsend(client->output, str_data(str), + str_len(str)); + + client_proxy_finish_destroy_client(client); + return 1; + } + + /* Authentication failed */ + bool try_later; + (void)managesieve_proxy_parse_auth_reply(line, &reason, + &try_later); + + /* Login failed. Send our own failure reply so client can't + figure out if user exists or not just by looking at the reply + string. + */ + enum login_proxy_failure_type failure_type; + if (try_later) + failure_type = LOGIN_PROXY_FAILURE_TYPE_AUTH_TEMPFAIL; + else { + failure_type = LOGIN_PROXY_FAILURE_TYPE_AUTH; + client_send_no(client, AUTH_FAILED_MSG); + } + + login_proxy_failed(client->login_proxy, + login_proxy_get_event(client->login_proxy), + failure_type, reason); + return -1; + default: + /* Not supposed to happen */ + break; + } + + i_unreached(); + return -1; +} + +void managesieve_proxy_reset(struct client *client) +{ + struct managesieve_client *msieve_client = + (struct managesieve_client *)client; + + msieve_client->proxy_starttls = FALSE; + msieve_client->proxy_sasl = FALSE; + msieve_client->proxy_xclient = FALSE; + msieve_client->proxy_state = MSIEVE_PROXY_STATE_NONE; +} + +static void +managesieve_proxy_send_failure_reply(struct client *client, + enum login_proxy_failure_type type, + const char *reason) +{ + switch (type) { + case LOGIN_PROXY_FAILURE_TYPE_CONNECT: + case LOGIN_PROXY_FAILURE_TYPE_INTERNAL: + case LOGIN_PROXY_FAILURE_TYPE_REMOTE: + case LOGIN_PROXY_FAILURE_TYPE_PROTOCOL: + client_send_reply_code(client, MANAGESIEVE_CMD_REPLY_NO, + "TRYLATER", LOGIN_PROXY_FAILURE_MSG); + break; + case LOGIN_PROXY_FAILURE_TYPE_INTERNAL_CONFIG: + case LOGIN_PROXY_FAILURE_TYPE_REMOTE_CONFIG: + client_send_reply_code(client, MANAGESIEVE_CMD_REPLY_NO, + NULL, LOGIN_PROXY_FAILURE_MSG); + break; + case LOGIN_PROXY_FAILURE_TYPE_AUTH_TEMPFAIL: + client_send_reply_code(client, MANAGESIEVE_CMD_REPLY_NO, + "TRYLATER", reason); + break; + case LOGIN_PROXY_FAILURE_TYPE_AUTH: + /* reply was already sent */ + break; + } +} + +void managesieve_proxy_failed(struct client *client, + enum login_proxy_failure_type type, + const char *reason, bool reconnecting) +{ + if (!reconnecting) + managesieve_proxy_send_failure_reply(client, type, reason); + client_common_proxy_failed(client, type, reason, reconnecting); +} + +const char *managesieve_proxy_get_state(struct client *client) +{ + struct managesieve_client *msieve_client = + (struct managesieve_client *)client; + + return managesieve_proxy_state_names[msieve_client->proxy_state]; +} diff --git a/pigeonhole/src/managesieve-login/managesieve-proxy.h b/pigeonhole/src/managesieve-login/managesieve-proxy.h new file mode 100644 index 0000000..946f074 --- /dev/null +++ b/pigeonhole/src/managesieve-login/managesieve-proxy.h @@ -0,0 +1,12 @@ +#ifndef MANAGESIEVE_PROXY_H +#define MANAGESIEVE_PROXY_H + +void managesieve_proxy_reset(struct client *client); +int managesieve_proxy_parse_line(struct client *client, const char *line); + +void managesieve_proxy_failed(struct client *client, + enum login_proxy_failure_type type, + const char *reason, bool reconnecting); +const char *managesieve_proxy_get_state(struct client *client); + +#endif diff --git a/pigeonhole/src/managesieve/Makefile.am b/pigeonhole/src/managesieve/Makefile.am new file mode 100644 index 0000000..17b5790 --- /dev/null +++ b/pigeonhole/src/managesieve/Makefile.am @@ -0,0 +1,59 @@ +settingsdir = $(dovecot_moduledir)/settings + +dovecot_pkglibexec_PROGRAMS = managesieve + +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_SERVICE_INCLUDE) \ + -DMODULEDIR=\""$(dovecot_moduledir)"\" \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/lib-sieve \ + -I$(top_srcdir)/src/lib-managesieve + +libmanagesieve_settings_la_LDFLAGS = -module -avoid-version + +settings_LTLIBRARIES = \ + libmanagesieve_settings.la + +libmanagesieve_settings_la_SOURCES = \ + managesieve-settings.c + +libs = \ + managesieve-settings.lo \ + $(top_builddir)/src/lib-managesieve/libmanagesieve.la \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la + +managesieve_CPPFLAGS = $(AM_CPPFLAGS) $(BINARY_CFLAGS) +managesieve_LDFLAGS = -export-dynamic $(BINARY_LDFLAGS) + +managesieve_LDADD = $(libs) $(LIBDOVECOT_STORAGE) $(LIBDOVECOT_LDA) $(LIBDOVECOT) + +managesieve_DEPENDENCIES = $(libs) $(LIBDOVECOT_STORAGE_DEPS) $(LIBDOVECOT_LDA_DEPS) $(LIBDOVECOT_DEPS) + +cmds = \ + cmd-capability.c \ + cmd-logout.c \ + cmd-putscript.c \ + cmd-getscript.c \ + cmd-setactive.c \ + cmd-deletescript.c \ + cmd-listscripts.c \ + cmd-havespace.c \ + cmd-renamescript.c \ + cmd-noop.c + +managesieve_SOURCES = \ + $(cmds) \ + managesieve-quota.c \ + managesieve-client.c \ + managesieve-commands.c \ + managesieve-capabilities.c \ + main.c + +noinst_HEADERS = \ + managesieve-quota.h \ + managesieve-client.h \ + managesieve-commands.h \ + managesieve-capabilities.h \ + managesieve-settings.h \ + managesieve-common.h diff --git a/pigeonhole/src/managesieve/Makefile.in b/pigeonhole/src/managesieve/Makefile.in new file mode 100644 index 0000000..d8f9faa --- /dev/null +++ b/pigeonhole/src/managesieve/Makefile.in @@ -0,0 +1,1134 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +dovecot_pkglibexec_PROGRAMS = managesieve$(EXEEXT) +subdir = src/managesieve +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(dovecot_pkglibexecdir)" \ + "$(DESTDIR)$(settingsdir)" +PROGRAMS = $(dovecot_pkglibexec_PROGRAMS) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +LTLIBRARIES = $(settings_LTLIBRARIES) +libmanagesieve_settings_la_LIBADD = +am_libmanagesieve_settings_la_OBJECTS = managesieve-settings.lo +libmanagesieve_settings_la_OBJECTS = \ + $(am_libmanagesieve_settings_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libmanagesieve_settings_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libmanagesieve_settings_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +am__objects_1 = managesieve-cmd-capability.$(OBJEXT) \ + managesieve-cmd-logout.$(OBJEXT) \ + managesieve-cmd-putscript.$(OBJEXT) \ + managesieve-cmd-getscript.$(OBJEXT) \ + managesieve-cmd-setactive.$(OBJEXT) \ + managesieve-cmd-deletescript.$(OBJEXT) \ + managesieve-cmd-listscripts.$(OBJEXT) \ + managesieve-cmd-havespace.$(OBJEXT) \ + managesieve-cmd-renamescript.$(OBJEXT) \ + managesieve-cmd-noop.$(OBJEXT) +am_managesieve_OBJECTS = $(am__objects_1) \ + managesieve-managesieve-quota.$(OBJEXT) \ + managesieve-managesieve-client.$(OBJEXT) \ + managesieve-managesieve-commands.$(OBJEXT) \ + managesieve-managesieve-capabilities.$(OBJEXT) \ + managesieve-main.$(OBJEXT) +managesieve_OBJECTS = $(am_managesieve_OBJECTS) +am__DEPENDENCIES_1 = +managesieve_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(managesieve_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/managesieve-cmd-capability.Po \ + ./$(DEPDIR)/managesieve-cmd-deletescript.Po \ + ./$(DEPDIR)/managesieve-cmd-getscript.Po \ + ./$(DEPDIR)/managesieve-cmd-havespace.Po \ + ./$(DEPDIR)/managesieve-cmd-listscripts.Po \ + ./$(DEPDIR)/managesieve-cmd-logout.Po \ + ./$(DEPDIR)/managesieve-cmd-noop.Po \ + ./$(DEPDIR)/managesieve-cmd-putscript.Po \ + ./$(DEPDIR)/managesieve-cmd-renamescript.Po \ + ./$(DEPDIR)/managesieve-cmd-setactive.Po \ + ./$(DEPDIR)/managesieve-main.Po \ + ./$(DEPDIR)/managesieve-managesieve-capabilities.Po \ + ./$(DEPDIR)/managesieve-managesieve-client.Po \ + ./$(DEPDIR)/managesieve-managesieve-commands.Po \ + ./$(DEPDIR)/managesieve-managesieve-quota.Po \ + ./$(DEPDIR)/managesieve-settings.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libmanagesieve_settings_la_SOURCES) $(managesieve_SOURCES) +DIST_SOURCES = $(libmanagesieve_settings_la_SOURCES) \ + $(managesieve_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +settingsdir = $(dovecot_moduledir)/settings +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_SERVICE_INCLUDE) \ + -DMODULEDIR=\""$(dovecot_moduledir)"\" \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/lib-sieve \ + -I$(top_srcdir)/src/lib-managesieve + +libmanagesieve_settings_la_LDFLAGS = -module -avoid-version +settings_LTLIBRARIES = \ + libmanagesieve_settings.la + +libmanagesieve_settings_la_SOURCES = \ + managesieve-settings.c + +libs = \ + managesieve-settings.lo \ + $(top_builddir)/src/lib-managesieve/libmanagesieve.la \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la + +managesieve_CPPFLAGS = $(AM_CPPFLAGS) $(BINARY_CFLAGS) +managesieve_LDFLAGS = -export-dynamic $(BINARY_LDFLAGS) +managesieve_LDADD = $(libs) $(LIBDOVECOT_STORAGE) $(LIBDOVECOT_LDA) $(LIBDOVECOT) +managesieve_DEPENDENCIES = $(libs) $(LIBDOVECOT_STORAGE_DEPS) $(LIBDOVECOT_LDA_DEPS) $(LIBDOVECOT_DEPS) +cmds = \ + cmd-capability.c \ + cmd-logout.c \ + cmd-putscript.c \ + cmd-getscript.c \ + cmd-setactive.c \ + cmd-deletescript.c \ + cmd-listscripts.c \ + cmd-havespace.c \ + cmd-renamescript.c \ + cmd-noop.c + +managesieve_SOURCES = \ + $(cmds) \ + managesieve-quota.c \ + managesieve-client.c \ + managesieve-commands.c \ + managesieve-capabilities.c \ + main.c + +noinst_HEADERS = \ + managesieve-quota.h \ + managesieve-client.h \ + managesieve-commands.h \ + managesieve-capabilities.h \ + managesieve-settings.h \ + managesieve-common.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/managesieve/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/managesieve/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dovecot_pkglibexecPROGRAMS: $(dovecot_pkglibexec_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(dovecot_pkglibexec_PROGRAMS)'; test -n "$(dovecot_pkglibexecdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(dovecot_pkglibexecdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(dovecot_pkglibexecdir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(dovecot_pkglibexecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(dovecot_pkglibexecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-dovecot_pkglibexecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(dovecot_pkglibexec_PROGRAMS)'; test -n "$(dovecot_pkglibexecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(dovecot_pkglibexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(dovecot_pkglibexecdir)" && rm -f $$files + +clean-dovecot_pkglibexecPROGRAMS: + @list='$(dovecot_pkglibexec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +install-settingsLTLIBRARIES: $(settings_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(settings_LTLIBRARIES)'; test -n "$(settingsdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(settingsdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(settingsdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(settingsdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(settingsdir)"; \ + } + +uninstall-settingsLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(settings_LTLIBRARIES)'; test -n "$(settingsdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(settingsdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(settingsdir)/$$f"; \ + done + +clean-settingsLTLIBRARIES: + -test -z "$(settings_LTLIBRARIES)" || rm -f $(settings_LTLIBRARIES) + @list='$(settings_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libmanagesieve_settings.la: $(libmanagesieve_settings_la_OBJECTS) $(libmanagesieve_settings_la_DEPENDENCIES) $(EXTRA_libmanagesieve_settings_la_DEPENDENCIES) + $(AM_V_CCLD)$(libmanagesieve_settings_la_LINK) -rpath $(settingsdir) $(libmanagesieve_settings_la_OBJECTS) $(libmanagesieve_settings_la_LIBADD) $(LIBS) + +managesieve$(EXEEXT): $(managesieve_OBJECTS) $(managesieve_DEPENDENCIES) $(EXTRA_managesieve_DEPENDENCIES) + @rm -f managesieve$(EXEEXT) + $(AM_V_CCLD)$(managesieve_LINK) $(managesieve_OBJECTS) $(managesieve_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-cmd-capability.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-cmd-deletescript.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-cmd-getscript.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-cmd-havespace.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-cmd-listscripts.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-cmd-logout.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-cmd-noop.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-cmd-putscript.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-cmd-renamescript.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-cmd-setactive.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-main.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-managesieve-capabilities.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-managesieve-client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-managesieve-commands.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-managesieve-quota.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve-settings.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +managesieve-cmd-capability.o: cmd-capability.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-capability.o -MD -MP -MF $(DEPDIR)/managesieve-cmd-capability.Tpo -c -o managesieve-cmd-capability.o `test -f 'cmd-capability.c' || echo '$(srcdir)/'`cmd-capability.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-capability.Tpo $(DEPDIR)/managesieve-cmd-capability.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-capability.c' object='managesieve-cmd-capability.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-capability.o `test -f 'cmd-capability.c' || echo '$(srcdir)/'`cmd-capability.c + +managesieve-cmd-capability.obj: cmd-capability.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-capability.obj -MD -MP -MF $(DEPDIR)/managesieve-cmd-capability.Tpo -c -o managesieve-cmd-capability.obj `if test -f 'cmd-capability.c'; then $(CYGPATH_W) 'cmd-capability.c'; else $(CYGPATH_W) '$(srcdir)/cmd-capability.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-capability.Tpo $(DEPDIR)/managesieve-cmd-capability.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-capability.c' object='managesieve-cmd-capability.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-capability.obj `if test -f 'cmd-capability.c'; then $(CYGPATH_W) 'cmd-capability.c'; else $(CYGPATH_W) '$(srcdir)/cmd-capability.c'; fi` + +managesieve-cmd-logout.o: cmd-logout.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-logout.o -MD -MP -MF $(DEPDIR)/managesieve-cmd-logout.Tpo -c -o managesieve-cmd-logout.o `test -f 'cmd-logout.c' || echo '$(srcdir)/'`cmd-logout.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-logout.Tpo $(DEPDIR)/managesieve-cmd-logout.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-logout.c' object='managesieve-cmd-logout.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-logout.o `test -f 'cmd-logout.c' || echo '$(srcdir)/'`cmd-logout.c + +managesieve-cmd-logout.obj: cmd-logout.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-logout.obj -MD -MP -MF $(DEPDIR)/managesieve-cmd-logout.Tpo -c -o managesieve-cmd-logout.obj `if test -f 'cmd-logout.c'; then $(CYGPATH_W) 'cmd-logout.c'; else $(CYGPATH_W) '$(srcdir)/cmd-logout.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-logout.Tpo $(DEPDIR)/managesieve-cmd-logout.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-logout.c' object='managesieve-cmd-logout.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-logout.obj `if test -f 'cmd-logout.c'; then $(CYGPATH_W) 'cmd-logout.c'; else $(CYGPATH_W) '$(srcdir)/cmd-logout.c'; fi` + +managesieve-cmd-putscript.o: cmd-putscript.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-putscript.o -MD -MP -MF $(DEPDIR)/managesieve-cmd-putscript.Tpo -c -o managesieve-cmd-putscript.o `test -f 'cmd-putscript.c' || echo '$(srcdir)/'`cmd-putscript.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-putscript.Tpo $(DEPDIR)/managesieve-cmd-putscript.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-putscript.c' object='managesieve-cmd-putscript.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-putscript.o `test -f 'cmd-putscript.c' || echo '$(srcdir)/'`cmd-putscript.c + +managesieve-cmd-putscript.obj: cmd-putscript.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-putscript.obj -MD -MP -MF $(DEPDIR)/managesieve-cmd-putscript.Tpo -c -o managesieve-cmd-putscript.obj `if test -f 'cmd-putscript.c'; then $(CYGPATH_W) 'cmd-putscript.c'; else $(CYGPATH_W) '$(srcdir)/cmd-putscript.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-putscript.Tpo $(DEPDIR)/managesieve-cmd-putscript.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-putscript.c' object='managesieve-cmd-putscript.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-putscript.obj `if test -f 'cmd-putscript.c'; then $(CYGPATH_W) 'cmd-putscript.c'; else $(CYGPATH_W) '$(srcdir)/cmd-putscript.c'; fi` + +managesieve-cmd-getscript.o: cmd-getscript.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-getscript.o -MD -MP -MF $(DEPDIR)/managesieve-cmd-getscript.Tpo -c -o managesieve-cmd-getscript.o `test -f 'cmd-getscript.c' || echo '$(srcdir)/'`cmd-getscript.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-getscript.Tpo $(DEPDIR)/managesieve-cmd-getscript.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-getscript.c' object='managesieve-cmd-getscript.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-getscript.o `test -f 'cmd-getscript.c' || echo '$(srcdir)/'`cmd-getscript.c + +managesieve-cmd-getscript.obj: cmd-getscript.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-getscript.obj -MD -MP -MF $(DEPDIR)/managesieve-cmd-getscript.Tpo -c -o managesieve-cmd-getscript.obj `if test -f 'cmd-getscript.c'; then $(CYGPATH_W) 'cmd-getscript.c'; else $(CYGPATH_W) '$(srcdir)/cmd-getscript.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-getscript.Tpo $(DEPDIR)/managesieve-cmd-getscript.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-getscript.c' object='managesieve-cmd-getscript.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-getscript.obj `if test -f 'cmd-getscript.c'; then $(CYGPATH_W) 'cmd-getscript.c'; else $(CYGPATH_W) '$(srcdir)/cmd-getscript.c'; fi` + +managesieve-cmd-setactive.o: cmd-setactive.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-setactive.o -MD -MP -MF $(DEPDIR)/managesieve-cmd-setactive.Tpo -c -o managesieve-cmd-setactive.o `test -f 'cmd-setactive.c' || echo '$(srcdir)/'`cmd-setactive.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-setactive.Tpo $(DEPDIR)/managesieve-cmd-setactive.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-setactive.c' object='managesieve-cmd-setactive.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-setactive.o `test -f 'cmd-setactive.c' || echo '$(srcdir)/'`cmd-setactive.c + +managesieve-cmd-setactive.obj: cmd-setactive.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-setactive.obj -MD -MP -MF $(DEPDIR)/managesieve-cmd-setactive.Tpo -c -o managesieve-cmd-setactive.obj `if test -f 'cmd-setactive.c'; then $(CYGPATH_W) 'cmd-setactive.c'; else $(CYGPATH_W) '$(srcdir)/cmd-setactive.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-setactive.Tpo $(DEPDIR)/managesieve-cmd-setactive.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-setactive.c' object='managesieve-cmd-setactive.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-setactive.obj `if test -f 'cmd-setactive.c'; then $(CYGPATH_W) 'cmd-setactive.c'; else $(CYGPATH_W) '$(srcdir)/cmd-setactive.c'; fi` + +managesieve-cmd-deletescript.o: cmd-deletescript.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-deletescript.o -MD -MP -MF $(DEPDIR)/managesieve-cmd-deletescript.Tpo -c -o managesieve-cmd-deletescript.o `test -f 'cmd-deletescript.c' || echo '$(srcdir)/'`cmd-deletescript.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-deletescript.Tpo $(DEPDIR)/managesieve-cmd-deletescript.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-deletescript.c' object='managesieve-cmd-deletescript.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-deletescript.o `test -f 'cmd-deletescript.c' || echo '$(srcdir)/'`cmd-deletescript.c + +managesieve-cmd-deletescript.obj: cmd-deletescript.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-deletescript.obj -MD -MP -MF $(DEPDIR)/managesieve-cmd-deletescript.Tpo -c -o managesieve-cmd-deletescript.obj `if test -f 'cmd-deletescript.c'; then $(CYGPATH_W) 'cmd-deletescript.c'; else $(CYGPATH_W) '$(srcdir)/cmd-deletescript.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-deletescript.Tpo $(DEPDIR)/managesieve-cmd-deletescript.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-deletescript.c' object='managesieve-cmd-deletescript.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-deletescript.obj `if test -f 'cmd-deletescript.c'; then $(CYGPATH_W) 'cmd-deletescript.c'; else $(CYGPATH_W) '$(srcdir)/cmd-deletescript.c'; fi` + +managesieve-cmd-listscripts.o: cmd-listscripts.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-listscripts.o -MD -MP -MF $(DEPDIR)/managesieve-cmd-listscripts.Tpo -c -o managesieve-cmd-listscripts.o `test -f 'cmd-listscripts.c' || echo '$(srcdir)/'`cmd-listscripts.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-listscripts.Tpo $(DEPDIR)/managesieve-cmd-listscripts.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-listscripts.c' object='managesieve-cmd-listscripts.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-listscripts.o `test -f 'cmd-listscripts.c' || echo '$(srcdir)/'`cmd-listscripts.c + +managesieve-cmd-listscripts.obj: cmd-listscripts.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-listscripts.obj -MD -MP -MF $(DEPDIR)/managesieve-cmd-listscripts.Tpo -c -o managesieve-cmd-listscripts.obj `if test -f 'cmd-listscripts.c'; then $(CYGPATH_W) 'cmd-listscripts.c'; else $(CYGPATH_W) '$(srcdir)/cmd-listscripts.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-listscripts.Tpo $(DEPDIR)/managesieve-cmd-listscripts.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-listscripts.c' object='managesieve-cmd-listscripts.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-listscripts.obj `if test -f 'cmd-listscripts.c'; then $(CYGPATH_W) 'cmd-listscripts.c'; else $(CYGPATH_W) '$(srcdir)/cmd-listscripts.c'; fi` + +managesieve-cmd-havespace.o: cmd-havespace.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-havespace.o -MD -MP -MF $(DEPDIR)/managesieve-cmd-havespace.Tpo -c -o managesieve-cmd-havespace.o `test -f 'cmd-havespace.c' || echo '$(srcdir)/'`cmd-havespace.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-havespace.Tpo $(DEPDIR)/managesieve-cmd-havespace.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-havespace.c' object='managesieve-cmd-havespace.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-havespace.o `test -f 'cmd-havespace.c' || echo '$(srcdir)/'`cmd-havespace.c + +managesieve-cmd-havespace.obj: cmd-havespace.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-havespace.obj -MD -MP -MF $(DEPDIR)/managesieve-cmd-havespace.Tpo -c -o managesieve-cmd-havespace.obj `if test -f 'cmd-havespace.c'; then $(CYGPATH_W) 'cmd-havespace.c'; else $(CYGPATH_W) '$(srcdir)/cmd-havespace.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-havespace.Tpo $(DEPDIR)/managesieve-cmd-havespace.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-havespace.c' object='managesieve-cmd-havespace.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-havespace.obj `if test -f 'cmd-havespace.c'; then $(CYGPATH_W) 'cmd-havespace.c'; else $(CYGPATH_W) '$(srcdir)/cmd-havespace.c'; fi` + +managesieve-cmd-renamescript.o: cmd-renamescript.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-renamescript.o -MD -MP -MF $(DEPDIR)/managesieve-cmd-renamescript.Tpo -c -o managesieve-cmd-renamescript.o `test -f 'cmd-renamescript.c' || echo '$(srcdir)/'`cmd-renamescript.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-renamescript.Tpo $(DEPDIR)/managesieve-cmd-renamescript.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-renamescript.c' object='managesieve-cmd-renamescript.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-renamescript.o `test -f 'cmd-renamescript.c' || echo '$(srcdir)/'`cmd-renamescript.c + +managesieve-cmd-renamescript.obj: cmd-renamescript.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-renamescript.obj -MD -MP -MF $(DEPDIR)/managesieve-cmd-renamescript.Tpo -c -o managesieve-cmd-renamescript.obj `if test -f 'cmd-renamescript.c'; then $(CYGPATH_W) 'cmd-renamescript.c'; else $(CYGPATH_W) '$(srcdir)/cmd-renamescript.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-renamescript.Tpo $(DEPDIR)/managesieve-cmd-renamescript.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-renamescript.c' object='managesieve-cmd-renamescript.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-renamescript.obj `if test -f 'cmd-renamescript.c'; then $(CYGPATH_W) 'cmd-renamescript.c'; else $(CYGPATH_W) '$(srcdir)/cmd-renamescript.c'; fi` + +managesieve-cmd-noop.o: cmd-noop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-noop.o -MD -MP -MF $(DEPDIR)/managesieve-cmd-noop.Tpo -c -o managesieve-cmd-noop.o `test -f 'cmd-noop.c' || echo '$(srcdir)/'`cmd-noop.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-noop.Tpo $(DEPDIR)/managesieve-cmd-noop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-noop.c' object='managesieve-cmd-noop.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-noop.o `test -f 'cmd-noop.c' || echo '$(srcdir)/'`cmd-noop.c + +managesieve-cmd-noop.obj: cmd-noop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-cmd-noop.obj -MD -MP -MF $(DEPDIR)/managesieve-cmd-noop.Tpo -c -o managesieve-cmd-noop.obj `if test -f 'cmd-noop.c'; then $(CYGPATH_W) 'cmd-noop.c'; else $(CYGPATH_W) '$(srcdir)/cmd-noop.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-cmd-noop.Tpo $(DEPDIR)/managesieve-cmd-noop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmd-noop.c' object='managesieve-cmd-noop.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-cmd-noop.obj `if test -f 'cmd-noop.c'; then $(CYGPATH_W) 'cmd-noop.c'; else $(CYGPATH_W) '$(srcdir)/cmd-noop.c'; fi` + +managesieve-managesieve-quota.o: managesieve-quota.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-managesieve-quota.o -MD -MP -MF $(DEPDIR)/managesieve-managesieve-quota.Tpo -c -o managesieve-managesieve-quota.o `test -f 'managesieve-quota.c' || echo '$(srcdir)/'`managesieve-quota.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-managesieve-quota.Tpo $(DEPDIR)/managesieve-managesieve-quota.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-quota.c' object='managesieve-managesieve-quota.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-managesieve-quota.o `test -f 'managesieve-quota.c' || echo '$(srcdir)/'`managesieve-quota.c + +managesieve-managesieve-quota.obj: managesieve-quota.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-managesieve-quota.obj -MD -MP -MF $(DEPDIR)/managesieve-managesieve-quota.Tpo -c -o managesieve-managesieve-quota.obj `if test -f 'managesieve-quota.c'; then $(CYGPATH_W) 'managesieve-quota.c'; else $(CYGPATH_W) '$(srcdir)/managesieve-quota.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-managesieve-quota.Tpo $(DEPDIR)/managesieve-managesieve-quota.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-quota.c' object='managesieve-managesieve-quota.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-managesieve-quota.obj `if test -f 'managesieve-quota.c'; then $(CYGPATH_W) 'managesieve-quota.c'; else $(CYGPATH_W) '$(srcdir)/managesieve-quota.c'; fi` + +managesieve-managesieve-client.o: managesieve-client.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-managesieve-client.o -MD -MP -MF $(DEPDIR)/managesieve-managesieve-client.Tpo -c -o managesieve-managesieve-client.o `test -f 'managesieve-client.c' || echo '$(srcdir)/'`managesieve-client.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-managesieve-client.Tpo $(DEPDIR)/managesieve-managesieve-client.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-client.c' object='managesieve-managesieve-client.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-managesieve-client.o `test -f 'managesieve-client.c' || echo '$(srcdir)/'`managesieve-client.c + +managesieve-managesieve-client.obj: managesieve-client.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-managesieve-client.obj -MD -MP -MF $(DEPDIR)/managesieve-managesieve-client.Tpo -c -o managesieve-managesieve-client.obj `if test -f 'managesieve-client.c'; then $(CYGPATH_W) 'managesieve-client.c'; else $(CYGPATH_W) '$(srcdir)/managesieve-client.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-managesieve-client.Tpo $(DEPDIR)/managesieve-managesieve-client.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-client.c' object='managesieve-managesieve-client.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-managesieve-client.obj `if test -f 'managesieve-client.c'; then $(CYGPATH_W) 'managesieve-client.c'; else $(CYGPATH_W) '$(srcdir)/managesieve-client.c'; fi` + +managesieve-managesieve-commands.o: managesieve-commands.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-managesieve-commands.o -MD -MP -MF $(DEPDIR)/managesieve-managesieve-commands.Tpo -c -o managesieve-managesieve-commands.o `test -f 'managesieve-commands.c' || echo '$(srcdir)/'`managesieve-commands.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-managesieve-commands.Tpo $(DEPDIR)/managesieve-managesieve-commands.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-commands.c' object='managesieve-managesieve-commands.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-managesieve-commands.o `test -f 'managesieve-commands.c' || echo '$(srcdir)/'`managesieve-commands.c + +managesieve-managesieve-commands.obj: managesieve-commands.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-managesieve-commands.obj -MD -MP -MF $(DEPDIR)/managesieve-managesieve-commands.Tpo -c -o managesieve-managesieve-commands.obj `if test -f 'managesieve-commands.c'; then $(CYGPATH_W) 'managesieve-commands.c'; else $(CYGPATH_W) '$(srcdir)/managesieve-commands.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-managesieve-commands.Tpo $(DEPDIR)/managesieve-managesieve-commands.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-commands.c' object='managesieve-managesieve-commands.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-managesieve-commands.obj `if test -f 'managesieve-commands.c'; then $(CYGPATH_W) 'managesieve-commands.c'; else $(CYGPATH_W) '$(srcdir)/managesieve-commands.c'; fi` + +managesieve-managesieve-capabilities.o: managesieve-capabilities.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-managesieve-capabilities.o -MD -MP -MF $(DEPDIR)/managesieve-managesieve-capabilities.Tpo -c -o managesieve-managesieve-capabilities.o `test -f 'managesieve-capabilities.c' || echo '$(srcdir)/'`managesieve-capabilities.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-managesieve-capabilities.Tpo $(DEPDIR)/managesieve-managesieve-capabilities.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-capabilities.c' object='managesieve-managesieve-capabilities.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-managesieve-capabilities.o `test -f 'managesieve-capabilities.c' || echo '$(srcdir)/'`managesieve-capabilities.c + +managesieve-managesieve-capabilities.obj: managesieve-capabilities.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-managesieve-capabilities.obj -MD -MP -MF $(DEPDIR)/managesieve-managesieve-capabilities.Tpo -c -o managesieve-managesieve-capabilities.obj `if test -f 'managesieve-capabilities.c'; then $(CYGPATH_W) 'managesieve-capabilities.c'; else $(CYGPATH_W) '$(srcdir)/managesieve-capabilities.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-managesieve-capabilities.Tpo $(DEPDIR)/managesieve-managesieve-capabilities.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-capabilities.c' object='managesieve-managesieve-capabilities.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-managesieve-capabilities.obj `if test -f 'managesieve-capabilities.c'; then $(CYGPATH_W) 'managesieve-capabilities.c'; else $(CYGPATH_W) '$(srcdir)/managesieve-capabilities.c'; fi` + +managesieve-main.o: main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-main.o -MD -MP -MF $(DEPDIR)/managesieve-main.Tpo -c -o managesieve-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-main.Tpo $(DEPDIR)/managesieve-main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main.c' object='managesieve-main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c + +managesieve-main.obj: main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve-main.obj -MD -MP -MF $(DEPDIR)/managesieve-main.Tpo -c -o managesieve-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve-main.Tpo $(DEPDIR)/managesieve-main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main.c' object='managesieve-main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(dovecot_pkglibexecdir)" "$(DESTDIR)$(settingsdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-dovecot_pkglibexecPROGRAMS clean-generic clean-libtool \ + clean-settingsLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/managesieve-cmd-capability.Po + -rm -f ./$(DEPDIR)/managesieve-cmd-deletescript.Po + -rm -f ./$(DEPDIR)/managesieve-cmd-getscript.Po + -rm -f ./$(DEPDIR)/managesieve-cmd-havespace.Po + -rm -f ./$(DEPDIR)/managesieve-cmd-listscripts.Po + -rm -f ./$(DEPDIR)/managesieve-cmd-logout.Po + -rm -f ./$(DEPDIR)/managesieve-cmd-noop.Po + -rm -f ./$(DEPDIR)/managesieve-cmd-putscript.Po + -rm -f ./$(DEPDIR)/managesieve-cmd-renamescript.Po + -rm -f ./$(DEPDIR)/managesieve-cmd-setactive.Po + -rm -f ./$(DEPDIR)/managesieve-main.Po + -rm -f ./$(DEPDIR)/managesieve-managesieve-capabilities.Po + -rm -f ./$(DEPDIR)/managesieve-managesieve-client.Po + -rm -f ./$(DEPDIR)/managesieve-managesieve-commands.Po + -rm -f ./$(DEPDIR)/managesieve-managesieve-quota.Po + -rm -f ./$(DEPDIR)/managesieve-settings.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-settingsLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-dovecot_pkglibexecPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/managesieve-cmd-capability.Po + -rm -f ./$(DEPDIR)/managesieve-cmd-deletescript.Po + -rm -f ./$(DEPDIR)/managesieve-cmd-getscript.Po + -rm -f ./$(DEPDIR)/managesieve-cmd-havespace.Po + -rm -f ./$(DEPDIR)/managesieve-cmd-listscripts.Po + -rm -f ./$(DEPDIR)/managesieve-cmd-logout.Po + -rm -f ./$(DEPDIR)/managesieve-cmd-noop.Po + -rm -f ./$(DEPDIR)/managesieve-cmd-putscript.Po + -rm -f ./$(DEPDIR)/managesieve-cmd-renamescript.Po + -rm -f ./$(DEPDIR)/managesieve-cmd-setactive.Po + -rm -f ./$(DEPDIR)/managesieve-main.Po + -rm -f ./$(DEPDIR)/managesieve-managesieve-capabilities.Po + -rm -f ./$(DEPDIR)/managesieve-managesieve-client.Po + -rm -f ./$(DEPDIR)/managesieve-managesieve-commands.Po + -rm -f ./$(DEPDIR)/managesieve-managesieve-quota.Po + -rm -f ./$(DEPDIR)/managesieve-settings.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dovecot_pkglibexecPROGRAMS \ + uninstall-settingsLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-dovecot_pkglibexecPROGRAMS clean-generic clean-libtool \ + clean-settingsLTLIBRARIES cscopelist-am ctags ctags-am \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dovecot_pkglibexecPROGRAMS install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-settingsLTLIBRARIES install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am \ + uninstall-dovecot_pkglibexecPROGRAMS \ + uninstall-settingsLTLIBRARIES + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/managesieve/cmd-capability.c b/pigeonhole/src/managesieve/cmd-capability.c new file mode 100644 index 0000000..1d26eb5 --- /dev/null +++ b/pigeonhole/src/managesieve/cmd-capability.c @@ -0,0 +1,76 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "strfuncs.h" +#include "ostream.h" + +#include "sieve.h" + +#include "managesieve-common.h" +#include "managesieve-commands.h" + +static void send_capability(struct client_command_context *cmd) +{ + struct client *client = cmd->client; + const char *sievecap, *notifycap; + unsigned int max_redirects; + + /* Get capabilities */ + sievecap = sieve_get_capabilities(client->svinst, NULL); + notifycap = sieve_get_capabilities(client->svinst, "notify"); + max_redirects = sieve_max_redirects(client->svinst); + + /* Default capabilities */ + client_send_line(client, + t_strconcat( + "\"IMPLEMENTATION\" \"", + client->set->managesieve_implementation_string, + "\"", NULL)); + client_send_line(client, + t_strconcat( + "\"SIEVE\" \"", + (sievecap == NULL ? "" : sievecap), + "\"", NULL)); + + /* Maximum number of redirects (if limited) */ + if (max_redirects > 0) { + client_send_line(client, + t_strdup_printf("\"MAXREDIRECTS\" \"%u\"", + max_redirects)); + } + + /* Notify methods */ + if (notifycap != NULL) { + client_send_line(client, + t_strconcat("\"NOTIFY\" \"", notifycap, "\"", + NULL)); + } + + /* Protocol version */ + client_send_line(client, "\"VERSION\" \"1.0\""); +} + +bool cmd_capability(struct client_command_context *cmd) +{ + struct client *client = cmd->client; + + /* no arguments */ + if (!client_read_no_args(cmd)) + return FALSE; + + o_stream_cork(client->output); + + T_BEGIN { + send_capability(cmd); + } T_END; + + client_send_line(client, "OK \"Capability completed.\""); + + o_stream_uncork(client->output); + + return TRUE; + +} + diff --git a/pigeonhole/src/managesieve/cmd-deletescript.c b/pigeonhole/src/managesieve/cmd-deletescript.c new file mode 100644 index 0000000..a8be5c9 --- /dev/null +++ b/pigeonhole/src/managesieve/cmd-deletescript.c @@ -0,0 +1,43 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "managesieve-common.h" +#include "managesieve-commands.h" + +bool cmd_deletescript(struct client_command_context *cmd) +{ + struct client *client = cmd->client; + struct sieve_storage *storage = client->storage; + const char *scriptname; + struct sieve_script *script; + + /* <script name>*/ + if (!client_read_string_args(cmd, TRUE, 1, &scriptname)) + return FALSE; + + event_add_str(cmd->event, "script_name", scriptname); + + script = sieve_storage_open_script(storage, scriptname, NULL); + if (script == NULL || sieve_script_delete(script, FALSE) < 0) { + client_command_storage_error( + cmd, "Failed to delete script `%s'", scriptname); + sieve_script_unref(&script); + return TRUE; + } + + struct event_passthrough *e = + client_command_create_finish_event(cmd); + e_debug(e->event(), "Deleted script `%s'", scriptname); + + client->deleted_count++; + client_send_ok(client, "Deletescript completed."); + + sieve_script_unref(&script); + return TRUE; +} diff --git a/pigeonhole/src/managesieve/cmd-getscript.c b/pigeonhole/src/managesieve/cmd-getscript.c new file mode 100644 index 0000000..2f0a5f9 --- /dev/null +++ b/pigeonhole/src/managesieve/cmd-getscript.c @@ -0,0 +1,157 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "ostream.h" +#include "istream.h" +#include "iostream.h" + +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "managesieve-common.h" +#include "managesieve-commands.h" + +struct cmd_getscript_context { + struct client *client; + struct client_command_context *cmd; + struct sieve_storage *storage; + uoff_t script_size; + + const char *scriptname; + struct sieve_script *script; + struct istream *script_stream; + + bool failed:1; +}; + +static bool cmd_getscript_finish(struct cmd_getscript_context *ctx) +{ + struct client_command_context *cmd = ctx->cmd; + struct client *client = ctx->client; + + if (ctx->script != NULL) + sieve_script_unref(&ctx->script); + + if (ctx->failed) { + if (client->output->closed) { + client_disconnect(client, NULL); + return TRUE; + } + + client_command_storage_error( + cmd, "Failed to retrieve script `%s'", ctx->scriptname); + return TRUE; + } + + client->get_count++; + client->get_bytes += ctx->script_size; + + struct event_passthrough *e = + client_command_create_finish_event(cmd); + e_debug(e->event(), "Retrieved script `%s'", ctx->scriptname); + + client_send_line(client, ""); + client_send_ok(client, "Getscript completed."); + return TRUE; +} + +static bool cmd_getscript_continue(struct client_command_context *cmd) +{ + struct client *client = cmd->client; + struct cmd_getscript_context *ctx = cmd->context; + + switch (o_stream_send_istream(client->output, ctx->script_stream)) { + case OSTREAM_SEND_ISTREAM_RESULT_FINISHED: + if (ctx->script_stream->v_offset != ctx->script_size && + !ctx->failed) { + /* Input stream gave less data than expected */ + sieve_storage_set_critical( + ctx->storage, "GETSCRIPT for script `%s' " + "from %s got too little data: " + "%"PRIuUOFF_T" vs %"PRIuUOFF_T, + sieve_script_name(ctx->script), + sieve_script_location(ctx->script), + ctx->script_stream->v_offset, ctx->script_size); + client_disconnect(ctx->client, "GETSCRIPT failed"); + ctx->failed = TRUE; + } + break; + case OSTREAM_SEND_ISTREAM_RESULT_WAIT_INPUT: + i_unreached(); + case OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT: + return FALSE; + case OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT: + sieve_storage_set_critical(ctx->storage, + "o_stream_send_istream() failed for script `%s' " + "from %s: %s", + sieve_script_name(ctx->script), + sieve_script_location(ctx->script), + i_stream_get_error(ctx->script_stream)); + ctx->failed = TRUE; + break; + case OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT: + client_disconnect(ctx->client, NULL); + ctx->failed = TRUE; + break; + } + return cmd_getscript_finish(ctx); +} + +bool cmd_getscript(struct client_command_context *cmd) +{ + struct client *client = cmd->client; + struct cmd_getscript_context *ctx; + const char *scriptname; + enum sieve_error error; + + /* <scriptname> */ + if (!client_read_string_args(cmd, TRUE, 1, &scriptname)) + return FALSE; + + event_add_str(cmd->event, "script_name", scriptname); + + ctx = p_new(cmd->pool, struct cmd_getscript_context, 1); + ctx->cmd = cmd; + ctx->client = client; + ctx->scriptname = p_strdup(cmd->pool, scriptname); + ctx->storage = client->storage; + ctx->failed = FALSE; + + ctx->script = sieve_storage_open_script(client->storage, scriptname, + NULL); + if (ctx->script == NULL) { + ctx->failed = TRUE; + return cmd_getscript_finish(ctx); + } + + if (sieve_script_get_stream(ctx->script, &ctx->script_stream, + &error) < 0 ) { + if (error == SIEVE_ERROR_NOT_FOUND) { + sieve_storage_set_error(client->storage, error, + "Script does not exist."); + } + ctx->failed = TRUE; + return cmd_getscript_finish(ctx); + } + + if (sieve_script_get_size(ctx->script, &ctx->script_size) <= 0) { + sieve_storage_set_critical(ctx->storage, + "failed to obtain script size for script `%s' from %s", + sieve_script_name(ctx->script), + sieve_script_location(ctx->script)); + ctx->failed = TRUE; + return cmd_getscript_finish(ctx); + } + + i_assert(ctx->script_stream->v_offset == 0); + + client_send_line(client, t_strdup_printf("{%"PRIuUOFF_T"}", + ctx->script_size)); + + client->command_pending = TRUE; + cmd->func = cmd_getscript_continue; + cmd->context = ctx; + + return cmd_getscript_continue(cmd); +} diff --git a/pigeonhole/src/managesieve/cmd-havespace.c b/pigeonhole/src/managesieve/cmd-havespace.c new file mode 100644 index 0000000..5af2bb1 --- /dev/null +++ b/pigeonhole/src/managesieve/cmd-havespace.c @@ -0,0 +1,60 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "managesieve-common.h" +#include "managesieve-commands.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "managesieve-client.h" +#include "managesieve-quota.h" + +bool cmd_havespace(struct client_command_context *cmd) +{ + struct client *client = cmd->client; + const struct managesieve_arg *args; + const char *scriptname; + uoff_t size; + + /* <scriptname> <size> */ + if (!client_read_args(cmd, 2, 0, TRUE, &args)) + return FALSE; + + if (!managesieve_arg_get_string(&args[0], &scriptname)) { + client_send_no(client, "Invalid string for scriptname."); + return TRUE; + } + + if (!managesieve_arg_get_number(&args[1], &size)) { + client_send_no(client, "Invalid scriptsize argument."); + return TRUE; + } + + if (!sieve_script_name_is_valid(scriptname)) { + client_send_no(client, "Invalid script name."); + return TRUE; + } + + if (size == 0) { + client_send_no(client, "Cannot upload empty script."); + return TRUE; + } + + event_add_str(cmd->event, "script_name", scriptname); + event_add_int(cmd->event, "script_size", size); + + if (!managesieve_quota_check_all(cmd, scriptname, size)) + return TRUE; + + struct event_passthrough *e = + client_command_create_finish_event(cmd); + e_debug(e->event(), "Quota is within limits for script `%s' " + "with size %"PRIuUOFF_T, scriptname, size); + + client_send_ok(client, "Putscript would succeed."); + return TRUE; +} diff --git a/pigeonhole/src/managesieve/cmd-listscripts.c b/pigeonhole/src/managesieve/cmd-listscripts.c new file mode 100644 index 0000000..9e6abd2 --- /dev/null +++ b/pigeonhole/src/managesieve/cmd-listscripts.c @@ -0,0 +1,65 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" + +#include "sieve.h" +#include "sieve-storage.h" + +#include "managesieve-quote.h" + +#include "managesieve-common.h" +#include "managesieve-commands.h" + +bool cmd_listscripts(struct client_command_context *cmd) +{ + struct client *client = cmd->client; + struct sieve_storage_list_context *ctx; + const char *scriptname; + unsigned int script_count = 0; + bool active; + string_t *str; + + /* no arguments */ + if (!client_read_no_args(cmd)) + return FALSE; + + if ((ctx = sieve_storage_list_init(client->storage)) == NULL) { + client_command_storage_error( + cmd, "Failed to list scripts"); + return TRUE; + } + + /* FIXME: This will be quite slow for large script lists. Implement + * some buffering to fix this. Wont truely be an issue with managesieve + * though. + */ + while ((scriptname = sieve_storage_list_next(ctx, &active)) != NULL) { + T_BEGIN { + str = t_str_new(128); + + managesieve_quote_append_string(str, scriptname, FALSE); + + if (active) + str_append(str, " ACTIVE"); + + client_send_line(client, str_c(str)); + } T_END; + + script_count++; + } + + if (sieve_storage_list_deinit(&ctx) < 0) { + client_command_storage_error( + cmd, "Failed to list scripts"); + return TRUE; + } + + struct event_passthrough *e = + client_command_create_finish_event(cmd); + e_debug(e->event(), "Listed %u scripts", script_count); + + client_send_ok(client, "Listscripts completed."); + return TRUE; +} diff --git a/pigeonhole/src/managesieve/cmd-logout.c b/pigeonhole/src/managesieve/cmd-logout.c new file mode 100644 index 0000000..9e0847d --- /dev/null +++ b/pigeonhole/src/managesieve/cmd-logout.c @@ -0,0 +1,21 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "ostream.h" + +#include "managesieve-common.h" +#include "managesieve-commands.h" + +bool cmd_logout(struct client_command_context *cmd) +{ + struct client *client = cmd->client; + + /* no arguments */ + if (!client_read_no_args(cmd)) + return FALSE; + + client_send_line(client, "OK \"Logout completed.\""); + client_disconnect(client, "Logged out"); + return TRUE; +} diff --git a/pigeonhole/src/managesieve/cmd-noop.c b/pigeonhole/src/managesieve/cmd-noop.c new file mode 100644 index 0000000..76d96c3 --- /dev/null +++ b/pigeonhole/src/managesieve/cmd-noop.c @@ -0,0 +1,46 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" + +#include "managesieve-quote.h" + +#include "managesieve-common.h" +#include "managesieve-commands.h" + + +bool cmd_noop(struct client_command_context *cmd) +{ + struct client *client = cmd->client; + const struct managesieve_arg *args; + const char *text; + string_t *resp_code; + + /* [<echo string>] */ + if (!client_read_args(cmd, 0, 0, FALSE, &args)) + return FALSE; + + if (MANAGESIEVE_ARG_IS_EOL(&args[0])) { + client_send_ok(client, "NOOP Completed"); + return TRUE; + } + + if (!managesieve_arg_get_string(&args[0], &text)) { + client_send_no(client, "Invalid echo tag."); + return TRUE; + } + + if (!MANAGESIEVE_ARG_IS_EOL(&args[1])) { + client_send_command_error(cmd, "Too many arguments."); + return TRUE; + } + + resp_code = t_str_new(256); + str_append(resp_code, "TAG "); + managesieve_quote_append_string(resp_code, text, FALSE); + + client_send_okresp(client, str_c(resp_code), "Done"); + return TRUE; +} + diff --git a/pigeonhole/src/managesieve/cmd-putscript.c b/pigeonhole/src/managesieve/cmd-putscript.c new file mode 100644 index 0000000..1998cd9 --- /dev/null +++ b/pigeonhole/src/managesieve/cmd-putscript.c @@ -0,0 +1,578 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* NOTE: this file also contains the checkscript command due to its obvious + * similarities. + */ + +#include "lib.h" +#include "ioloop.h" +#include "istream.h" +#include "ostream.h" +#include "iostream.h" +#include "str.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "managesieve-parser.h" + +#include "managesieve-common.h" +#include "managesieve-client.h" +#include "managesieve-commands.h" +#include "managesieve-quota.h" + +#include <sys/time.h> + +struct cmd_putscript_context { + struct client *client; + struct client_command_context *cmd; + struct sieve_storage *storage; + + struct istream *input; + + const char *scriptname; + uoff_t script_size, max_script_size; + + struct managesieve_parser *save_parser; + struct sieve_storage_save_context *save_ctx; + + bool script_size_valid:1; +}; + +static void cmd_putscript_finish(struct cmd_putscript_context *ctx); +static bool cmd_putscript_continue_script(struct client_command_context *cmd); + +static void client_input_putscript(struct client *client) +{ + struct client_command_context *cmd = &client->cmd; + + i_assert(!client->destroyed); + + client->last_input = ioloop_time; + timeout_reset(client->to_idle); + + switch (i_stream_read(client->input)) { + case -1: + /* disconnected */ + cmd_putscript_finish(cmd->context); + /* Reset command so that client_destroy() doesn't try to call + cmd_putscript_continue_script() anymore. */ + _client_reset_command(client); + client_destroy(client, "Disconnected in PUTSCRIPT/CHECKSCRIPT"); + return; + case -2: + cmd_putscript_finish(cmd->context); + if (client->command_pending) { + /* uploaded script data, this is handled internally by + mailbox_save_continue() */ + break; + } + + /* parameter word is longer than max. input buffer size. + this is most likely an error, so skip the new data + until newline is found. */ + client->input_skip_line = TRUE; + + client_send_command_error(cmd, "Too long argument."); + cmd->param_error = TRUE; + _client_reset_command(client); + return; + } + + if (cmd->func(cmd)) { + /* command execution was finished. Note that if cmd_sync() + didn't finish, we didn't get here but the input handler + has already been moved. So don't do anything important + here.. + + reset command once again to reset cmd_sync()'s changes. */ + _client_reset_command(client); + + if (client->input_pending) + client_input(client); + } +} + +static void cmd_putscript_finish(struct cmd_putscript_context *ctx) +{ + managesieve_parser_destroy(&ctx->save_parser); + + io_remove(&ctx->client->io); + o_stream_set_flush_callback(ctx->client->output, + client_output, ctx->client); + + if (ctx->save_ctx != NULL) { + ctx->client->input_skip_line = TRUE; + sieve_storage_save_cancel(&ctx->save_ctx); + } +} + +static bool cmd_putscript_continue_cancel(struct client_command_context *cmd) +{ + struct cmd_putscript_context *ctx = cmd->context; + size_t size; + + (void)i_stream_read(ctx->input); + (void)i_stream_get_data(ctx->input, &size); + i_stream_skip(ctx->input, size); + + if (cmd->client->input->closed || ctx->input->eof || + ctx->input->v_offset == ctx->script_size) { + cmd_putscript_finish(ctx); + return TRUE; + } + return FALSE; +} + +static bool cmd_putscript_cancel(struct cmd_putscript_context *ctx, bool skip) +{ + ctx->client->input_skip_line = TRUE; + + if (!skip) { + cmd_putscript_finish(ctx); + return TRUE; + } + + /* we have to read the nonsynced literal so we don't treat the uploaded + script as commands. */ + ctx->client->command_pending = TRUE; + ctx->cmd->func = cmd_putscript_continue_cancel; + ctx->cmd->context = ctx; + return cmd_putscript_continue_cancel(ctx->cmd); +} + +static void cmd_putscript_storage_error(struct cmd_putscript_context *ctx) +{ + struct client_command_context *cmd = ctx->cmd; + + if (ctx->scriptname == NULL) { + client_command_storage_error(cmd, "Failed to check script"); + } else { + client_command_storage_error(cmd, "Failed to store script `%s'", + ctx->scriptname); + } +} + +static bool cmd_putscript_save(struct cmd_putscript_context *ctx) +{ + /* Commit to save only when this is a putscript command */ + if (ctx->scriptname == NULL) + return TRUE; + + /* Check commit */ + if (sieve_storage_save_commit(&ctx->save_ctx) < 0) { + cmd_putscript_storage_error(ctx); + return FALSE; + } + return TRUE; +} + +static void +cmd_putscript_finish_script(struct cmd_putscript_context *ctx, + struct sieve_script *script) +{ + struct client *client = ctx->client; + struct client_command_context *cmd = ctx->cmd; + struct sieve_error_handler *ehandler; + enum sieve_compile_flags cpflags = + SIEVE_COMPILE_FLAG_NOGLOBAL | SIEVE_COMPILE_FLAG_UPLOADED; + struct sieve_binary *sbin; + bool success = TRUE; + enum sieve_error error; + string_t *errors; + + /* Mark this as an activation when we are replacing the + active script */ + if (sieve_storage_save_will_activate(ctx->save_ctx)) + cpflags |= SIEVE_COMPILE_FLAG_ACTIVATED; + + /* Prepare error handler */ + errors = str_new(default_pool, 1024); + ehandler = sieve_strbuf_ehandler_create( + client->svinst, errors, TRUE, + client->set->managesieve_max_compile_errors); + + /* Compile */ + sbin = sieve_compile_script(script, ehandler, cpflags, &error); + if (sbin == NULL) { + const char *errormsg = NULL, *action; + + if (error != SIEVE_ERROR_NOT_VALID) { + errormsg = sieve_script_get_last_error(script, &error); + if (error == SIEVE_ERROR_NONE) + errormsg = NULL; + } + + action = (ctx->scriptname != NULL ? + t_strdup_printf("store script `%s'", + ctx->scriptname) : + "check script"); + + if (errormsg == NULL) { + struct event_passthrough *e = + client_command_create_finish_event(cmd)-> + add_str("error", "Compilation failed")-> + add_int("compile_errors", + sieve_get_errors(ehandler))-> + add_int("compile_warnings", + sieve_get_warnings(ehandler)); + e_debug(e->event(), "Failed to %s: " + "Compilation failed (%u errors, %u warnings)", + action, sieve_get_errors(ehandler), + sieve_get_warnings(ehandler)); + + client_send_no(client, str_c(errors)); + } else { + struct event_passthrough *e = + client_command_create_finish_event(cmd)-> + add_str("error", errormsg); + e_debug(e->event(), "Failed to %s: %s", + action, errormsg); + + client_send_no(client, errormsg); + } + + success = FALSE; + } else { + sieve_close(&sbin); + + if (!cmd_putscript_save(ctx)) + success = FALSE; + } + + /* Finish up */ + cmd_putscript_finish(ctx); + + /* Report result to user */ + if (success) { + if (ctx->scriptname != NULL) { + client->put_count++; + client->put_bytes += ctx->script_size; + } else { + client->check_count++; + client->check_bytes += ctx->script_size; + } + + struct event_passthrough *e = + client_command_create_finish_event(cmd)-> + add_int("compile_warnings", + sieve_get_warnings(ehandler)); + if (ctx->scriptname != NULL) { + e_debug(e->event(), "Stored script `%s' successfully " + "(%u warnings)", ctx->scriptname, + sieve_get_warnings(ehandler)); + } else { + e_debug(e->event(), "Checked script successfully " + "(%u warnings)", sieve_get_warnings(ehandler)); + } + + if (sieve_get_warnings(ehandler) > 0) + client_send_okresp(client, "WARNINGS", str_c(errors)); + else if (ctx->scriptname != NULL) + client_send_ok(client, "PUTSCRIPT completed."); + else + client_send_ok(client, "Script checked successfully."); + } + + sieve_error_handler_unref(&ehandler); + str_free(&errors); +} + +static void cmd_putscript_handle_script(struct cmd_putscript_context *ctx) +{ + struct client_command_context *cmd = ctx->cmd; + struct sieve_script *script; + + /* Obtain script object for uploaded script */ + script = sieve_storage_save_get_tempscript(ctx->save_ctx); + + /* Check result */ + if (script == NULL) { + cmd_putscript_storage_error(ctx); + cmd_putscript_finish(ctx); + return; + } + + /* If quoted string, the size was not known until now */ + if (!ctx->script_size_valid) { + if (sieve_script_get_size(script, &ctx->script_size) < 0) { + cmd_putscript_storage_error(ctx); + cmd_putscript_finish(ctx); + return; + } + ctx->script_size_valid = TRUE; + + /* Check quota; max size is already checked */ + if (ctx->scriptname != NULL && + !managesieve_quota_check_all(cmd, ctx->scriptname, + ctx->script_size)) { + cmd_putscript_finish(ctx); + return; + } + } + + /* Try to compile and store the script */ + T_BEGIN { + cmd_putscript_finish_script(ctx, script); + } T_END; +} + +static bool cmd_putscript_finish_parsing(struct client_command_context *cmd) +{ + struct client *client = cmd->client; + struct cmd_putscript_context *ctx = cmd->context; + const struct managesieve_arg *args; + int ret; + + /* if error occurs, the CRLF is already read. */ + client->input_skip_line = FALSE; + + /* <script literal> */ + ret = managesieve_parser_read_args(ctx->save_parser, 0, 0, &args); + if (ret == -1 || client->output->closed) { + if (ctx->storage != NULL) { + const char *msg; + bool fatal ATTR_UNUSED; + + msg = managesieve_parser_get_error( + ctx->save_parser, &fatal); + client_send_command_error(cmd, msg); + } + cmd_putscript_finish(ctx); + return TRUE; + } + if (ret < 0) { + /* need more data */ + return FALSE; + } + + if (MANAGESIEVE_ARG_IS_EOL(&args[0])) { + /* Eat away the trailing CRLF */ + client->input_skip_line = TRUE; + + cmd_putscript_handle_script(ctx); + return TRUE; + } + + client_send_command_error(cmd, "Too many command arguments."); + cmd_putscript_finish(ctx); + return TRUE; +} + +static bool cmd_putscript_continue_parsing(struct client_command_context *cmd) +{ + struct client *client = cmd->client; + struct cmd_putscript_context *ctx = cmd->context; + const struct managesieve_arg *args; + int ret; + + /* if error occurs, the CRLF is already read. */ + client->input_skip_line = FALSE; + + /* <script literal> */ + ret = managesieve_parser_read_args( + ctx->save_parser, 0, MANAGESIEVE_PARSE_FLAG_STRING_STREAM, + &args); + if (ret == -1 || client->output->closed) { + cmd_putscript_finish(ctx); + client_send_command_error(cmd, "Invalid arguments."); + client->input_skip_line = TRUE; + return TRUE; + } + if (ret < 0) { + /* need more data */ + return FALSE; + } + + /* Validate the script argument */ + if (!managesieve_arg_get_string_stream(args,&ctx->input)) { + client_send_command_error(cmd, "Invalid arguments."); + return cmd_putscript_cancel(ctx, FALSE); + } + + if (i_stream_get_size(ctx->input, FALSE, &ctx->script_size) > 0) { + ctx->script_size_valid = TRUE; + + /* Check quota */ + if (ctx->scriptname == NULL) { + if (!managesieve_quota_check_validsize( + cmd, ctx->script_size)) + return cmd_putscript_cancel(ctx, TRUE); + } else { + if (!managesieve_quota_check_all( + cmd, ctx->scriptname, ctx->script_size)) + return cmd_putscript_cancel(ctx, TRUE); + } + + } else { + ctx->max_script_size = + managesieve_quota_max_script_size(client); + } + + /* save the script */ + ctx->save_ctx = sieve_storage_save_init(ctx->storage, ctx->scriptname, + ctx->input); + + if (ctx->save_ctx == NULL) { + /* save initialization failed */ + cmd_putscript_storage_error(ctx); + return cmd_putscript_cancel(ctx, TRUE); + } + + /* after literal comes CRLF, if we fail make sure we eat it away */ + client->input_skip_line = TRUE; + + client->command_pending = TRUE; + cmd->func = cmd_putscript_continue_script; + return cmd_putscript_continue_script(cmd); +} + +static bool cmd_putscript_continue_script(struct client_command_context *cmd) +{ + struct client *client = cmd->client; + struct cmd_putscript_context *ctx = cmd->context; + size_t size; + int ret; + + if (ctx->save_ctx != NULL) { + for (;;) { + i_assert(!ctx->script_size_valid || + ctx->input->v_offset <= ctx->script_size); + if (ctx->max_script_size > 0 && + ctx->input->v_offset > ctx->max_script_size) { + (void)managesieve_quota_check_validsize( + cmd, ctx->input->v_offset); + cmd_putscript_finish(ctx); + return TRUE; + } + + ret = i_stream_read(ctx->input); + if ((ret != -1 || ctx->input->stream_errno != EINVAL || + client->input->eof) && + sieve_storage_save_continue(ctx->save_ctx) < 0) { + /* we still have to finish reading the script + from client */ + sieve_storage_save_cancel(&ctx->save_ctx); + break; + } + if (ret == -1 || ret == 0) + break; + } + } + + if (ctx->save_ctx == NULL) { + (void)i_stream_read(ctx->input); + (void)i_stream_get_data(ctx->input, &size); + i_stream_skip(ctx->input, size); + } + + if (ctx->input->eof || client->input->closed) { + bool failed = FALSE; + bool all_written = FALSE; + + if (!ctx->script_size_valid) { + if (!client->input->eof && + ctx->input->stream_errno == EINVAL) { + client_send_command_error( + cmd, t_strdup_printf( + "Invalid input: %s", + i_stream_get_error(ctx->input))); + client->input_skip_line = TRUE; + failed = TRUE; + } + all_written = (ctx->input->eof && + ctx->input->stream_errno == 0); + + } else { + all_written = (ctx->input->v_offset == ctx->script_size); + } + + /* finished */ + ctx->input = NULL; + + if (!failed) { + if (ctx->save_ctx == NULL) { + /* failed above */ + cmd_putscript_storage_error(ctx); + failed = TRUE; + } else if (!all_written) { + /* client disconnected before it finished sending the + whole script. */ + failed = TRUE; + sieve_storage_save_cancel(&ctx->save_ctx); + const char *reason = t_strdup_printf( + "%s (While appending in PUTSCRIPT/CHECKSCRIPT)", + io_stream_get_disconnect_reason(client->input, + client->output)); + client_disconnect(client, reason); + } else if (sieve_storage_save_finish(ctx->save_ctx) < 0) { + failed = TRUE; + cmd_putscript_storage_error(ctx); + } else { + failed = client->input->closed; + } + } + + if (failed) { + cmd_putscript_finish(ctx); + return TRUE; + } + + /* finish */ + client->command_pending = FALSE; + managesieve_parser_reset(ctx->save_parser); + cmd->func = cmd_putscript_finish_parsing; + return cmd_putscript_finish_parsing(cmd); + } + + return FALSE; +} + +static bool +cmd_putscript_start(struct client_command_context *cmd, const char *scriptname) +{ + struct cmd_putscript_context *ctx; + struct client *client = cmd->client; + + ctx = p_new(cmd->pool, struct cmd_putscript_context, 1); + ctx->cmd = cmd; + ctx->client = client; + ctx->storage = client->storage; + ctx->scriptname = scriptname; + + io_remove(&client->io); + client->io = io_add(i_stream_get_fd(client->input), IO_READ, + client_input_putscript, client); + /* putscript is special because we're only waiting on client input, not + client output, so disable the standard output handler until we're + finished */ + o_stream_unset_flush_callback(client->output); + + ctx->save_parser = managesieve_parser_create( + client->input, client->set->managesieve_max_line_length); + + cmd->func = cmd_putscript_continue_parsing; + cmd->context = ctx; + return cmd_putscript_continue_parsing(cmd); + +} + +bool cmd_putscript(struct client_command_context *cmd) +{ + const char *scriptname; + + /* <scriptname> */ + if (!client_read_string_args(cmd, FALSE, 1, &scriptname)) + return FALSE; + + event_add_str(cmd->event, "script_name", scriptname); + + return cmd_putscript_start(cmd, scriptname); +} + +bool cmd_checkscript(struct client_command_context *cmd) +{ + return cmd_putscript_start(cmd, NULL); +} diff --git a/pigeonhole/src/managesieve/cmd-renamescript.c b/pigeonhole/src/managesieve/cmd-renamescript.c new file mode 100644 index 0000000..bc7a99d --- /dev/null +++ b/pigeonhole/src/managesieve/cmd-renamescript.c @@ -0,0 +1,54 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "managesieve-common.h" +#include "managesieve-commands.h" + +bool cmd_renamescript(struct client_command_context *cmd) +{ + struct client *client = cmd->client; + struct sieve_storage *storage = client->storage; + const char *scriptname, *newname; + struct sieve_script *script; + + /* <oldname> <newname> */ + if (!client_read_string_args(cmd, TRUE, 2, &scriptname, &newname)) + return FALSE; + + event_add_str(cmd->event, "old_script_name", scriptname); + event_add_str(cmd->event, "new_script_name", newname); + + script = sieve_storage_open_script(storage, scriptname, NULL); + if (script == NULL) { + client_command_storage_error( + cmd, "Failed to open script `%s' for rename to `%s'", + scriptname, newname); + return TRUE; + } + + if (sieve_script_rename(script, newname) < 0) { + client_command_storage_error( + cmd, "Failed to rename script `%s' to `%s'", + scriptname, newname); + } else { + client->renamed_count++; + + struct event_passthrough *e = + client_command_create_finish_event(cmd); + e_debug(e->event(), "Renamed script `%s' to `%s'", + scriptname, newname); + + client_send_ok(client, "Renamescript completed."); + } + + sieve_script_unref(&script); + return TRUE; +} + diff --git a/pigeonhole/src/managesieve/cmd-setactive.c b/pigeonhole/src/managesieve/cmd-setactive.c new file mode 100644 index 0000000..07844c5 --- /dev/null +++ b/pigeonhole/src/managesieve/cmd-setactive.c @@ -0,0 +1,165 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "managesieve-common.h" +#include "managesieve-commands.h" + +static void +cmd_setactive_activate(struct client_command_context *cmd, + const char *scriptname) +{ + struct client *client = cmd->client; + struct sieve_storage *storage = client->storage; + struct sieve_script *script; + string_t *errors = NULL; + const char *errormsg = NULL; + unsigned int warning_count = 0, error_count = 0; + bool success = TRUE; + int ret; + + event_add_str(cmd->event, "script_name", scriptname); + + script = sieve_storage_open_script(storage, scriptname, NULL); + if (script == NULL) { + client_command_storage_error( + cmd, "Failed to open script `%s' for activation", + scriptname); + return; + } + + if (sieve_script_is_active(script) <= 0) T_BEGIN { + /* Script is first being activated; compile it again without the + UPLOAD flag. */ + struct sieve_error_handler *ehandler; + enum sieve_compile_flags cpflags = + SIEVE_COMPILE_FLAG_NOGLOBAL | + SIEVE_COMPILE_FLAG_ACTIVATED; + struct sieve_binary *sbin; + enum sieve_error error; + + /* Prepare error handler */ + errors = str_new(default_pool, 1024); + ehandler = sieve_strbuf_ehandler_create( + client->svinst, errors, TRUE, + client->set->managesieve_max_compile_errors); + + /* Compile */ + sbin = sieve_compile_script(script, ehandler, cpflags, &error); + if (sbin == NULL) { + if (error != SIEVE_ERROR_NOT_VALID) { + errormsg = sieve_script_get_last_error( + script, &error); + if (error == SIEVE_ERROR_NONE) + errormsg = NULL; + } + success = FALSE; + } else { + sieve_close(&sbin); + } + + warning_count = sieve_get_warnings(ehandler); + error_count = sieve_get_errors(ehandler); + sieve_error_handler_unref(&ehandler); + } T_END; + + /* Activate only when script is valid (or already active) */ + if (success) { + /* Refresh activation no matter what; this can also + resolve some erroneous situations. */ + ret = sieve_script_activate(script, (time_t)-1); + if (ret < 0) { + client_command_storage_error( + cmd, "Failed to activate script `%s'", + scriptname); + } else { + struct event_passthrough *e = + client_command_create_finish_event(cmd)-> + add_int("compile_warnings", warning_count); + e_debug(e->event(), "Activated script `%s' " + " (%u warnings%s)", + scriptname, warning_count, + (ret == 0 ? ", redundant" : "")); + + if (warning_count > 0) { + client_send_okresp( + client, "WARNINGS", + str_c(errors)); + } else { + client_send_ok(client, + (ret > 0 ? + "Setactive completed." : + "Script is already active.")); + } + } + } else if (errormsg == NULL) { + struct event_passthrough *e = + client_command_create_finish_event(cmd)-> + add_str("error", "Compilation failed")-> + add_int("compile_errors", error_count)-> + add_int("compile_warnings", warning_count); + e_debug(e->event(), "Failed to activate script `%s': " + "Compilation failed (%u errors, %u warnings)", + scriptname, error_count, warning_count); + + client_send_no(client, str_c(errors)); + } else { + struct event_passthrough *e = + client_command_create_finish_event(cmd)-> + add_str("error", errormsg); + e_debug(e->event(), "Failed to activate script `%s': %s", + scriptname, errormsg); + + client_send_no(client, errormsg); + } + + if (errors != NULL) + str_free(&errors); + sieve_script_unref(&script); +} + +static void +cmd_setactive_deactivate(struct client_command_context *cmd) +{ + struct client *client = cmd->client; + struct sieve_storage *storage = client->storage; + int ret; + + ret = sieve_storage_deactivate(storage, (time_t)-1); + if (ret < 0) { + client_command_storage_error( + cmd, "Failed to deactivate script"); + return; + } + + struct event_passthrough *e = + client_command_create_finish_event(cmd); + e_debug(e->event(), "Deactivated script"); + + client_send_ok(client, (ret > 0 ? + "Active script is now deactivated." : + "No scripts currently active.")); +} + +bool cmd_setactive(struct client_command_context *cmd) +{ + const char *scriptname; + + /* <scriptname> */ + if (!client_read_string_args(cmd, TRUE, 1, &scriptname)) + return FALSE; + + /* Activate, or deactivate */ + if (*scriptname != '\0') + cmd_setactive_activate(cmd, scriptname); + else + cmd_setactive_deactivate(cmd); + + return TRUE; +} diff --git a/pigeonhole/src/managesieve/main.c b/pigeonhole/src/managesieve/main.c new file mode 100644 index 0000000..321ebe3 --- /dev/null +++ b/pigeonhole/src/managesieve/main.c @@ -0,0 +1,401 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "buffer.h" +#include "ioloop.h" +#include "istream.h" +#include "istream-concat.h" +#include "ostream.h" +#include "path-util.h" +#include "str.h" +#include "base64.h" +#include "process-title.h" +#include "restrict-access.h" +#include "settings-parser.h" +#include "master-interface.h" +#include "master-service.h" +#include "master-login.h" +#include "mail-user.h" +#include "mail-storage-service.h" + +#include "managesieve-common.h" +#include "managesieve-commands.h" +#include "managesieve-capabilities.h" + +#include <stdio.h> +#include <unistd.h> + +#define IS_STANDALONE() \ + (getenv(MASTER_IS_PARENT_ENV) == NULL) + +#define MANAGESIEVE_DIE_IDLE_SECS 10 + +static bool verbose_proctitle = FALSE; +static struct mail_storage_service_ctx *storage_service; +static struct master_login *master_login = NULL; + +void (*hook_client_created)(struct client **client) = NULL; + +struct event_category event_category_managesieve = { + .name = "managesieve", +}; + +void managesieve_refresh_proctitle(void) +{ +#define MANAGESIEVE_PROCTITLE_PREFERRED_LEN 80 + struct client *client; + string_t *title = t_str_new(128); + + if (!verbose_proctitle) + return; + + str_append_c(title, '['); + switch (managesieve_client_count) { + case 0: + str_append(title, "idling"); + break; + case 1: + client = managesieve_clients; + str_append(title, client->user->username); + if (client->user->conn.remote_ip != NULL) { + str_append_c(title, ' '); + str_append(title, + net_ip2addr(client->user->conn.remote_ip)); + } + + if (client->cmd.name != NULL && + str_len(title) <= MANAGESIEVE_PROCTITLE_PREFERRED_LEN) { + str_append_c(title, ' '); + str_append(title, client->cmd.name); + } + break; + default: + str_printfa(title, "%u connections", managesieve_client_count); + break; + } + str_append_c(title, ']'); + process_title_set(str_c(title)); +} + +static void client_kill_idle(struct client *client) +{ + mail_storage_service_io_activate_user(client->service_user); + client_send_bye(client, "Server shutting down."); + client_destroy(client, "Server shutting down."); +} + +static void managesieve_die(void) +{ + struct client *client, *next; + time_t last_io, now = time(NULL); + time_t stop_timestamp = now - MANAGESIEVE_DIE_IDLE_SECS; + unsigned int stop_msecs; + + for (client = managesieve_clients; client != NULL; client = next) { + next = client->next; + + last_io = I_MAX(client->last_input, client->last_output); + if (last_io <= stop_timestamp) + client_kill_idle(client); + else { + timeout_remove(&client->to_idle); + stop_msecs = (last_io - stop_timestamp) * 1000; + client->to_idle = timeout_add(stop_msecs, + client_kill_idle, client); + } + } +} + +static void client_add_istream_prefix(struct client *client, + const buffer_t *input) +{ + struct istream *inputs[] = { + i_stream_create_copy_from_data(input->data, input->used), + client->input, + NULL + }; + client->input = i_stream_create_concat(inputs); + i_stream_copy_fd(client->input, inputs[1]); + i_stream_unref(&inputs[0]); + i_stream_unref(&inputs[1]); + + i_stream_set_input_pending(client->input, TRUE); +} + +static void client_logged_in(struct client *client) +{ + struct ostream *output; + + output = client->output; + o_stream_ref(output); + o_stream_cork(output); + if (!IS_STANDALONE()) + client_send_ok(client, "Logged in."); + (void)client_input(client); + o_stream_uncork(output); + o_stream_unref(&output); +} + +static int +client_create_from_input(const struct mail_storage_service_input *input, + int fd_in, int fd_out, const buffer_t *input_buf, + const char **error_r) +{ + struct mail_storage_service_input service_input; + struct mail_storage_service_user *user; + struct mail_user *mail_user; + struct client *client; + struct managesieve_settings *set; + struct event *event; + const char *error; + + event = event_create(NULL); + event_add_category(event, &event_category_managesieve); + event_add_fields(event, (const struct event_add_field []){ + { .key = "user", .value = input->username }, + { .key = "session", .value = input->session_id }, + { .key = NULL } + }); + + service_input = *input; + service_input.event_parent = event; + if (mail_storage_service_lookup_next(storage_service, &service_input, + &user, &mail_user, error_r) <= 0) { + event_unref(&event); + return -1; + } + restrict_access_allow_coredumps(TRUE); + + set = mail_storage_service_user_get_set(user)[1]; + if (set->verbose_proctitle) + verbose_proctitle = TRUE; + + if (settings_var_expand(&managesieve_setting_parser_info, set, + mail_user->pool, + mail_user_var_expand_table(mail_user), + &error) <= 0) { + i_error("Failed to expand settings: %s", error); + mail_storage_service_user_unref(&user); + mail_user_unref(&mail_user); + event_unref(&event); + return -1; + } + + client = client_create(fd_in, fd_out, input->session_id, + event, mail_user, user, set); + if (input_buf != NULL && input_buf->used > 0) + client_add_istream_prefix(client, input_buf); + client_create_finish(client); + T_BEGIN { + client_logged_in(client); + } T_END; + event_unref(&event); + return 0; +} + +static void main_stdio_run(const char *username) +{ + struct mail_storage_service_input input; + const char *value, *error, *input_base64; + buffer_t *input_buf; + + i_zero(&input); + input.module = "managesieve"; + input.service = "sieve"; + input.username = username != NULL ? username : getenv("USER"); + if (input.username == NULL && IS_STANDALONE()) + input.username = getlogin(); + if (input.username == NULL) + i_fatal("USER environment missing"); + if ((value = getenv("IP")) != NULL) + net_addr2ip(value, &input.remote_ip); + if ((value = getenv("LOCAL_IP")) != NULL) + net_addr2ip(value, &input.local_ip); + + input_base64 = getenv("CLIENT_INPUT"); + input_buf = (input_base64 == NULL ? + NULL : t_base64_decode_str(input_base64)); + + if (client_create_from_input(&input, STDIN_FILENO, STDOUT_FILENO, + input_buf, &error) < 0) + i_fatal("%s", error); +} + +static void +login_client_connected(const struct master_login_client *client, + const char *username, const char *const *extra_fields) +{ +#define MSG_BYE_INTERNAL_ERROR "BYE \""CRITICAL_MSG"\"\r\n" + struct mail_storage_service_input input; + enum mail_auth_request_flags flags = client->auth_req.flags; + const char *error; + buffer_t input_buf; + + i_zero(&input); + input.module = "managesieve"; + input.service = "sieve"; + input.local_ip = client->auth_req.local_ip; + input.remote_ip = client->auth_req.remote_ip; + input.local_port = client->auth_req.local_port; + input.remote_port = client->auth_req.remote_port; + input.username = username; + input.userdb_fields = extra_fields; + input.session_id = client->session_id; + if ((flags & MAIL_AUTH_REQUEST_FLAG_CONN_SECURED) != 0) + input.conn_secured = TRUE; + if ((flags & MAIL_AUTH_REQUEST_FLAG_CONN_SSL_SECURED) != 0) + input.conn_ssl_secured = TRUE; + + buffer_create_from_const_data(&input_buf, client->data, + client->auth_req.data_size); + if (client_create_from_input(&input, client->fd, client->fd, + &input_buf, &error) < 0) { + int fd = client->fd; + + if (write(fd, MSG_BYE_INTERNAL_ERROR, + strlen(MSG_BYE_INTERNAL_ERROR)) < 0) { + if (errno != EAGAIN && errno != EPIPE) + i_error("write(client) failed: %m"); + } + i_error("%s", error); + i_close_fd(&fd); + master_service_client_connection_destroyed(master_service); + } +} + +static void +login_client_failed(const struct master_login_client *client, + const char *errormsg) +{ + const char *msg; + + msg = t_strdup_printf("NO \"%s\"\r\n", errormsg); + if (write(client->fd, msg, strlen(msg)) < 0) { + /* ignored */ + } +} + +static void client_connected(struct master_service_connection *conn) +{ + /* when running standalone, we shouldn't even get here */ + i_assert(master_login != NULL); + + master_service_client_connection_accept(conn); + master_login_add(master_login, conn->fd); +} + +int main(int argc, char *argv[]) +{ + static const struct setting_parser_info *set_roots[] = { + &managesieve_setting_parser_info, + NULL + }; + struct master_login_settings login_set; + enum master_service_flags service_flags = 0; + enum mail_storage_service_flags storage_service_flags = 0; + const char *username = NULL, *error = NULL; + int c; + + i_zero(&login_set); + login_set.postlogin_timeout_secs = MASTER_POSTLOGIN_TIMEOUT_DEFAULT; + + if (IS_STANDALONE() && getuid() == 0 && + net_getpeername(1, NULL, NULL) == 0) { + printf("NO \"managesieve binary must not be started from " + "inetd, use managesieve-login instead.\"\n"); + return 1; + } + + if (IS_STANDALONE() || getenv("DUMP_CAPABILITY") != NULL) { + service_flags |= MASTER_SERVICE_FLAG_STANDALONE | + MASTER_SERVICE_FLAG_STD_CLIENT; + } else { + service_flags |= MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN; + } + if (getenv("DUMP_CAPABILITY") != NULL) { + service_flags |= MASTER_SERVICE_FLAG_DONT_SEND_STATS | + MASTER_SERVICE_FLAG_DISABLE_SSL_SET; + } + + master_service = master_service_init("managesieve", service_flags, + &argc, &argv, "t:u:"); + while ((c = master_getopt(master_service)) > 0) { + switch (c) { + case 't': + if (str_to_uint(optarg, + &login_set.postlogin_timeout_secs) < 0 || + login_set.postlogin_timeout_secs == 0) + i_fatal("Invalid -t parameter: %s", optarg); + break; + case 'u': + storage_service_flags |= + MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP; + username = optarg; + break; + default: + return FATAL_DEFAULT; + } + } + + master_service_set_die_callback(master_service, managesieve_die); + + /* plugins may want to add commands, so this needs to be called early */ + commands_init(); + + /* Dump capabilities if requested */ + if (getenv("DUMP_CAPABILITY") != NULL) { + i_set_debug_file("/dev/null"); + managesieve_capabilities_dump(); + commands_deinit(); + master_service_deinit(&master_service); + exit(0); + } + + if (t_abspath("auth-master", &login_set.auth_socket_path, &error) < 0) + i_fatal("t_abspath(%s) failed: %s", "auth-master", error); + + if (argv[optind] != NULL && + t_abspath(argv[optind], &login_set.postlogin_socket_path, + &error) < 0) { + i_fatal("t_abspath(%s) failed: %s", argv[optind], error); + } + + login_set.callback = login_client_connected; + login_set.failure_callback = login_client_failed; + + if (!IS_STANDALONE()) + master_login = master_login_init(master_service, &login_set); + + storage_service = + mail_storage_service_init(master_service, + set_roots, storage_service_flags); + master_service_init_finish(master_service); + /* NOTE: login_set.*_socket_path are now invalid due to data stack + having been freed */ + + /* fake that we're running, so we know if client was destroyed + while handling its initial input */ + io_loop_set_running(current_ioloop); + + if (IS_STANDALONE()) { + T_BEGIN { + main_stdio_run(username); + } T_END; + } else { + io_loop_set_running(current_ioloop); + } + + if (io_loop_is_running(current_ioloop)) + master_service_run(master_service, client_connected); + clients_destroy_all(); + + if (master_login != NULL) + master_login_deinit(&master_login); + mail_storage_service_deinit(&storage_service); + + commands_deinit(); + + master_service_deinit(&master_service); + return 0; +} diff --git a/pigeonhole/src/managesieve/managesieve-capabilities.c b/pigeonhole/src/managesieve/managesieve-capabilities.c new file mode 100644 index 0000000..c72558f --- /dev/null +++ b/pigeonhole/src/managesieve/managesieve-capabilities.c @@ -0,0 +1,136 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "hostpid.h" +#include "var-expand.h" +#include "settings-parser.h" +#include "master-service.h" +#include "master-service-settings.h" +#include "master-service-settings-cache.h" + +#include "sieve.h" + +#include "managesieve-capabilities.h" + +#include <stddef.h> +#include <unistd.h> + +/* + * Global plugin settings + */ + +struct plugin_settings { + ARRAY(const char *) plugin_envs; +}; + +static const struct setting_parser_info **plugin_set_roots; + +static const struct setting_define plugin_setting_defines[] = { + { .type = SET_STRLIST, .key = "plugin", + .offset = offsetof(struct plugin_settings, plugin_envs) }, + + SETTING_DEFINE_LIST_END +}; + +static const struct setting_parser_info plugin_setting_parser_info = { + .module_name = "managesieve", + .defines = plugin_setting_defines, + + .type_offset = (size_t)-1, + .struct_size = sizeof(struct plugin_settings), + + .parent_offset = (size_t)-1, +}; + +static const struct setting_parser_info *default_plugin_set_roots[] = { + &plugin_setting_parser_info, + NULL +}; + +static const struct setting_parser_info **plugin_set_roots = + default_plugin_set_roots; + +static struct plugin_settings *plugin_settings_read(void) +{ + const char *error; + + if (master_service_settings_read_simple( + master_service, plugin_set_roots, &error) < 0) + i_fatal("Error reading configuration: %s", error); + + return (struct plugin_settings *) + master_service_settings_get_others(master_service)[0]; +} + +static const char * +plugin_settings_get(const struct plugin_settings *set, const char *identifier) +{ + const char *const *envs; + unsigned int i, count; + + if ( !array_is_created(&set->plugin_envs) ) + return NULL; + + envs = array_get(&set->plugin_envs, &count); + for ( i = 0; i < count; i += 2 ) { + if ( strcmp(envs[i], identifier) == 0 ) + return envs[i+1]; + } + return NULL; +} + +/* + * Sieve environment + */ + +static const char *sieve_get_setting(void *context, const char *identifier) +{ + const struct plugin_settings *set = context; + + return plugin_settings_get(set, identifier); +} + +static const struct sieve_callbacks sieve_callbacks = { + NULL, + sieve_get_setting +}; + +/* + * Capability dumping + */ + +void managesieve_capabilities_dump(void) +{ + const struct plugin_settings *global_plugin_settings; + struct sieve_environment svenv; + struct sieve_instance *svinst; + const char *notify_cap; + + /* Read plugin settings */ + + global_plugin_settings = plugin_settings_read(); + + /* Initialize Sieve engine */ + + memset((void*)&svenv, 0, sizeof(svenv)); + svenv.home_dir = "/tmp"; + + svinst = sieve_init(&svenv, &sieve_callbacks, + (void *) global_plugin_settings, FALSE); + + /* Dump capabilities */ + + notify_cap = sieve_get_capabilities(svinst, "notify"); + + if (notify_cap == NULL) + printf("SIEVE: %s\n", sieve_get_capabilities(svinst, NULL)); + else { + printf("SIEVE: %s, NOTIFY: %s\n", + sieve_get_capabilities(svinst, NULL), + sieve_get_capabilities(svinst, "notify")); + } + + sieve_deinit(&svinst); +} diff --git a/pigeonhole/src/managesieve/managesieve-capabilities.h b/pigeonhole/src/managesieve/managesieve-capabilities.h new file mode 100644 index 0000000..b7503a9 --- /dev/null +++ b/pigeonhole/src/managesieve/managesieve-capabilities.h @@ -0,0 +1,6 @@ +#ifndef MANAGESIEVE_CAPABILITIES_H +#define MANAGESIEVE_CAPABILITIES_H + +void managesieve_capabilities_dump(void); + +#endif diff --git a/pigeonhole/src/managesieve/managesieve-client.c b/pigeonhole/src/managesieve/managesieve-client.c new file mode 100644 index 0000000..bacf460 --- /dev/null +++ b/pigeonhole/src/managesieve/managesieve-client.c @@ -0,0 +1,792 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "ioloop.h" +#include "llist.h" +#include "str.h" +#include "hostpid.h" +#include "net.h" +#include "istream.h" +#include "ostream.h" +#include "iostream.h" +#include "iostream-rawlog.h" +#include "var-expand.h" +#include "time-util.h" +#include "master-service.h" +#include "mail-storage-service.h" +#include "mail-namespace.h" + +#include "sieve.h" +#include "sieve-storage.h" + +#include "managesieve-quote.h" +#include "managesieve-common.h" +#include "managesieve-commands.h" +#include "managesieve-client.h" + +#include <unistd.h> + +extern struct mail_storage_callbacks mail_storage_callbacks; +struct managesieve_module_register managesieve_module_register = { 0 }; + +struct client *managesieve_clients = NULL; +unsigned int managesieve_client_count = 0; + +static const char * +managesieve_sieve_get_setting(void *context, const char *identifier) +{ + struct mail_user *mail_user = (struct mail_user *) context; + + if (mail_user == NULL) + return NULL; + + return mail_user_plugin_getenv(mail_user, identifier); +} + +static const struct sieve_callbacks managesieve_sieve_callbacks = { + NULL, + managesieve_sieve_get_setting +}; + +static void client_idle_timeout(struct client *client) +{ + if (client->cmd.func != NULL) { + client_destroy(client, + "Disconnected for inactivity in reading our output"); + } else { + client_send_bye(client, "Disconnected for inactivity"); + client_destroy(client, "Disconnected for inactivity"); + } +} + +static struct sieve_storage * +client_get_storage(struct sieve_instance *svinst, struct mail_user *user, + int fd_out) +{ + struct sieve_storage *storage; + enum sieve_error error; + const char *errormsg, *byemsg; + + /* Open personal script storage */ + + storage = sieve_storage_create_main(svinst, user, + SIEVE_STORAGE_FLAG_READWRITE, + &error); + if (storage == NULL) { + switch (error) { + case SIEVE_ERROR_NOT_POSSIBLE: + byemsg = "BYE \"Sieve processing is disabled for this user.\"\r\n"; + errormsg = "Failed to open Sieve storage: " + "Sieve is disabled for this user"; + break; + case SIEVE_ERROR_NOT_FOUND: + byemsg = "BYE \"This user cannot manage personal Sieve scripts.\"\r\n"; + errormsg = "Failed to open Sieve storage: " + "Personal script storage disabled or not found."; + break; + default: + byemsg = t_strflocaltime( + "BYE \""CRITICAL_MSG_STAMP"\"\r\n", ioloop_time); + errormsg = "Failed to open Sieve storage."; + } + + if (write(fd_out, byemsg, strlen(byemsg)) < 0) { + if (errno != EAGAIN && errno != EPIPE) + i_error("write(client) failed: %m"); + } + i_fatal("%s", errormsg); + } + + return storage; +} + +struct client * +client_create(int fd_in, int fd_out, const char *session_id, + struct event *event, struct mail_user *user, + struct mail_storage_service_user *service_user, + const struct managesieve_settings *set) +{ + struct client *client; + const char *ident; + struct sieve_environment svenv; + struct sieve_instance *svinst; + struct sieve_storage *storage; + pool_t pool; + + /* Initialize Sieve */ + + memset((void*)&svenv, 0, sizeof(svenv)); + svenv.username = user->username; + (void)mail_user_get_home(user, &svenv.home_dir); + svenv.base_dir = user->set->base_dir; + svenv.event_parent = event; + svenv.flags = SIEVE_FLAG_HOME_RELATIVE; + + svinst = sieve_init(&svenv, &managesieve_sieve_callbacks, + (void *) user, set->mail_debug); + + /* Get Sieve storage */ + + storage = client_get_storage(svinst, user, fd_out); + + /* always use nonblocking I/O */ + net_set_nonblock(fd_in, TRUE); + net_set_nonblock(fd_out, TRUE); + + pool = pool_alloconly_create("managesieve client", 1024); + client = p_new(pool, struct client, 1); + client->pool = pool; + client->event = event; + event_ref(client->event); + client->set = set; + client->service_user = service_user; + client->session_id = p_strdup(pool, session_id); + client->fd_in = fd_in; + client->fd_out = fd_out; + client->input = i_stream_create_fd( + fd_in, set->managesieve_max_line_length); + client->output = o_stream_create_fd(fd_out, (size_t)-1); + + o_stream_set_no_error_handling(client->output, TRUE); + i_stream_set_name(client->input, "<managesieve client>"); + o_stream_set_name(client->output, "<managesieve client>"); + + o_stream_set_flush_callback(client->output, client_output, client); + + client->last_input = ioloop_time; + client->to_idle = timeout_add(CLIENT_IDLE_TIMEOUT_MSECS, + client_idle_timeout, client); + + client->cmd.pool = pool_alloconly_create( + MEMPOOL_GROWING"client command", 1024*12); + client->cmd.client = client; + client->cmd.event = event_create(client->event); + client->user = user; + + client->svinst = svinst; + client->storage = storage; + + ident = mail_user_get_anvil_userip_ident(client->user); + if (ident != NULL) { + master_service_anvil_send( + master_service, t_strconcat("CONNECT\t", my_pid, + "\tsieve/", ident, + "\n", NULL)); + client->anvil_sent = TRUE; + } + + managesieve_client_count++; + DLLIST_PREPEND(&managesieve_clients, client); + if (hook_client_created != NULL) + hook_client_created(&client); + + managesieve_refresh_proctitle(); + return client; +} + +void client_create_finish(struct client *client) +{ + if (client->set->rawlog_dir[0] != '\0') { + (void)iostream_rawlog_create(client->set->rawlog_dir, + &client->input, &client->output); + } + client->parser = managesieve_parser_create( + client->input, client->set->managesieve_max_line_length); + client->io = io_add_istream(client->input, client_input, client); +} + +static const char *client_stats(struct client *client) +{ + const struct var_expand_table logout_tab[] = { + { 'i', dec2str(i_stream_get_absolute_offset(client->input)), + "input" }, + { 'o', dec2str(client->output->offset), "output" }, + { '\0', dec2str(client->put_bytes), "put_bytes" }, + { '\0', dec2str(client->put_count), "put_count" }, + { '\0', dec2str(client->get_bytes), "get_bytes" }, + { '\0', dec2str(client->get_count), "get_count" }, + { '\0', dec2str(client->check_bytes), "check_bytes" }, + { '\0', dec2str(client->check_count), "check_count" }, + { '\0', dec2str(client->deleted_count), "deleted_count" }, + { '\0', dec2str(client->renamed_count), "renamed_count" }, + { '\0', client->session_id, "session" }, + { '\0', NULL, NULL } + }; + const struct var_expand_table *user_tab = + mail_user_var_expand_table(client->user); + const struct var_expand_table *tab = + t_var_expand_merge_tables(logout_tab, user_tab); + string_t *str; + const char *error; + + str = t_str_new(128); + if (var_expand_with_funcs(str, client->set->managesieve_logout_format, + tab, mail_user_var_expand_func_table, + client->user, &error) < 0) { + i_error("Failed to expand managesieve_logout_format=%s: %s", + client->set->managesieve_logout_format, error); + } + return str_c(str); +} + +void client_destroy(struct client *client, const char *reason) +{ + bool ret; + + i_assert(!client->handling_input); + i_assert(!client->destroyed); + client->destroyed = TRUE; + + client_disconnect(client, reason); + + if (client->command_pending) { + /* try to deinitialize the command */ + i_assert(client->cmd.func != NULL); + + i_stream_close(client->input); + o_stream_close(client->output); + + client->input_pending = FALSE; + + ret = client->cmd.func(&client->cmd); + i_assert(ret); + } + + if (client->anvil_sent) { + master_service_anvil_send( + master_service, t_strconcat( + "DISCONNECT\t", my_pid, "\tsieve/", + mail_user_get_anvil_userip_ident(client->user), + "\n", NULL)); + } + + managesieve_parser_destroy(&client->parser); + io_remove(&client->io); + timeout_remove(&client->to_idle_output); + timeout_remove(&client->to_idle); + + /* i/ostreams are already closed at this stage, so fd can be closed */ + net_disconnect(client->fd_in); + if (client->fd_in != client->fd_out) + net_disconnect(client->fd_out); + + /* Free the user after client is already disconnected. It may start + some background work like autoexpunging. */ + mail_user_unref(&client->user); + + /* free the i/ostreams after mail_user_unref(), which could trigger + mail_storage_callbacks notifications that write to the ostream. */ + i_stream_destroy(&client->input); + o_stream_destroy(&client->output); + + sieve_storage_unref(&client->storage); + sieve_deinit(&client->svinst); + + event_unref(&client->cmd.event); + pool_unref(&client->cmd.pool); + mail_storage_service_user_unref(&client->service_user); + + managesieve_client_count--; + DLLIST_REMOVE(&managesieve_clients, client); + event_unref(&client->event); + pool_unref(&client->pool); + + master_service_client_connection_destroyed(master_service); + managesieve_refresh_proctitle(); +} + +static void client_destroy_timeout(struct client *client) +{ + client_destroy(client, NULL); +} + +void client_disconnect(struct client *client, const char *reason) +{ + if (client->disconnected) + return; + + if (reason == NULL) { + reason = io_stream_get_disconnect_reason(client->input, + client->output); + i_info("%s %s", reason, client_stats(client)); + } else { + i_info("Disconnected: %s %s", reason, client_stats(client)); + } + client->disconnected = TRUE; + o_stream_flush(client->output); + o_stream_uncork(client->output); + + i_stream_close(client->input); + o_stream_close(client->output); + + timeout_remove(&client->to_idle); + if (!client->destroyed) + client->to_idle = timeout_add(0, client_destroy_timeout, client); +} + +void client_disconnect_with_error(struct client *client, const char *msg) +{ + client_send_bye(client, msg); + client_disconnect(client, msg); +} + +int client_send_line(struct client *client, const char *data) +{ + struct const_iovec iov[2]; + + if (client->output->closed) + return -1; + + iov[0].iov_base = data; + iov[0].iov_len = strlen(data); + iov[1].iov_base = "\r\n"; + iov[1].iov_len = 2; + + if (o_stream_sendv(client->output, iov, 2) < 0) + return -1; + client->last_output = ioloop_time; + + if (o_stream_get_buffer_used_size(client->output) >= + CLIENT_OUTPUT_OPTIMAL_SIZE) { + /* buffer full, try flushing */ + return o_stream_flush(client->output); + } + return 1; +} + +void client_send_response(struct client *client, const char *oknobye, + const char *resp_code, const char *msg) +{ + string_t *str; + + str = t_str_new(128); + str_append(str, oknobye); + + if (resp_code != NULL) { + str_append(str, " ("); + str_append(str, resp_code); + str_append_c(str, ')'); + } + + if (msg != NULL) { + str_append_c(str, ' '); + managesieve_quote_append_string(str, msg, TRUE); + } + + client_send_line(client, str_c(str)); +} + +struct event_passthrough * +client_command_create_finish_event(struct client_command_context *cmd) +{ + struct event_passthrough *e = + event_create_passthrough(cmd->event)-> + set_name("managesieve_command_finished"); + return e; +} + +void client_send_command_error(struct client_command_context *cmd, + const char *msg) +{ + struct client *client = cmd->client; + const char *error, *cmd_name; + bool fatal; + + if (msg == NULL) { + msg = managesieve_parser_get_error(client->parser, &fatal); + if (fatal) { + client_disconnect_with_error(client, msg); + return; + } + } + + if (cmd->name == NULL) { + error = t_strconcat("Error in MANAGESIEVE command: ", + msg, NULL); + } else { + cmd_name = t_str_ucase(cmd->name); + error = t_strconcat("Error in MANAGESIEVE command ", + cmd_name, ": ", msg, NULL); + } + + client_send_no(client, error); + + if (++client->bad_counter >= CLIENT_MAX_BAD_COMMANDS) { + client_disconnect_with_error( + client, "Too many invalid MANAGESIEVE commands."); + } + + /* client_read_args() failures rely on this being set, so that the + command processing is stopped even while command function returns + FALSE. */ + cmd->param_error = TRUE; +} + +#undef client_command_storage_error +void client_command_storage_error(struct client_command_context *cmd, + const char *source_filename, + unsigned int source_linenum, + const char *log_prefix, ...) +{ + struct event_log_params params = { + .log_type = LOG_TYPE_INFO, + .source_filename = source_filename, + .source_linenum = source_linenum, + }; + struct client *client = cmd->client; + struct sieve_storage *storage = client->storage; + enum sieve_error error_code; + const char *error; + va_list args; + + error = sieve_storage_get_last_error(storage, &error_code); + + switch (error_code) { + case SIEVE_ERROR_TEMP_FAILURE: + client_send_noresp(client, "TRYLATER", error); + break; + case SIEVE_ERROR_NO_QUOTA: + client_send_noresp(client, "QUOTA", error); + break; + case SIEVE_ERROR_NOT_FOUND: + client_send_noresp(client, "NONEXISTENT", error); + break; + case SIEVE_ERROR_ACTIVE: + client_send_noresp(client, "ACTIVE", error); + break; + case SIEVE_ERROR_EXISTS: + client_send_noresp(client, "ALREADYEXISTS", error); + break; + case SIEVE_ERROR_NOT_POSSIBLE: + default: + client_send_no(client, error); + break; + } + + struct event_passthrough *e = + client_command_create_finish_event(cmd)-> + add_str("error", error); + + va_start(args, log_prefix); + event_log(e->event(), ¶ms, "%s: %s", + t_strdup_vprintf(log_prefix, args), error); + va_end(args); +} + +bool client_read_args(struct client_command_context *cmd, unsigned int count, + unsigned int flags, bool no_more, + const struct managesieve_arg **args_r) +{ + const struct managesieve_arg *dummy_args_r = NULL; + string_t *str; + int ret; + + if (args_r == NULL) + args_r = &dummy_args_r; + + i_assert(count <= INT_MAX); + + ret = managesieve_parser_read_args(cmd->client->parser, + (no_more ? 0 : count), + flags, args_r); + if (ret >= 0) { + if (count > 0 || no_more) { + if (ret < (int)count) { + client_send_command_error( + cmd, "Missing arguments."); + return FALSE; + } else if (no_more && ret > (int)count) { + client_send_command_error( + cmd, "Too many arguments."); + return FALSE; + } + } + + str = t_str_new(256); + managesieve_write_args(str, *args_r); + cmd->args = p_strdup(cmd->pool, str_c(str)); + + event_add_str(cmd->event, "cmd_args", cmd->args); + + /* all parameters read successfully */ + return TRUE; + } else if (ret == -2) { + /* need more data */ + if (cmd->client->input->closed) { + /* disconnected */ + cmd->param_error = TRUE; + } + return FALSE; + } else { + /* error */ + client_send_command_error(cmd, NULL); + return FALSE; + } +} + +bool client_read_string_args(struct client_command_context *cmd, + bool no_more, unsigned int count, ...) +{ + const struct managesieve_arg *msieve_args; + va_list va; + const char *str; + unsigned int i; + bool result = TRUE; + + if (!client_read_args(cmd, count, 0, no_more, &msieve_args)) + return FALSE; + + va_start(va, count); + for (i = 0; i < count; i++) { + const char **ret = va_arg(va, const char **); + + if (MANAGESIEVE_ARG_IS_EOL(&msieve_args[i])) { + client_send_command_error(cmd, "Missing arguments."); + result = FALSE; + break; + } + + if (!managesieve_arg_get_string(&msieve_args[i], &str)) { + client_send_command_error(cmd, "Invalid arguments."); + result = FALSE; + break; + } + + if (ret != NULL) + *ret = str; + } + va_end(va); + + return result; +} + +void _client_reset_command(struct client *client) +{ + pool_t pool; + size_t size; + + /* reset input idle time because command output might have taken a long + time and we don't want to disconnect client immediately then */ + client->last_input = ioloop_time; + timeout_reset(client->to_idle); + + client->command_pending = FALSE; + if (client->io == NULL && !client->disconnected) { + i_assert(i_stream_get_fd(client->input) >= 0); + client->io = io_add(i_stream_get_fd(client->input), + IO_READ, client_input, client); + } + o_stream_set_flush_callback(client->output, client_output, client); + + event_unref(&client->cmd.event); + + pool = client->cmd.pool; + i_zero(&client->cmd); + + p_clear(pool); + client->cmd.pool = pool; + client->cmd.client = client; + + client->cmd.event = event_create(client->event); + + managesieve_parser_reset(client->parser); + + /* if there's unread data in buffer, remember that there's input pending + and we should get around to calling client_input() soon. This is + mostly for APPEND/IDLE. */ + (void)i_stream_get_data(client->input, &size); + if (size > 0 && !client->destroyed) + client->input_pending = TRUE; +} + +/* Skip incoming data until newline is found, + returns TRUE if newline was found. */ +static bool client_skip_line(struct client *client) +{ + const unsigned char *data; + size_t i, data_size; + + data = i_stream_get_data(client->input, &data_size); + + for (i = 0; i < data_size; i++) { + if (data[i] == '\n') { + client->input_skip_line = FALSE; + i++; + break; + } + } + + i_stream_skip(client->input, i); + return !client->input_skip_line; +} + +static bool client_handle_input(struct client_command_context *cmd) +{ + struct client *client = cmd->client; + + if (cmd->func != NULL) { + bool finished; + + event_push_global(cmd->event); + finished = cmd->func(cmd); + event_pop_global(cmd->event); + + /* command is being executed - continue it */ + if (finished || cmd->param_error) { + /* command execution was finished */ + if (!cmd->param_error) + client->bad_counter = 0; + _client_reset_command(client); + return TRUE; + } + + /* unfinished */ + if (client->command_pending) + o_stream_set_flush_pending(client->output, TRUE); + return FALSE; + } + + if (client->input_skip_line) { + /* we're just waiting for new line.. */ + if (!client_skip_line(client)) + return FALSE; + + /* got the newline */ + _client_reset_command(client); + + /* pass through to parse next command */ + } + + if (cmd->name == NULL) { + cmd->name = managesieve_parser_read_word(client->parser); + if (cmd->name == NULL) + return FALSE; /* need more data */ + cmd->name = p_strdup(cmd->pool, cmd->name); + managesieve_refresh_proctitle(); + } + + if (cmd->name[0] == '\0') { + /* command not given - cmd_func is already NULL. */ + } else { + /* find the command function */ + struct command *command = command_find(cmd->name); + + if (command != NULL) + cmd->func = command->func; + } + + client->input_skip_line = TRUE; + if (cmd->func == NULL) { + /* unknown command */ + client_send_command_error(cmd, "Unknown command."); + _client_reset_command(client); + } else { + i_assert(!client->disconnected); + + event_add_str(cmd->event, "cmd_name", t_str_ucase(cmd->name)); + client_handle_input(cmd); + } + + return TRUE; +} + +void client_input(struct client *client) +{ + struct client_command_context *cmd = &client->cmd; + bool ret; + + if (client->command_pending) { + /* already processing one command. wait. */ + io_remove(&client->io); + return; + } + + client->input_pending = FALSE; + client->last_input = ioloop_time; + timeout_reset(client->to_idle); + + switch (i_stream_read(client->input)) { + case -1: + /* disconnected */ + client_destroy(client, NULL); + return; + case -2: + /* parameter word is longer than max. input buffer size. + this is most likely an error, so skip the new data + until newline is found. */ + client->input_skip_line = TRUE; + + client_send_command_error(cmd, "Too long argument."); + _client_reset_command(client); + break; + } + + client->handling_input = TRUE; + o_stream_cork(client->output); + do { + T_BEGIN { + ret = client_handle_input(cmd); + } T_END; + } while (ret && !client->disconnected); + o_stream_uncork(client->output); + client->handling_input = FALSE; + + if (client->command_pending) + client->input_pending = TRUE; + + if (client->output->closed) + client_destroy(client, NULL); +} + +int client_output(struct client *client) +{ + struct client_command_context *cmd = &client->cmd; + int ret; + bool finished; + + client->last_output = ioloop_time; + timeout_reset(client->to_idle); + if (client->to_idle_output != NULL) + timeout_reset(client->to_idle_output); + + if ((ret = o_stream_flush(client->output)) < 0) { + client_destroy(client, NULL); + return 1; + } + + if (!client->command_pending) + return 1; + + /* continue processing command */ + o_stream_cork(client->output); + client->output_pending = TRUE; + finished = cmd->func(cmd) || cmd->param_error; + + /* a bit kludgy check. normally we would want to get back to this + output handler, but IDLE is a special case which has command + pending but without necessarily anything to write. */ + if (!finished && client->output_pending) + o_stream_set_flush_pending(client->output, TRUE); + + o_stream_uncork(client->output); + + if (finished) { + /* command execution was finished */ + client->bad_counter = 0; + _client_reset_command(client); + + if (client->input_pending) + client_input(client); + } + return ret; +} + +void clients_destroy_all(void) +{ + while (managesieve_clients != NULL) { + mail_storage_service_io_activate_user(managesieve_clients->service_user); + client_send_bye(managesieve_clients, "Server shutting down."); + client_destroy(managesieve_clients, "Server shutting down."); + } +} diff --git a/pigeonhole/src/managesieve/managesieve-client.h b/pigeonhole/src/managesieve/managesieve-client.h new file mode 100644 index 0000000..6053eb6 --- /dev/null +++ b/pigeonhole/src/managesieve/managesieve-client.h @@ -0,0 +1,162 @@ +#ifndef MANAGESIEVE_CLIENT_H +#define MANAGESIEVE_CLIENT_H + +#include "managesieve-commands.h" + +struct client; +struct sieve_storage; +struct managesieve_parser; +struct managesieve_arg; + +struct client_command_context { + struct client *client; + struct event *event; + + pool_t pool; + /* Name of this command */ + const char *name; + /* Parameters for this command. These are generated from parsed + ManageSieve arguments, so they may not be exactly the same as how + client sent them. */ + const char *args; + + command_func_t *func; + void *context; + + bool param_error:1; +}; + +struct managesieve_module_register { + unsigned int id; +}; + +union managesieve_module_context { + struct managesieve_module_register *reg; +}; +extern struct managesieve_module_register managesieve_module_register; + +struct client { + struct client *prev, *next; + + struct event *event; + const char *session_id; + int fd_in, fd_out; + struct io *io; + struct istream *input; + struct ostream *output; + struct timeout *to_idle, *to_idle_output; + + pool_t pool; + struct mail_storage_service_user *service_user; + const struct managesieve_settings *set; + + struct mail_user *user; + + struct sieve_instance *svinst; + struct sieve_storage *storage; + + time_t last_input, last_output; + unsigned int bad_counter; + + struct managesieve_parser *parser; + struct client_command_context cmd; + + uoff_t put_bytes; + uoff_t get_bytes; + uoff_t check_bytes; + unsigned int put_count; + unsigned int get_count; + unsigned int check_count; + unsigned int deleted_count; + unsigned int renamed_count; + + bool disconnected:1; + bool destroyed:1; + bool command_pending:1; + bool input_pending:1; + bool output_pending:1; + bool handling_input:1; + bool anvil_sent:1; + bool input_skip_line:1; /* skip all the data until we've found a new + line */ +}; + +extern struct client *managesieve_clients; +extern unsigned int managesieve_client_count; + +/* Create new client with specified input/output handles. socket specifies + if the handle is a socket. */ +struct client * +client_create(int fd_in, int fd_out, const char *session_id, + struct event *event, struct mail_user *user, + struct mail_storage_service_user *service_user, + const struct managesieve_settings *set); +void client_create_finish(struct client *client); +void client_destroy(struct client *client, const char *reason); + +void client_dump_capability(struct client *client); + +/* Disconnect client connection */ +void client_disconnect(struct client *client, const char *reason); +void client_disconnect_with_error(struct client *client, const char *msg); + +/* Send a line of data to client. Returns 1 if ok, 0 if buffer is getting full, + -1 if error */ +int client_send_line(struct client *client, const char *data); + +void client_send_response(struct client *client, const char *oknobye, + const char *resp_code, const char *msg); + +#define client_send_ok(client, msg) \ + client_send_response(client, "OK", NULL, msg) +#define client_send_no(client, msg) \ + client_send_response(client, "NO", NULL, msg) +#define client_send_bye(client, msg) \ + client_send_response(client, "BYE", NULL, msg) + +#define client_send_okresp(client, resp_code, msg) \ + client_send_response(client, "OK", resp_code, msg) +#define client_send_noresp(client, resp_code, msg) \ + client_send_response(client, "NO", resp_code, msg) +#define client_send_byeresp(cmd, resp_code, msg) \ + client_send_response(client, "BYE", resp_code, msg) + +struct event_passthrough * +client_command_create_finish_event(struct client_command_context *cmd); + +/* Send BAD command error to client. msg can be NULL. */ +void client_send_command_error(struct client_command_context *cmd, + const char *msg); + +/* Send storage or sieve-related errors to the client. Returns command finish + event with the "error" field set accordingly. */ +void client_command_storage_error(struct client_command_context *cmd, + const char *source_filename, + unsigned int source_linenum, + const char *log_prefix, ...) + ATTR_FORMAT(4, 5); +#define client_command_storage_error(cmd, ...) \ + client_command_storage_error(cmd, __FILE__, __LINE__, __VA_ARGS__) + +/* Read a number of arguments. Returns TRUE if everything was read or + FALSE if either needs more data or error occurred. */ +bool client_read_args(struct client_command_context *cmd, unsigned int count, + unsigned int flags, bool no_more, + const struct managesieve_arg **args_r); +/* Reads a number of string arguments. ... is a list of pointers where to + store the arguments. */ +bool client_read_string_args(struct client_command_context *cmd, bool no_more, + unsigned int count, ...); + +static inline bool client_read_no_args(struct client_command_context *cmd) +{ + return client_read_args(cmd, 0, 0, TRUE, NULL); +} + +void _client_reset_command(struct client *client); +void client_input(struct client *client); +int client_output(struct client *client); + +void clients_destroy_all(void); + +#endif diff --git a/pigeonhole/src/managesieve/managesieve-commands.c b/pigeonhole/src/managesieve/managesieve-commands.c new file mode 100644 index 0000000..87e2048 --- /dev/null +++ b/pigeonhole/src/managesieve/managesieve-commands.c @@ -0,0 +1,110 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" + +#include "managesieve-common.h" +#include "managesieve-commands.h" + + +/* May want to combine this somewhere in a commands-common.c to avoid duplicate + code + */ + +static const struct command managesieve_base_commands[] = { + { "CAPABILITY", cmd_capability }, + { "LOGOUT", cmd_logout }, + { "PUTSCRIPT", cmd_putscript }, + { "CHECKSCRIPT", cmd_checkscript }, + { "GETSCRIPT", cmd_getscript }, + { "SETACTIVE", cmd_setactive }, + { "DELETESCRIPT", cmd_deletescript }, + { "LISTSCRIPTS", cmd_listscripts }, + { "HAVESPACE", cmd_havespace }, + { "RENAMESCRIPT", cmd_renamescript }, + { "NOOP", cmd_noop } +}; + +#define MANAGESIEVE_COMMANDS_COUNT N_ELEMENTS(managesieve_base_commands) + +static ARRAY(struct command) managesieve_commands; +static bool commands_unsorted; + +void command_register(const char *name, command_func_t *func) +{ + struct command cmd; + + i_zero(&cmd); + cmd.name = name; + cmd.func = func; + array_append(&managesieve_commands, &cmd, 1); + + commands_unsorted = TRUE; +} + +void command_unregister(const char *name) +{ + const struct command *cmd; + unsigned int i, count; + + cmd = array_get(&managesieve_commands, &count); + for (i = 0; i < count; i++) { + if (strcasecmp(cmd[i].name, name) == 0) { + array_delete(&managesieve_commands, i, 1); + return; + } + } + + i_error("Trying to unregister unknown command '%s'", name); +} + +void command_register_array(const struct command *cmdarr, unsigned int count) +{ + commands_unsorted = TRUE; + array_append(&managesieve_commands, cmdarr, count); +} + +void command_unregister_array(const struct command *cmdarr, unsigned int count) +{ + while (count > 0) { + command_unregister(cmdarr->name); + count--; cmdarr++; + } +} + +static int command_cmp(const struct command *c1, const struct command *c2) +{ + return strcasecmp(c1->name, c2->name); +} + +static int command_bsearch(const char *name, const struct command *cmd) +{ + return strcasecmp(name, cmd->name); +} + +struct command *command_find(const char *name) +{ + if (commands_unsorted) { + array_sort(&managesieve_commands, command_cmp); + commands_unsorted = FALSE; + } + + return array_bsearch(&managesieve_commands, name, command_bsearch); +} + +void commands_init(void) +{ + i_array_init(&managesieve_commands, 16); + commands_unsorted = FALSE; + + command_register_array(managesieve_base_commands, + MANAGESIEVE_COMMANDS_COUNT); +} + +void commands_deinit(void) +{ + command_unregister_array(managesieve_base_commands, + MANAGESIEVE_COMMANDS_COUNT); + array_free(&managesieve_commands); +} diff --git a/pigeonhole/src/managesieve/managesieve-commands.h b/pigeonhole/src/managesieve/managesieve-commands.h new file mode 100644 index 0000000..d922b74 --- /dev/null +++ b/pigeonhole/src/managesieve/managesieve-commands.h @@ -0,0 +1,46 @@ +#ifndef MANAGESIEVE_COMMANDS_H +#define MANAGESIEVE_COMMANDS_H + +struct client_command_context; + +#include "managesieve-parser.h" + +typedef bool command_func_t(struct client_command_context *cmd); + +struct command { + const char *name; + command_func_t *func; +}; + +/* Register command. Given name parameter must be permanently stored until + command is unregistered. */ +void command_register(const char *name, command_func_t *func); +void command_unregister(const char *name); + +/* Register array of commands. */ +void command_register_array(const struct command *cmdarr, unsigned int count); +void command_unregister_array(const struct command *cmdarr, unsigned int count); + +struct command *command_find(const char *name); + +void commands_init(void); +void commands_deinit(void); + +/* MANAGESIEVE commands: */ + +/* Non-Authenticated State */ +extern bool cmd_logout(struct client_command_context *cmd); +extern bool cmd_capability(struct client_command_context *cmd); +extern bool cmd_noop(struct client_command_context *cmd); + +/* Authenticated State */ +extern bool cmd_putscript(struct client_command_context *cmd); +extern bool cmd_checkscript(struct client_command_context *cmd); +extern bool cmd_getscript(struct client_command_context *cmd); +extern bool cmd_setactive(struct client_command_context *cmd); +extern bool cmd_deletescript(struct client_command_context *cmd); +extern bool cmd_listscripts(struct client_command_context *cmd); +extern bool cmd_havespace(struct client_command_context *cmd); +extern bool cmd_renamescript(struct client_command_context *cmd); + +#endif diff --git a/pigeonhole/src/managesieve/managesieve-common.h b/pigeonhole/src/managesieve/managesieve-common.h new file mode 100644 index 0000000..e1df589 --- /dev/null +++ b/pigeonhole/src/managesieve/managesieve-common.h @@ -0,0 +1,31 @@ +#ifndef MANAGESIEVE_COMMON_H +#define MANAGESIEVE_COMMON_H + +#include "pigeonhole-config.h" + +/* Disconnect client after idling this many milliseconds */ +#define CLIENT_IDLE_TIMEOUT_MSECS (60*30*1000) + +/* If we can't send anything to client for this long, disconnect the client */ +#define CLIENT_OUTPUT_TIMEOUT_MSECS (5*60*1000) + +/* Stop buffering more data into output stream after this many bytes */ +#define CLIENT_OUTPUT_OPTIMAL_SIZE 2048 + +/* Disconnect client when it sends too many bad commands in a row */ +#define CLIENT_MAX_BAD_COMMANDS 20 + +#define CRITICAL_MSG \ + "Internal error occurred. Refer to server log for more information." +#define CRITICAL_MSG_STAMP CRITICAL_MSG " [%Y-%m-%d %H:%M:%S]" + +#include "lib.h" +#include "managesieve-client.h" +#include "managesieve-settings.h" + +extern void (*hook_client_created)(struct client **client); +extern struct event_category event_category_managesieve; + +void managesieve_refresh_proctitle(void); + +#endif diff --git a/pigeonhole/src/managesieve/managesieve-quota.c b/pigeonhole/src/managesieve/managesieve-quota.c new file mode 100644 index 0000000..07b58ca --- /dev/null +++ b/pigeonhole/src/managesieve/managesieve-quota.c @@ -0,0 +1,98 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "strfuncs.h" + +#include "sieve.h" +#include "sieve-storage.h" + +#include "managesieve-client.h" +#include "managesieve-quota.h" + +uint64_t managesieve_quota_max_script_size(struct client *client) +{ + return sieve_storage_quota_max_script_size(client->storage); +} + +bool managesieve_quota_check_validsize(struct client_command_context *cmd, + size_t size) +{ + struct client *client = cmd->client; + uint64_t limit; + + if (!sieve_storage_quota_validsize(client->storage, size, &limit)) { + const char *error_msg; + + error_msg = t_strdup_printf( + "Script is too large (max %llu bytes).", + (unsigned long long int)limit); + + struct event_passthrough *e = + client_command_create_finish_event(cmd); + e_debug(e->event(), + "Script size check failed (size %zu bytes): %s", + size, error_msg); + + client_send_noresp(client, "QUOTA/MAXSIZE", error_msg); + return FALSE; + } + return TRUE; +} + +bool managesieve_quota_check_all(struct client_command_context *cmd, + const char *scriptname, size_t size) +{ + struct client *client = cmd->client; + enum sieve_storage_quota quota; + uint64_t limit; + const char *resp_code = NULL, *error_msg = NULL; + int ret; + + ret = sieve_storage_quota_havespace(client->storage, scriptname, + size, "a, &limit); + if (ret > 0) + return TRUE; + if (ret < 0) { + client_command_storage_error( + cmd, "Failed to check quota for script `%s' " + "(size %zu bytes)", scriptname, size); + return FALSE; + } + + switch (quota) { + case SIEVE_STORAGE_QUOTA_MAXSIZE: + resp_code = "QUOTA/MAXSIZE"; + error_msg = t_strdup_printf("Script is too large " + "(max %llu bytes).", + (unsigned long long int)limit); + break; + case SIEVE_STORAGE_QUOTA_MAXSCRIPTS: + resp_code = "QUOTA/MAXSCRIPTS"; + error_msg = t_strdup_printf("Script count quota exceeded " + "(max %llu scripts).", + (unsigned long long int)limit); + break; + case SIEVE_STORAGE_QUOTA_MAXSTORAGE: + resp_code = "QUOTA/MAXSTORAGE"; + error_msg = t_strdup_printf("Script storage quota exceeded " + "(max %llu bytes).", + (unsigned long long int)limit); + break; + default: + resp_code = "QUOTA"; + error_msg = "Quota exceeded."; + } + + struct event_passthrough *e = + client_command_create_finish_event(cmd)-> + add_str("error", error_msg); + e_debug(e->event(), + "Quota check failed for script `%s' (size %zu bytes): %s", + scriptname, size, error_msg); + + client_send_noresp(client, resp_code, error_msg); + + return FALSE; +} + diff --git a/pigeonhole/src/managesieve/managesieve-quota.h b/pigeonhole/src/managesieve/managesieve-quota.h new file mode 100644 index 0000000..f6b37bf --- /dev/null +++ b/pigeonhole/src/managesieve/managesieve-quota.h @@ -0,0 +1,11 @@ +#ifndef MANAGESIEVE_QUOTA_H +#define MANAGESIEVE_QUOTA_H + +uint64_t managesieve_quota_max_script_size(struct client *client); + +bool managesieve_quota_check_validsize(struct client_command_context *cmd, + size_t size); +bool managesieve_quota_check_all(struct client_command_context *cmd, + const char *scriptname, size_t size); + +#endif diff --git a/pigeonhole/src/managesieve/managesieve-settings.c b/pigeonhole/src/managesieve/managesieve-settings.c new file mode 100644 index 0000000..8e6e88b --- /dev/null +++ b/pigeonhole/src/managesieve/managesieve-settings.c @@ -0,0 +1,170 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "buffer.h" +#include "settings-parser.h" +#include "service-settings.h" +#include "mail-storage-settings.h" + +#include "pigeonhole-config.h" + +#include "managesieve-settings.h" + +#include <stddef.h> +#include <unistd.h> + +static bool managesieve_settings_verify(void *_set, pool_t pool, + const char **error_r); + +/* <settings checks> */ +static struct file_listener_settings managesieve_unix_listeners_array[] = { + { "login/sieve", 0666, "", "" } +}; +static struct file_listener_settings *managesieve_unix_listeners[] = { + &managesieve_unix_listeners_array[0] +}; +static buffer_t managesieve_unix_listeners_buf = { + { { managesieve_unix_listeners, sizeof(managesieve_unix_listeners) } } +}; +/* </settings checks> */ + +struct service_settings managesieve_settings_service_settings = { + .name = "managesieve", + .protocol = "sieve", + .type = "", + .executable = "managesieve", + .user = "", + .group = "", + .privileged_group = "", + .extra_groups = "", + .chroot = "", + + .drop_priv_before_exec = FALSE, + + .process_min_avail = 0, + .process_limit = 0, + .client_limit = 1, + .service_count = 1, + .idle_kill = 0, + .vsz_limit = (uoff_t)-1, + + .unix_listeners = { { &managesieve_unix_listeners_buf, + sizeof(managesieve_unix_listeners[0]) } }, + .fifo_listeners = ARRAY_INIT, + .inet_listeners = ARRAY_INIT +}; + +#undef DEF +#define DEF(type, name) \ + SETTING_DEFINE_STRUCT_##type(#name, name, struct managesieve_settings) + +static struct setting_define managesieve_setting_defines[] = { + DEF(BOOL, mail_debug), + DEF(BOOL, verbose_proctitle), + DEF(STR_VARS, rawlog_dir), + + DEF(SIZE, managesieve_max_line_length), + DEF(STR, managesieve_implementation_string), + DEF(STR, managesieve_client_workarounds), + DEF(STR, managesieve_logout_format), + DEF(UINT, managesieve_max_compile_errors), + + + SETTING_DEFINE_LIST_END +}; + +static struct managesieve_settings managesieve_default_settings = { + .mail_debug = FALSE, + .verbose_proctitle = FALSE, + .rawlog_dir = "", + + /* RFC-2683 recommends at least 8000 bytes. Some clients however don't + break large message sets to multiple commands, so we're pretty + liberal by default. */ + .managesieve_max_line_length = 65536, + .managesieve_implementation_string = DOVECOT_NAME " " PIGEONHOLE_NAME, + .managesieve_client_workarounds = "", + .managesieve_logout_format = "bytes=%i/%o", + .managesieve_max_compile_errors = 5 +}; + +static const struct setting_parser_info *managesieve_setting_dependencies[] = { + &mail_user_setting_parser_info, + NULL +}; + +const struct setting_parser_info managesieve_setting_parser_info = { + .module_name = "managesieve", + .defines = managesieve_setting_defines, + .defaults = &managesieve_default_settings, + + .type_offset = (size_t)-1, + .struct_size = sizeof(struct managesieve_settings), + + .parent_offset = (size_t)-1, + .parent = NULL, + + .check_func = managesieve_settings_verify, + .dependencies = managesieve_setting_dependencies +}; + +const struct setting_parser_info *managesieve_settings_set_roots[] = { + &managesieve_setting_parser_info, + NULL +}; + +/* <settings checks> */ +struct managesieve_client_workaround_list { + const char *name; + enum managesieve_client_workarounds num; +}; + +static const struct managesieve_client_workaround_list +managesieve_client_workaround_list[] = { + { NULL, 0 } +}; + +static int +managesieve_settings_parse_workarounds(struct managesieve_settings *set, + const char **error_r) +{ + enum managesieve_client_workarounds client_workarounds = 0; + const struct managesieve_client_workaround_list *list; + const char *const *str; + + str = t_strsplit_spaces(set->managesieve_client_workarounds, " ,"); + for (; *str != NULL; str++) { + list = managesieve_client_workaround_list; + for (; list->name != NULL; list++) { + if (strcasecmp(*str, list->name) == 0) { + client_workarounds |= list->num; + break; + } + } + if (list->name == NULL) { + *error_r = t_strdup_printf( + "managesieve_client_workarounds: " + "Unknown workaround: %s", *str); + return -1; + } + } + set->parsed_workarounds = client_workarounds; + return 0; +} + + +static bool +managesieve_settings_verify(void *_set, pool_t pool ATTR_UNUSED, + const char **error_r) +{ + struct managesieve_settings *set = _set; + + if (managesieve_settings_parse_workarounds(set, error_r) < 0) + return FALSE; + return TRUE; +} + +/* </settings checks> */ + +const char *managesieve_settings_version = DOVECOT_ABI_VERSION; diff --git a/pigeonhole/src/managesieve/managesieve-settings.h b/pigeonhole/src/managesieve/managesieve-settings.h new file mode 100644 index 0000000..a72338b --- /dev/null +++ b/pigeonhole/src/managesieve/managesieve-settings.h @@ -0,0 +1,29 @@ +#ifndef MANAGESIEVE_SETTINGS_H +#define MANAGESIEVE_SETTINGS_H + +struct mail_user_settings; + +/* <settings checks> */ +enum managesieve_client_workarounds { + WORKAROUND_NONE = 0x00 +}; +/* </settings checks> */ + +struct managesieve_settings { + bool mail_debug; + bool verbose_proctitle; + const char *rawlog_dir; + + /* managesieve: */ + uoff_t managesieve_max_line_length; + const char *managesieve_implementation_string; + const char *managesieve_client_workarounds; + const char *managesieve_logout_format; + unsigned int managesieve_max_compile_errors; + + enum managesieve_client_workarounds parsed_workarounds; +}; + +extern const struct setting_parser_info managesieve_setting_parser_info; + +#endif diff --git a/pigeonhole/src/plugins/Makefile.am b/pigeonhole/src/plugins/Makefile.am new file mode 100644 index 0000000..b6c7551 --- /dev/null +++ b/pigeonhole/src/plugins/Makefile.am @@ -0,0 +1,7 @@ +SUBDIRS = \ + doveadm-sieve \ + lda-sieve \ + sieve-extprograms \ + imapsieve \ + imap-filter-sieve \ + settings diff --git a/pigeonhole/src/plugins/Makefile.in b/pigeonhole/src/plugins/Makefile.in new file mode 100644 index 0000000..890ce14 --- /dev/null +++ b/pigeonhole/src/plugins/Makefile.in @@ -0,0 +1,699 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/plugins +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = \ + doveadm-sieve \ + lda-sieve \ + sieve-extprograms \ + imapsieve \ + imap-filter-sieve \ + settings + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/plugins/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/plugins/doveadm-sieve/Makefile.am b/pigeonhole/src/plugins/doveadm-sieve/Makefile.am new file mode 100644 index 0000000..9f98dab --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/Makefile.am @@ -0,0 +1,31 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_STORAGE_INCLUDE) \ + $(LIBDOVECOT_DOVEADM_INCLUDE) + +doveadm_moduledir = $(dovecot_moduledir)/doveadm +lib10_doveadm_sieve_plugin_la_LDFLAGS = -module -avoid-version + +doveadm_module_LTLIBRARIES = lib10_doveadm_sieve_plugin.la + +lib10_doveadm_sieve_plugin_la_LIBADD = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la + +commands = \ + doveadm-sieve-cmd-list.c \ + doveadm-sieve-cmd-get.c \ + doveadm-sieve-cmd-put.c \ + doveadm-sieve-cmd-delete.c \ + doveadm-sieve-cmd-activate.c \ + doveadm-sieve-cmd-rename.c + +lib10_doveadm_sieve_plugin_la_SOURCES = \ + $(commands) \ + doveadm-sieve-cmd.c \ + doveadm-sieve-sync.c \ + doveadm-sieve-plugin.c + +noinst_HEADERS = \ + doveadm-sieve-cmd.h \ + doveadm-sieve-plugin.h diff --git a/pigeonhole/src/plugins/doveadm-sieve/Makefile.in b/pigeonhole/src/plugins/doveadm-sieve/Makefile.in new file mode 100644 index 0000000..be3b853 --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/Makefile.in @@ -0,0 +1,796 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/plugins/doveadm-sieve +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(doveadm_moduledir)" +LTLIBRARIES = $(doveadm_module_LTLIBRARIES) +lib10_doveadm_sieve_plugin_la_DEPENDENCIES = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la +am__objects_1 = doveadm-sieve-cmd-list.lo doveadm-sieve-cmd-get.lo \ + doveadm-sieve-cmd-put.lo doveadm-sieve-cmd-delete.lo \ + doveadm-sieve-cmd-activate.lo doveadm-sieve-cmd-rename.lo +am_lib10_doveadm_sieve_plugin_la_OBJECTS = $(am__objects_1) \ + doveadm-sieve-cmd.lo doveadm-sieve-sync.lo \ + doveadm-sieve-plugin.lo +lib10_doveadm_sieve_plugin_la_OBJECTS = \ + $(am_lib10_doveadm_sieve_plugin_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +lib10_doveadm_sieve_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) \ + $(lib10_doveadm_sieve_plugin_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/doveadm-sieve-cmd-activate.Plo \ + ./$(DEPDIR)/doveadm-sieve-cmd-delete.Plo \ + ./$(DEPDIR)/doveadm-sieve-cmd-get.Plo \ + ./$(DEPDIR)/doveadm-sieve-cmd-list.Plo \ + ./$(DEPDIR)/doveadm-sieve-cmd-put.Plo \ + ./$(DEPDIR)/doveadm-sieve-cmd-rename.Plo \ + ./$(DEPDIR)/doveadm-sieve-cmd.Plo \ + ./$(DEPDIR)/doveadm-sieve-plugin.Plo \ + ./$(DEPDIR)/doveadm-sieve-sync.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(lib10_doveadm_sieve_plugin_la_SOURCES) +DIST_SOURCES = $(lib10_doveadm_sieve_plugin_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_STORAGE_INCLUDE) \ + $(LIBDOVECOT_DOVEADM_INCLUDE) + +doveadm_moduledir = $(dovecot_moduledir)/doveadm +lib10_doveadm_sieve_plugin_la_LDFLAGS = -module -avoid-version +doveadm_module_LTLIBRARIES = lib10_doveadm_sieve_plugin.la +lib10_doveadm_sieve_plugin_la_LIBADD = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la + +commands = \ + doveadm-sieve-cmd-list.c \ + doveadm-sieve-cmd-get.c \ + doveadm-sieve-cmd-put.c \ + doveadm-sieve-cmd-delete.c \ + doveadm-sieve-cmd-activate.c \ + doveadm-sieve-cmd-rename.c + +lib10_doveadm_sieve_plugin_la_SOURCES = \ + $(commands) \ + doveadm-sieve-cmd.c \ + doveadm-sieve-sync.c \ + doveadm-sieve-plugin.c + +noinst_HEADERS = \ + doveadm-sieve-cmd.h \ + doveadm-sieve-plugin.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/doveadm-sieve/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/plugins/doveadm-sieve/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-doveadm_moduleLTLIBRARIES: $(doveadm_module_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(doveadm_module_LTLIBRARIES)'; test -n "$(doveadm_moduledir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(doveadm_moduledir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(doveadm_moduledir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(doveadm_moduledir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(doveadm_moduledir)"; \ + } + +uninstall-doveadm_moduleLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(doveadm_module_LTLIBRARIES)'; test -n "$(doveadm_moduledir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(doveadm_moduledir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(doveadm_moduledir)/$$f"; \ + done + +clean-doveadm_moduleLTLIBRARIES: + -test -z "$(doveadm_module_LTLIBRARIES)" || rm -f $(doveadm_module_LTLIBRARIES) + @list='$(doveadm_module_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +lib10_doveadm_sieve_plugin.la: $(lib10_doveadm_sieve_plugin_la_OBJECTS) $(lib10_doveadm_sieve_plugin_la_DEPENDENCIES) $(EXTRA_lib10_doveadm_sieve_plugin_la_DEPENDENCIES) + $(AM_V_CCLD)$(lib10_doveadm_sieve_plugin_la_LINK) -rpath $(doveadm_moduledir) $(lib10_doveadm_sieve_plugin_la_OBJECTS) $(lib10_doveadm_sieve_plugin_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doveadm-sieve-cmd-activate.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doveadm-sieve-cmd-delete.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doveadm-sieve-cmd-get.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doveadm-sieve-cmd-list.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doveadm-sieve-cmd-put.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doveadm-sieve-cmd-rename.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doveadm-sieve-cmd.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doveadm-sieve-plugin.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doveadm-sieve-sync.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(doveadm_moduledir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-doveadm_moduleLTLIBRARIES clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-activate.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-delete.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-get.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-list.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-put.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-rename.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-plugin.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-sync.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-doveadm_moduleLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-activate.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-delete.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-get.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-list.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-put.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-rename.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-plugin.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-sync.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-doveadm_moduleLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-doveadm_moduleLTLIBRARIES clean-generic clean-libtool \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-doveadm_moduleLTLIBRARIES \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-doveadm_moduleLTLIBRARIES + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-activate.c b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-activate.c new file mode 100644 index 0000000..f392478 --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-activate.c @@ -0,0 +1,145 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "doveadm-mail.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "doveadm-sieve-cmd.h" + +struct doveadm_sieve_activate_cmd_context { + struct doveadm_sieve_cmd_context ctx; + + const char *scriptname; +}; + +static int +cmd_sieve_activate_run(struct doveadm_sieve_cmd_context *_ctx) +{ + struct doveadm_sieve_activate_cmd_context *ctx = + (struct doveadm_sieve_activate_cmd_context *)_ctx; + struct sieve_storage *storage = _ctx->storage; + struct sieve_script *script; + enum sieve_error error; + int ret = 0; + + script = sieve_storage_open_script + (storage, ctx->scriptname, NULL); + if ( script == NULL ) { + i_error("Failed to activate Sieve script: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + return -1; + } + + if ( sieve_script_is_active(script) <= 0 ) { + /* Script is first being activated; compile it again without the UPLOAD + * flag. + */ + struct sieve_error_handler *ehandler; + enum sieve_compile_flags cpflags = + SIEVE_COMPILE_FLAG_NOGLOBAL | SIEVE_COMPILE_FLAG_ACTIVATED; + struct sieve_binary *sbin; + enum sieve_error error; + + /* Compile */ + ehandler = sieve_master_ehandler_create(ctx->ctx.svinst, 0); + if ( (sbin=sieve_compile_script + (script, ehandler, cpflags, &error)) == NULL ) { + doveadm_sieve_cmd_failed_error(_ctx, error); + ret = -1; + } else { + sieve_close(&sbin); + } + sieve_error_handler_unref(&ehandler); + } + + /* Activate only when script is valid (or already active) */ + if ( ret == 0 ) { + /* Refresh activation no matter what; this can also resolve some erroneous + * situations. + */ + ret = sieve_script_activate(script, (time_t)-1); + if ( ret < 0 ) { + i_error("Failed to activate Sieve script: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + ret = -1; + } + } + + sieve_script_unref(&script); + return ret; +} + +static int cmd_sieve_deactivate_run +(struct doveadm_sieve_cmd_context *_ctx) +{ + struct sieve_storage *storage = _ctx->storage; + enum sieve_error error; + + if (sieve_storage_deactivate(storage, (time_t)-1) < 0) { + i_error("Failed to deactivate Sieve script: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + return -1; + } + return 0; +} + +static void cmd_sieve_activate_init +(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct doveadm_sieve_activate_cmd_context *ctx = + (struct doveadm_sieve_activate_cmd_context *)_ctx; + + if (str_array_length(args) != 1) + doveadm_mail_help_name("sieve activate"); + doveadm_sieve_cmd_scriptnames_check(args); + + ctx->scriptname = p_strdup(ctx->ctx.ctx.pool, args[0]); +} + +static struct doveadm_mail_cmd_context * +cmd_sieve_activate_alloc(void) +{ + struct doveadm_sieve_activate_cmd_context *ctx; + + ctx = doveadm_sieve_cmd_alloc(struct doveadm_sieve_activate_cmd_context); + ctx->ctx.ctx.v.init = cmd_sieve_activate_init; + ctx->ctx.v.run = cmd_sieve_activate_run; + return &ctx->ctx.ctx; +} + +static struct doveadm_mail_cmd_context * +cmd_sieve_deactivate_alloc(void) +{ + struct doveadm_sieve_cmd_context *ctx; + + ctx = doveadm_sieve_cmd_alloc(struct doveadm_sieve_cmd_context); + ctx->v.run = cmd_sieve_deactivate_run; + return &ctx->ctx; +} + +struct doveadm_cmd_ver2 doveadm_sieve_cmd_activate = { + .name = "sieve activate", + .mail_cmd = cmd_sieve_activate_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"<scriptname>", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('\0',"scriptname",CMD_PARAM_STR,CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; + +struct doveadm_cmd_ver2 doveadm_sieve_cmd_deactivate = { + .name = "sieve deactivate", + .mail_cmd = cmd_sieve_deactivate_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX, +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAMS_END +}; diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-delete.c b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-delete.c new file mode 100644 index 0000000..8517abd --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-delete.c @@ -0,0 +1,116 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "doveadm-mail.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "doveadm-sieve-cmd.h" + +struct doveadm_sieve_delete_cmd_context { + struct doveadm_sieve_cmd_context ctx; + + ARRAY_TYPE(const_string) scriptnames; + bool ignore_active:1; +}; + +static int +cmd_sieve_delete_run(struct doveadm_sieve_cmd_context *_ctx) +{ + struct doveadm_sieve_delete_cmd_context *ctx = + (struct doveadm_sieve_delete_cmd_context *)_ctx; + struct sieve_storage *storage = _ctx->storage; + const ARRAY_TYPE(const_string) *scriptnames = &ctx->scriptnames; + const char *scriptname; + struct sieve_script *script; + enum sieve_error error; + int ret = 0; + + array_foreach_elem(scriptnames, scriptname) { + int sret = 0; + + script = sieve_storage_open_script + (storage, scriptname, NULL); + if (script == NULL) { + sret = -1; + } else { + if (sieve_script_delete(script, ctx->ignore_active) < 0) { + (void)sieve_storage_get_last_error(storage, &error); + sret = -1; + } + sieve_script_unref(&script); + } + + if (sret < 0) { + i_error("Failed to delete Sieve script: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + ret = -1; + } + } + return ret; +} + +static void cmd_sieve_delete_init +(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct doveadm_sieve_delete_cmd_context *ctx = + (struct doveadm_sieve_delete_cmd_context *)_ctx; + const char *name; + unsigned int i; + + if (args[0] == NULL) + doveadm_mail_help_name("sieve delete"); + doveadm_sieve_cmd_scriptnames_check(args); + + for (i = 0; args[i] != NULL; i++) { + name = p_strdup(ctx->ctx.ctx.pool, args[i]); + array_append(&ctx->scriptnames, &name, 1); + } +} + +static bool +cmd_sieve_delete_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c) +{ + struct doveadm_sieve_delete_cmd_context *ctx = + (struct doveadm_sieve_delete_cmd_context *)_ctx; + + switch ( c ) { + case 'a': + ctx->ignore_active = TRUE; + break; + default: + return FALSE; + } + return TRUE; +} + +static struct doveadm_mail_cmd_context * +cmd_sieve_delete_alloc(void) +{ + struct doveadm_sieve_delete_cmd_context *ctx; + + ctx = doveadm_sieve_cmd_alloc(struct doveadm_sieve_delete_cmd_context); + ctx->ctx.ctx.getopt_args = "a"; + ctx->ctx.ctx.v.parse_arg = cmd_sieve_delete_parse_arg; + ctx->ctx.ctx.v.init = cmd_sieve_delete_init; + ctx->ctx.v.run = cmd_sieve_delete_run; + p_array_init(&ctx->scriptnames, ctx->ctx.ctx.pool, 16); + return &ctx->ctx.ctx; +} + +struct doveadm_cmd_ver2 doveadm_sieve_cmd_delete = { + .name = "sieve delete", + .mail_cmd = cmd_sieve_delete_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"[-a] <scriptname> [...]", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('a',"ignore-active",CMD_PARAM_BOOL,0) +DOVEADM_CMD_PARAM('\0',"scriptname",CMD_PARAM_ARRAY,CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-get.c b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-get.c new file mode 100644 index 0000000..e1bf7e3 --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-get.c @@ -0,0 +1,83 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "doveadm-print.h" +#include "doveadm-mail.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "doveadm-sieve-cmd.h" + +struct doveadm_sieve_get_cmd_context { + struct doveadm_sieve_cmd_context ctx; + + const char *scriptname; +}; + +static int +cmd_sieve_get_run(struct doveadm_sieve_cmd_context *_ctx) +{ + struct doveadm_sieve_get_cmd_context *ctx = + (struct doveadm_sieve_get_cmd_context *)_ctx; + struct sieve_script *script; + struct istream *input; + enum sieve_error error; + int ret; + + script = sieve_storage_open_script + (_ctx->storage, ctx->scriptname, &error); + if ( script == NULL || sieve_script_get_stream + (script, &input, &error) < 0 ) { + i_error("Failed to open Sieve script: %s", + sieve_storage_get_last_error(_ctx->storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + if (script != NULL) + sieve_script_unref(&script); + return -1; + } + + ret = doveadm_print_istream(input); + sieve_script_unref(&script); + return ret; +} + +static void cmd_sieve_get_init +(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct doveadm_sieve_get_cmd_context *ctx = + (struct doveadm_sieve_get_cmd_context *)_ctx; + + if ( str_array_length(args) != 1 ) + doveadm_mail_help_name("sieve get"); + doveadm_sieve_cmd_scriptnames_check(args); + + ctx->scriptname = p_strdup(ctx->ctx.ctx.pool, args[0]); + + doveadm_print_header_simple("sieve script"); +} + +static struct doveadm_mail_cmd_context * +cmd_sieve_get_alloc(void) +{ + struct doveadm_sieve_get_cmd_context *ctx; + + ctx = doveadm_sieve_cmd_alloc(struct doveadm_sieve_get_cmd_context); + ctx->ctx.ctx.v.init = cmd_sieve_get_init; + ctx->ctx.v.run = cmd_sieve_get_run; + doveadm_print_init("pager"); + return &ctx->ctx.ctx; +} + +struct doveadm_cmd_ver2 doveadm_sieve_cmd_get = { + .name = "sieve get", + .mail_cmd = cmd_sieve_get_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"<scriptname>", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('\0',"scriptname",CMD_PARAM_STR,CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-list.c b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-list.c new file mode 100644 index 0000000..0dbf379 --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-list.c @@ -0,0 +1,79 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "doveadm-print.h" +#include "doveadm-mail.h" + +#include "sieve.h" +#include "sieve-storage.h" + +#include "doveadm-sieve-cmd.h" + +static int +cmd_sieve_list_run(struct doveadm_sieve_cmd_context *_ctx) +{ + struct sieve_storage *storage = _ctx->storage; + struct sieve_storage_list_context *lctx; + enum sieve_error error; + const char *scriptname; + bool active; + + if ( (lctx = sieve_storage_list_init(storage)) + == NULL ) { + i_error("Listing Sieve scripts failed: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + return -1; + } + + while ( (scriptname=sieve_storage_list_next(lctx, &active)) + != NULL ) { + doveadm_print(scriptname); + if ( active ) + doveadm_print("ACTIVE"); + else + doveadm_print(""); + } + + if ( sieve_storage_list_deinit(&lctx) < 0 ) { + i_error("Listing Sieve scripts failed: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + return -1; + } + return 0; +} + +static void cmd_sieve_list_init +(struct doveadm_mail_cmd_context *_ctx ATTR_UNUSED, + const char *const args[] ATTR_UNUSED) +{ + doveadm_print_header("script", "script", + DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE); + doveadm_print_header("active", "active", + DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE); +} + +static struct doveadm_mail_cmd_context * +cmd_sieve_list_alloc(void) +{ + struct doveadm_sieve_cmd_context *ctx; + + ctx = doveadm_sieve_cmd_alloc(struct doveadm_sieve_cmd_context); + ctx->ctx.v.init = cmd_sieve_list_init; + ctx->ctx.getopt_args = "s"; + ctx->v.run = cmd_sieve_list_run; + doveadm_print_init(DOVEADM_PRINT_TYPE_FLOW); + return &ctx->ctx; +} + +struct doveadm_cmd_ver2 doveadm_sieve_cmd_list = { + .name = "sieve list", + .mail_cmd = cmd_sieve_list_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX, +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAMS_END +}; + diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-put.c b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-put.c new file mode 100644 index 0000000..ef9472d --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-put.c @@ -0,0 +1,189 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "istream.h" +#include "doveadm-mail.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "doveadm-sieve-cmd.h" + +struct doveadm_sieve_put_cmd_context { + struct doveadm_sieve_cmd_context ctx; + + const char *scriptname; + + bool activate:1; +}; + +static int cmd_sieve_put_run +(struct doveadm_sieve_cmd_context *_ctx) +{ + struct doveadm_sieve_put_cmd_context *ctx = + (struct doveadm_sieve_put_cmd_context *)_ctx; + struct sieve_storage_save_context *save_ctx; + struct sieve_storage *storage = _ctx->storage; + struct istream *input = _ctx->ctx.cmd_input; + enum sieve_error error; + ssize_t ret; + bool save_failed = FALSE; + + save_ctx = sieve_storage_save_init + (storage, ctx->scriptname, input); + if ( save_ctx == NULL ) { + i_error("Saving failed: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + return -1; + } + + while ( (ret = i_stream_read(input)) > 0 || ret == -2 ) { + if ( sieve_storage_save_continue(save_ctx) < 0 ) { + save_failed = TRUE; + ret = -1; + break; + } + } + i_assert(ret == -1); + + if ( input->stream_errno != 0 ) { + i_error("read(script input) failed: %s", i_stream_get_error(input)); + doveadm_sieve_cmd_failed_error + (&ctx->ctx, SIEVE_ERROR_TEMP_FAILURE); + } else if ( save_failed ) { + i_error("Saving failed: %s", + sieve_storage_get_last_error(storage, NULL)); + doveadm_sieve_cmd_failed_storage(&ctx->ctx, storage); + } else if ( sieve_storage_save_finish(save_ctx) < 0 ) { + i_error("Saving failed: %s", + sieve_storage_get_last_error(storage, NULL)); + doveadm_sieve_cmd_failed_storage(&ctx->ctx, storage); + } else { + ret = 0; + } + + /* Verify that script compiles */ + if ( ret == 0 ) { + struct sieve_error_handler *ehandler; + enum sieve_compile_flags cpflags = + SIEVE_COMPILE_FLAG_NOGLOBAL | SIEVE_COMPILE_FLAG_UPLOADED; + struct sieve_script *script; + struct sieve_binary *sbin; + + /* Obtain script object for uploaded script */ + script = sieve_storage_save_get_tempscript(save_ctx); + + /* Check result */ + if ( script == NULL ) { + i_error("Saving failed: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + ret = -1; + + } else { + /* Mark this as an activation when we are replacing the active script */ + if ( ctx->activate || sieve_storage_save_will_activate(save_ctx) ) + cpflags |= SIEVE_COMPILE_FLAG_ACTIVATED; + + /* Compile */ + ehandler = sieve_master_ehandler_create(ctx->ctx.svinst, 0); + if ( (sbin=sieve_compile_script + (script, ehandler, cpflags, &error)) == NULL ) { + doveadm_sieve_cmd_failed_error(_ctx, error); + ret = -1; + } else { + sieve_close(&sbin); + + /* Script is valid; commit it to storage */ + ret = sieve_storage_save_commit(&save_ctx); + if (ret < 0) { + i_error("Saving failed: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + ret = -1; + } + } + sieve_error_handler_unref(&ehandler); + } + } + + if ( save_ctx != NULL ) + sieve_storage_save_cancel(&save_ctx); + + if ( ctx->activate && ret == 0 ) { + struct sieve_script *script = sieve_storage_open_script + (storage, ctx->scriptname, NULL); + if ( script == NULL || + sieve_script_activate(script, (time_t)-1) < 0) { + i_error("Failed to activate Sieve script: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + ret = -1; + } + if (script != NULL) + sieve_script_unref(&script); + } + + i_assert(input->eof); + return ret < 0 ? -1 : 0; +} + +static void cmd_sieve_put_init +(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct doveadm_sieve_put_cmd_context *ctx = + (struct doveadm_sieve_put_cmd_context *)_ctx; + + if ( str_array_length(args) != 1 ) + doveadm_mail_help_name("sieve put"); + doveadm_sieve_cmd_scriptnames_check(args); + + ctx->scriptname = p_strdup(ctx->ctx.ctx.pool, args[0]); + + doveadm_mail_get_input(_ctx); +} + +static bool +cmd_sieve_put_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c) +{ + struct doveadm_sieve_put_cmd_context *ctx = + (struct doveadm_sieve_put_cmd_context *)_ctx; + + switch ( c ) { + case 'a': + ctx->activate = TRUE; + break; + default: + return FALSE; + } + return TRUE; +} + +static struct doveadm_mail_cmd_context * +cmd_sieve_put_alloc(void) +{ + struct doveadm_sieve_put_cmd_context *ctx; + + ctx = doveadm_sieve_cmd_alloc(struct doveadm_sieve_put_cmd_context); + ctx->ctx.ctx.getopt_args = "a"; + ctx->ctx.ctx.v.parse_arg = cmd_sieve_put_parse_arg; + ctx->ctx.ctx.v.init = cmd_sieve_put_init; + ctx->ctx.v.run = cmd_sieve_put_run; + return &ctx->ctx.ctx; +} + +struct doveadm_cmd_ver2 doveadm_sieve_cmd_put = { + .name = "sieve put", + .mail_cmd = cmd_sieve_put_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"[-a] <scriptname>", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('a',"activate",CMD_PARAM_BOOL,0) +DOVEADM_CMD_PARAM('\0',"scriptname",CMD_PARAM_STR,CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAM('\0',"file",CMD_PARAM_ISTREAM,CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-rename.c b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-rename.c new file mode 100644 index 0000000..3cc53c7 --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-rename.c @@ -0,0 +1,83 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "doveadm-mail.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "doveadm-sieve-cmd.h" + +struct doveadm_sieve_rename_cmd_context { + struct doveadm_sieve_cmd_context ctx; + + const char *oldname, *newname; +}; + +static int +cmd_sieve_rename_run(struct doveadm_sieve_cmd_context *_ctx) +{ + struct doveadm_sieve_rename_cmd_context *ctx = + (struct doveadm_sieve_rename_cmd_context *)_ctx; + struct sieve_storage *storage = _ctx->storage; + struct sieve_script *script; + enum sieve_error error; + int ret = 0; + + script = sieve_storage_open_script + (storage, ctx->oldname, NULL); + if ( script == NULL ) { + i_error("Failed to rename Sieve script: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + ret = -1; + } else if ( sieve_script_rename(script, ctx->newname) < 0 ) { + i_error("Failed to rename Sieve script: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + ret = -1; + } + + if ( script != NULL ) + sieve_script_unref(&script); + return ret; +} + +static void cmd_sieve_rename_init +(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct doveadm_sieve_rename_cmd_context *ctx = + (struct doveadm_sieve_rename_cmd_context *)_ctx; + + if ( str_array_length(args) != 2 ) + doveadm_mail_help_name("sieve rename"); + doveadm_sieve_cmd_scriptnames_check(args); + + ctx->oldname = p_strdup(ctx->ctx.ctx.pool, args[0]); + ctx->newname = p_strdup(ctx->ctx.ctx.pool, args[1]); +} + +static struct doveadm_mail_cmd_context * +cmd_sieve_rename_alloc(void) +{ + struct doveadm_sieve_rename_cmd_context *ctx; + + ctx = doveadm_sieve_cmd_alloc(struct doveadm_sieve_rename_cmd_context); + ctx->ctx.ctx.v.init = cmd_sieve_rename_init; + ctx->ctx.v.run = cmd_sieve_rename_run; + return &ctx->ctx.ctx; +} + +struct doveadm_cmd_ver2 doveadm_sieve_cmd_rename = { + .name = "sieve rename", + .mail_cmd = cmd_sieve_rename_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"<oldname> <newname>", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('\0',"oldname",CMD_PARAM_STR,CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAM('\0',"newname",CMD_PARAM_STR,CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd.c b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd.c new file mode 100644 index 0000000..eb9318c --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd.c @@ -0,0 +1,179 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "unichar.h" +#include "mail-storage.h" +#include "doveadm-mail.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "doveadm-sieve-cmd.h" + +void doveadm_sieve_cmd_failed_error +(struct doveadm_sieve_cmd_context *ctx, enum sieve_error error) +{ + struct doveadm_mail_cmd_context *mctx = &ctx->ctx; + int exit_code = 0; + + switch ( error ) { + case SIEVE_ERROR_NONE: + i_unreached(); + return; + case SIEVE_ERROR_TEMP_FAILURE: + exit_code = EX_TEMPFAIL; + break; + case SIEVE_ERROR_NOT_POSSIBLE: + case SIEVE_ERROR_EXISTS: + case SIEVE_ERROR_NOT_VALID: + case SIEVE_ERROR_ACTIVE: + exit_code = DOVEADM_EX_NOTPOSSIBLE; + break; + case SIEVE_ERROR_BAD_PARAMS: + exit_code = EX_USAGE; + break; + case SIEVE_ERROR_NO_PERMISSION: + exit_code = EX_NOPERM; + break; + case SIEVE_ERROR_NO_QUOTA: + exit_code = EX_CANTCREAT; + break; + case SIEVE_ERROR_NOT_FOUND: + exit_code = DOVEADM_EX_NOTFOUND; + break; + default: + i_unreached(); + } + /* tempfail overrides all other exit codes, otherwise use whatever + error happened first */ + if ( mctx->exit_code == 0 || exit_code == EX_TEMPFAIL ) + mctx->exit_code = exit_code; +} + +void doveadm_sieve_cmd_failed_storage +(struct doveadm_sieve_cmd_context *ctx, struct sieve_storage *storage) +{ + enum sieve_error error; + + (void)sieve_storage_get_last_error(storage, &error); + doveadm_sieve_cmd_failed_error(ctx, error); +} + +static const char *doveadm_sieve_cmd_get_setting +(void *context, const char *identifier) +{ + struct doveadm_sieve_cmd_context *ctx = + (struct doveadm_sieve_cmd_context *) context; + + return mail_user_plugin_getenv(ctx->ctx.cur_mail_user, identifier); +} + +static const struct sieve_callbacks sieve_callbacks = { + NULL, + doveadm_sieve_cmd_get_setting +}; + +static bool doveadm_sieve_cmd_parse_arg +(struct doveadm_mail_cmd_context *_ctx ATTR_UNUSED, + int c ATTR_UNUSED) +{ + return FALSE; +} + +void doveadm_sieve_cmd_scriptnames_check(const char *const args[]) +{ + unsigned int i; + + for (i = 0; args[i] != NULL; i++) { + if (!uni_utf8_str_is_valid(args[i])) { + i_fatal_status(EX_DATAERR, + "Sieve script name not valid UTF-8: %s", args[i]); + } + if ( !sieve_script_name_is_valid(args[i]) ) { + i_fatal_status(EX_DATAERR, + "Sieve script name not valid: %s", args[i]); + } + } +} + +static int +doveadm_sieve_cmd_run +(struct doveadm_mail_cmd_context *_ctx, + struct mail_user *user) +{ + struct doveadm_sieve_cmd_context *ctx = + (struct doveadm_sieve_cmd_context *)_ctx; + struct sieve_environment svenv; + enum sieve_error error; + int ret; + + memset((void*)&svenv, 0, sizeof(svenv)); + svenv.username = user->username; + (void)mail_user_get_home(user, &svenv.home_dir); + svenv.base_dir = user->set->base_dir; + svenv.flags = SIEVE_FLAG_HOME_RELATIVE; + + ctx->svinst = sieve_init + (&svenv, &sieve_callbacks, (void *)ctx, user->mail_debug); + + ctx->storage = sieve_storage_create_main + (ctx->svinst, user, SIEVE_STORAGE_FLAG_READWRITE, &error); + if ( ctx->storage == NULL ) { + switch ( error ) { + case SIEVE_ERROR_NOT_POSSIBLE: + error = SIEVE_ERROR_NOT_FOUND; + i_error("Failed to open Sieve storage: " + "Sieve is disabled for this user"); + break; + case SIEVE_ERROR_NOT_FOUND: + i_error("Failed to open Sieve storage: " + "User cannot manage personal Sieve scripts."); + break; + default: + i_error("Failed to open Sieve storage."); + } + doveadm_sieve_cmd_failed_error(ctx, error); + ret = -1; + + } else { + i_assert( ctx->v.run != NULL ); + ret = ctx->v.run(ctx); + sieve_storage_unref(&ctx->storage); + } + + sieve_deinit(&ctx->svinst); + return ret; +} + +struct doveadm_sieve_cmd_context * +doveadm_sieve_cmd_alloc_size(size_t size) +{ + struct doveadm_sieve_cmd_context *ctx; + + ctx = (struct doveadm_sieve_cmd_context *) + doveadm_mail_cmd_alloc_size(size); + ctx->ctx.getopt_args = "s"; + ctx->ctx.v.parse_arg = doveadm_sieve_cmd_parse_arg; + ctx->ctx.v.run = doveadm_sieve_cmd_run; + return ctx; +} + +static struct doveadm_cmd_ver2 *doveadm_sieve_commands[] = { + &doveadm_sieve_cmd_list, + &doveadm_sieve_cmd_get, + &doveadm_sieve_cmd_put, + &doveadm_sieve_cmd_delete, + &doveadm_sieve_cmd_activate, + &doveadm_sieve_cmd_deactivate, + &doveadm_sieve_cmd_rename +}; + +void doveadm_sieve_cmds_init(void) +{ + unsigned int i; + + for (i = 0; i < N_ELEMENTS(doveadm_sieve_commands); i++) + doveadm_cmd_register_ver2(doveadm_sieve_commands[i]); +} diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd.h b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd.h new file mode 100644 index 0000000..1296701 --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd.h @@ -0,0 +1,43 @@ +#ifndef DOVEADM_SIEVE_CMD_H +#define DOVEADM_SIEVE_CMD_H + +struct doveadm_sieve_cmd_context; + +struct doveadm_sieve_cmd_vfuncs { + /* This is the main function which performs all the work for the + command. This is called once per each user. */ + int (*run)(struct doveadm_sieve_cmd_context *ctx); +}; + +struct doveadm_sieve_cmd_context { + struct doveadm_mail_cmd_context ctx; + + struct sieve_instance *svinst; + struct sieve_storage *storage; + + struct doveadm_sieve_cmd_vfuncs v; +}; + +void doveadm_sieve_cmd_failed_error +(struct doveadm_sieve_cmd_context *ctx, enum sieve_error error); +void doveadm_sieve_cmd_failed_storage +(struct doveadm_sieve_cmd_context *ctx, struct sieve_storage *storage); + +#define doveadm_sieve_cmd_alloc(type) \ + (type *)doveadm_sieve_cmd_alloc_size(sizeof(type)) +struct doveadm_sieve_cmd_context * +doveadm_sieve_cmd_alloc_size(size_t size); + +void doveadm_sieve_cmd_scriptnames_check(const char *const args[]); + +extern struct doveadm_cmd_ver2 doveadm_sieve_cmd_list; +extern struct doveadm_cmd_ver2 doveadm_sieve_cmd_get; +extern struct doveadm_cmd_ver2 doveadm_sieve_cmd_put; +extern struct doveadm_cmd_ver2 doveadm_sieve_cmd_delete; +extern struct doveadm_cmd_ver2 doveadm_sieve_cmd_activate; +extern struct doveadm_cmd_ver2 doveadm_sieve_cmd_deactivate; +extern struct doveadm_cmd_ver2 doveadm_sieve_cmd_rename; + +void doveadm_sieve_cmds_init(void); + +#endif diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-plugin.c b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-plugin.c new file mode 100644 index 0000000..0478b55 --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-plugin.c @@ -0,0 +1,24 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "doveadm-mail.h" + +#include "sieve.h" + +#include "doveadm-sieve-cmd.h" +#include "doveadm-sieve-plugin.h" + +const char *doveadm_sieve_plugin_version = DOVECOT_ABI_VERSION; + +void doveadm_sieve_plugin_init(struct module *module) +{ + doveadm_sieve_sync_init(module); + doveadm_sieve_cmds_init(); +} + +void doveadm_sieve_plugin_deinit(void) +{ + /* the hooks array is freed already */ + /*mail_storage_hooks_remove(&doveadm_sieve_mail_storage_hooks);*/ +} diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-plugin.h b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-plugin.h new file mode 100644 index 0000000..6e9446d --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-plugin.h @@ -0,0 +1,17 @@ +#ifndef DOVEADM_SIEVE_PLUGIN_H +#define DOVEADM_SIEVE_PLUGIN_H + +/* + * Plugin interface + */ + +void doveadm_sieve_plugin_init(struct module *module); +void doveadm_sieve_plugin_deinit(void); + +/* + * Replication + */ + +void doveadm_sieve_sync_init(struct module *module); + +#endif diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-sync.c b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-sync.c new file mode 100644 index 0000000..c85a3fc --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-sync.c @@ -0,0 +1,746 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "ioloop.h" +#include "time-util.h" +#include "istream.h" +#include "istream-concat.h" +#include "mail-storage-private.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "doveadm-sieve-plugin.h" + +#define SIEVE_MAIL_CONTEXT(obj) \ + MODULE_CONTEXT_REQUIRE(obj, sieve_storage_module) +#define SIEVE_USER_CONTEXT(obj) \ + MODULE_CONTEXT_REQUIRE(obj, sieve_user_module) + +struct sieve_mail_user { + union mail_user_module_context module_ctx; + + struct sieve_instance *svinst; + struct sieve_storage *sieve_storage; +}; + +struct sieve_mailbox_attribute_iter { + struct mailbox_attribute_iter iter; + struct mailbox_attribute_iter *super; + + struct sieve_storage_list_context *sieve_list; + string_t *name; + + bool failed; + bool have_active; +}; + +static MODULE_CONTEXT_DEFINE_INIT(sieve_storage_module, + &mail_storage_module_register); +static MODULE_CONTEXT_DEFINE_INIT(sieve_user_module, + &mail_user_module_register); + +static const char * +mail_sieve_get_setting(void *context, const char *identifier) +{ + struct mail_user *mail_user = context; + + return mail_user_plugin_getenv(mail_user, identifier); +} + +static const struct sieve_callbacks mail_sieve_callbacks = { + NULL, + mail_sieve_get_setting +}; + +static void mail_sieve_user_deinit(struct mail_user *user) +{ + struct sieve_mail_user *suser = SIEVE_USER_CONTEXT(user); + + if ( suser->svinst != NULL ) { + if (suser->sieve_storage != NULL) + sieve_storage_unref(&suser->sieve_storage); + sieve_deinit(&suser->svinst); + } + + suser->module_ctx.super.deinit(user); +} + +static int +mail_sieve_user_init +(struct mail_user *user, struct sieve_storage **svstorage_r) +{ + struct sieve_mail_user *suser = SIEVE_USER_CONTEXT(user); + enum sieve_storage_flags storage_flags = + SIEVE_STORAGE_FLAG_READWRITE | + SIEVE_STORAGE_FLAG_SYNCHRONIZING; + struct sieve_environment svenv; + + if ( suser->svinst != NULL ) { + *svstorage_r = suser->sieve_storage; + return suser->sieve_storage != NULL ? 1 : 0; + } + + /* Delayed initialization of sieve storage until it's actually needed */ + i_zero(&svenv); + svenv.username = user->username; + (void)mail_user_get_home(user, &svenv.home_dir); + svenv.base_dir = user->set->base_dir; + svenv.flags = SIEVE_FLAG_HOME_RELATIVE; + + suser->svinst = sieve_init(&svenv, &mail_sieve_callbacks, + user, user->mail_debug); + suser->sieve_storage = sieve_storage_create_main + (suser->svinst, user, storage_flags, NULL); + + *svstorage_r = suser->sieve_storage; + return suser->sieve_storage != NULL ? 1 : 0; +} + +static int sieve_attribute_unset_script(struct mail_storage *storage, + struct sieve_storage *svstorage, + const char *scriptname) +{ + struct sieve_script *script; + const char *errstr; + enum sieve_error error; + int ret = 0; + + script = sieve_storage_open_script(svstorage, scriptname, NULL); + if (script == NULL) { + ret = -1; + } else { + ret = sieve_script_delete(script, TRUE); + sieve_script_unref(&script); + } + + if (ret < 0) { + errstr = sieve_storage_get_last_error(svstorage, &error); + if (error == SIEVE_ERROR_NOT_FOUND) { + /* already deleted, ignore */ + return 0; + } + mail_storage_set_critical(storage, + "Failed to delete Sieve script '%s': %s", scriptname, + errstr); + return -1; + } + return 0; +} + +static int +sieve_attribute_set_active(struct mail_storage *storage, + struct sieve_storage *svstorage, + const struct mail_attribute_value *value) +{ + const char *scriptname; + struct sieve_script *script; + time_t last_change = + (value->last_change == 0 ? ioloop_time : value->last_change); + int ret; + + if (mailbox_attribute_value_to_string(storage, value, &scriptname) < 0) + return -1; + + if (scriptname == NULL) { + /* don't affect non-link active script */ + if ((ret=sieve_storage_is_singular(svstorage)) != 0) { + if (ret < 0) { + mail_storage_set_internal_error(storage); + return -1; + } + return 0; + } + + /* deactivate current script */ + if (sieve_storage_deactivate(svstorage, last_change) < 0) { + mail_storage_set_critical(storage, + "Failed to deactivate Sieve: %s", + sieve_storage_get_last_error(svstorage, NULL)); + return -1; + } + return 0; + } + i_assert(scriptname[0] == MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_LINK); + scriptname++; + + /* activate specified script */ + script = sieve_storage_open_script(svstorage, scriptname, NULL); + ret = script == NULL ? -1 : + sieve_script_activate(script, last_change); + if (ret < 0) { + mail_storage_set_critical(storage, + "Failed to activate Sieve script '%s': %s", scriptname, + sieve_storage_get_last_error(svstorage, NULL)); + } + if (script != NULL) + sieve_script_unref(&script); + sieve_storage_set_modified(svstorage, last_change); + return ret; +} + +static int +sieve_attribute_unset_active_script(struct mail_storage *storage, + struct sieve_storage *svstorage, time_t last_change) +{ + int ret; + + if ((ret=sieve_storage_is_singular(svstorage)) != 0) { + if (ret < 0) + mail_storage_set_internal_error(storage); + return ret; + } + + if (sieve_storage_deactivate(svstorage, last_change) < 0) { + mail_storage_set_critical(storage, + "Failed to deactivate sieve: %s", + sieve_storage_get_last_error(svstorage, NULL)); + return -1; + } + return 0; +} + +static int +sieve_attribute_set_active_script(struct mail_storage *storage, + struct sieve_storage *svstorage, + const struct mail_attribute_value *value) +{ + struct istream *input; + time_t last_change = + (value->last_change == 0 ? ioloop_time : value->last_change); + + if (value->value != NULL) { + input = i_stream_create_from_data(value->value, strlen(value->value)); + } else if (value->value_stream != NULL) { + input = value->value_stream; + i_stream_ref(input); + } else { + return sieve_attribute_unset_active_script + (storage, svstorage, last_change); + } + /* skip over the 'S' type */ + i_stream_skip(input, 1); + + if (sieve_storage_save_as_active + (svstorage, input, last_change) < 0) { + mail_storage_set_critical(storage, + "Failed to save active sieve script: %s", + sieve_storage_get_last_error(svstorage, NULL)); + i_stream_unref(&input); + return -1; + } + + sieve_storage_set_modified(svstorage, last_change); + i_stream_unref(&input); + return 0; +} + +static int +sieve_attribute_set_default(struct mail_storage *storage, + struct sieve_storage *svstorage, + const struct mail_attribute_value *value) +{ + const unsigned char *data; + size_t size; + ssize_t ret; + char type; + + if (value->value != NULL) { + type = value->value[0]; + } else if (value->value_stream != NULL) { + ret = i_stream_read_more(value->value_stream, &data, &size); + if (ret == -1) { + mail_storage_set_critical(storage, "read(%s) failed: %m", + i_stream_get_name(value->value_stream)); + return -1; + } + i_assert(ret > 0); + type = data[0]; + } else { + type = MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_SCRIPT; + } + if (type == MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_LINK) + return sieve_attribute_set_active(storage, svstorage, value); + if (type == MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_SCRIPT) + return sieve_attribute_set_active_script(storage, svstorage, value); + mail_storage_set_error(storage, MAIL_ERROR_PARAMS, + "Invalid value for default sieve attribute"); + return -1; +} + +static int +sieve_attribute_set_sieve(struct mail_storage *storage, + const char *key, + const struct mail_attribute_value *value) +{ + struct sieve_storage *svstorage; + struct sieve_storage_save_context *save_ctx; + struct istream *input; + const char *scriptname; + int ret; + + if ((ret = mail_sieve_user_init(storage->user, &svstorage)) <= 0) { + if (ret == 0) { + mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND, + "Sieve not enabled for user"); + } + return -1; + } + + if (strcmp(key, MAILBOX_ATTRIBUTE_SIEVE_DEFAULT) == 0) + return sieve_attribute_set_default(storage, svstorage, value); + if (!str_begins(key, MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES)) { + mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND, + "Nonexistent sieve attribute"); + return -1; + } + scriptname = key + strlen(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES); + + if (value->value != NULL) { + input = i_stream_create_from_data(value->value, + strlen(value->value)); + save_ctx = sieve_storage_save_init(svstorage, scriptname, input); + } else if (value->value_stream != NULL) { + input = value->value_stream; + i_stream_ref(input); + save_ctx = sieve_storage_save_init(svstorage, scriptname, input); + } else { + return sieve_attribute_unset_script(storage, svstorage, scriptname); + } + + if (save_ctx == NULL) { + /* save initialization failed */ + mail_storage_set_critical(storage, + "Failed to save sieve script '%s': %s", scriptname, + sieve_storage_get_last_error(svstorage, NULL)); + i_stream_unref(&input); + return -1; + } + + if (value->last_change != 0) + sieve_storage_save_set_mtime(save_ctx, value->last_change); + + ret = 0; + while (input->stream_errno == 0 && + !i_stream_read_eof(input)) { + if (sieve_storage_save_continue(save_ctx) < 0) { + mail_storage_set_critical(storage, + "Failed to save sieve script '%s': %s", scriptname, + sieve_storage_get_last_error(svstorage, NULL)); + ret = -1; + break; + } + } + if (input->stream_errno != 0) { + errno = input->stream_errno; + mail_storage_set_critical(storage, + "Saving sieve script: read(%s) failed: %m", + i_stream_get_name(input)); + ret = -1; + } + i_assert(input->eof || ret < 0); + if (ret == 0 && sieve_storage_save_finish(save_ctx) < 0) { + mail_storage_set_critical(storage, + "Failed to save sieve script '%s': %s", scriptname, + sieve_storage_get_last_error(svstorage, NULL)); + ret = -1; + } + if (ret < 0) + sieve_storage_save_cancel(&save_ctx); + else if (sieve_storage_save_commit(&save_ctx) < 0) { + mail_storage_set_critical(storage, + "Failed to save sieve script '%s': %s", scriptname, + sieve_storage_get_last_error(svstorage, NULL)); + ret = -1; + } + i_stream_unref(&input); + return ret; +} + +static int +sieve_attribute_set(struct mailbox_transaction_context *t, + enum mail_attribute_type type, const char *key, + const struct mail_attribute_value *value) +{ + struct mail_user *user = t->box->storage->user; + union mailbox_module_context *sbox = SIEVE_MAIL_CONTEXT(t->box); + + if (t->box->storage->user->dsyncing && + type == MAIL_ATTRIBUTE_TYPE_PRIVATE && + str_begins(key, MAILBOX_ATTRIBUTE_PREFIX_SIEVE)) { + time_t ts = + (value->last_change != 0 ? value->last_change : ioloop_time); + + if (sieve_attribute_set_sieve(t->box->storage, key, value) < 0) + return -1; + + if (user->mail_debug) { + const char *change; + if (value->last_change != 0) { + change = t_strflocaltime + ("(last change: %Y-%m-%d %H:%M:%S)", value->last_change); + } else { + change = t_strflocaltime + ("(time: %Y-%m-%d %H:%M:%S)", ioloop_time); + } + i_debug("doveadm-sieve: Assigned value for key `%s' %s", + key, change); + } + + /* FIXME: set value len to sieve script size / active name + length */ + if (value->value != NULL || value->value_stream != NULL) + mail_index_attribute_set(t->itrans, TRUE, key, ts, 0); + else + mail_index_attribute_unset(t->itrans, TRUE, key, ts); + return 0; + } + return sbox->super.attribute_set(t, type, key, value); +} + +static int +sieve_attribute_retrieve_script(struct mail_storage *storage, + struct sieve_storage *svstorage, struct sieve_script *script, + bool add_type_prefix, + struct mail_attribute_value *value_r, const char **errorstr_r) +{ + static char type = MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_SCRIPT; + struct istream *input, *inputs[3]; + const struct stat *st; + enum sieve_error error; + + if (script == NULL) + *errorstr_r = sieve_storage_get_last_error(svstorage, &error); + else if (sieve_script_get_stream(script, &input, &error) < 0) + sieve_script_unref(&script); + + if (script == NULL) { + if (error == SIEVE_ERROR_NOT_FOUND) { + /* already deleted, but return the last_change */ + (void)sieve_storage_get_last_change(svstorage, + &value_r->last_change); + return 0; + } + *errorstr_r = sieve_storage_get_last_error(svstorage, &error); + return -1; + } + if (i_stream_stat(input, FALSE, &st) < 0) { + mail_storage_set_critical(storage, + "stat(%s) failed: %m", i_stream_get_name(input)); + } else { + value_r->last_change = st->st_mtime; + } + if (!add_type_prefix) { + i_stream_ref(input); + value_r->value_stream = input; + } else { + inputs[0] = i_stream_create_from_data(&type, 1); + inputs[1] = input; + inputs[2] = NULL; + value_r->value_stream = i_stream_create_concat(inputs); + i_stream_unref(&inputs[0]); + } + sieve_script_unref(&script); + return 1; +} + +static int +sieve_attribute_get_active_script(struct mail_storage *storage, + struct sieve_storage *svstorage, + struct mail_attribute_value *value_r) +{ + struct sieve_script *script; + const char *errstr; + int ret; + + if ((ret=sieve_storage_is_singular(svstorage)) <= 0) { + if (ret == 0 && sieve_storage_active_script_get_last_change + (svstorage, &value_r->last_change) < 0) { + ret = -1; + } + if (ret < 0) + mail_storage_set_internal_error(storage); + return ret; + } + + if ((script=sieve_storage_active_script_open + (svstorage, NULL)) == NULL) + return 0; + + if ((ret=sieve_attribute_retrieve_script + (storage, svstorage, script, TRUE, value_r, &errstr)) < 0) { + mail_storage_set_critical(storage, + "Failed to access active sieve script: %s", errstr); + } + return ret; +} + +static int +sieve_attribute_get_default(struct mail_storage *storage, + struct sieve_storage *svstorage, + struct mail_attribute_value *value_r) +{ + const char *scriptname; + int ret; + + ret = sieve_storage_active_script_get_name(svstorage, &scriptname); + if (ret == 0) + return sieve_attribute_get_active_script(storage, svstorage, value_r); + + if (ret > 0) { + value_r->value = t_strdup_printf("%c%s", + MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_LINK, scriptname); + if (sieve_storage_active_script_get_last_change + (svstorage, &value_r->last_change) < 0) + ret = -1; + } + if (ret < 0) + mail_storage_set_internal_error(storage); + return ret; +} + +static int +sieve_attribute_get_sieve(struct mail_storage *storage, const char *key, + struct mail_attribute_value *value_r) +{ + struct sieve_storage *svstorage; + struct sieve_script *script; + const char *scriptname, *errstr; + int ret; + + if ((ret = mail_sieve_user_init(storage->user, &svstorage)) <= 0) + return ret; + + if (strcmp(key, MAILBOX_ATTRIBUTE_SIEVE_DEFAULT) == 0) + return sieve_attribute_get_default(storage, svstorage, value_r); + if (!str_begins(key, MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES)) + return 0; + if ((value_r->flags & MAIL_ATTRIBUTE_VALUE_FLAG_INT_STREAMS) == 0) { + mail_storage_set_error(storage, MAIL_ERROR_PARAMS, + "Sieve attributes are available only as streams"); + return -1; + } + scriptname = key + strlen(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES); + script = sieve_storage_open_script(svstorage, scriptname, NULL); + if ((ret=sieve_attribute_retrieve_script + (storage, svstorage, script, FALSE, value_r, &errstr)) < 0) { + mail_storage_set_critical(storage, + "Failed to access sieve script '%s': %s", + scriptname, errstr); + } + return ret; +} + +static int +sieve_attribute_get(struct mailbox *box, + enum mail_attribute_type type, const char *key, + struct mail_attribute_value *value_r) +{ + union mailbox_module_context *sbox = SIEVE_MAIL_CONTEXT(box); + struct mail_user *user = box->storage->user; + int ret; + + if (box->storage->user->dsyncing && + type == MAIL_ATTRIBUTE_TYPE_PRIVATE && + str_begins(key, MAILBOX_ATTRIBUTE_PREFIX_SIEVE)) { + + ret = sieve_attribute_get_sieve(box->storage, key, value_r); + if (ret >= 0 && user->mail_debug) { + struct tm *tm = localtime(&value_r->last_change); + char str[256]; + const char *timestamp = ""; + + if (strftime(str, sizeof(str), + " (last change: %Y-%m-%d %H:%M:%S)", tm) > 0) + timestamp = str; + + if (ret > 0) { + i_debug("doveadm-sieve: Retrieved value for key `%s'%s", + key, timestamp); + } else { + i_debug("doveadm-sieve: Value missing for key `%s'%s", + key, timestamp); + } + } + return ret; + } + return sbox->super.attribute_get(box, type, key, value_r); +} + +static int +sieve_attribute_iter_script_init(struct sieve_mailbox_attribute_iter *siter) +{ + struct mail_user *user = siter->iter.box->storage->user; + struct sieve_storage *svstorage; + int ret; + + if (user->mail_debug) + i_debug("doveadm-sieve: Iterating Sieve mailbox attributes"); + + if ((ret = mail_sieve_user_init(user, &svstorage)) <= 0) + return ret; + + siter->sieve_list = sieve_storage_list_init(svstorage); + if (siter->sieve_list == NULL) { + mail_storage_set_critical(siter->iter.box->storage, + "Failed to iterate sieve scripts: %s", + sieve_storage_get_last_error(svstorage, NULL)); + return -1; + } + siter->name = str_new(default_pool, 128); + str_append(siter->name, MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES); + return 0; +} + +static struct mailbox_attribute_iter * +sieve_attribute_iter_init(struct mailbox *box, enum mail_attribute_type type, + const char *prefix) +{ + union mailbox_module_context *sbox = SIEVE_MAIL_CONTEXT(box); + struct sieve_mailbox_attribute_iter *siter; + + siter = i_new(struct sieve_mailbox_attribute_iter, 1); + siter->iter.box = box; + siter->super = sbox->super.attribute_iter_init(box, type, prefix); + + if (box->storage->user->dsyncing && + type == MAIL_ATTRIBUTE_TYPE_PRIVATE) { + if (sieve_attribute_iter_script_init(siter) < 0) + siter->failed = TRUE; + } + return &siter->iter; +} + +static const char * +sieve_attribute_iter_next_script(struct sieve_mailbox_attribute_iter *siter) +{ + struct mail_user *user = siter->iter.box->storage->user; + struct sieve_mail_user *suser = SIEVE_USER_CONTEXT(user); + struct sieve_storage *svstorage = suser->sieve_storage; + const char *scriptname; + bool active; + int ret; + + if (siter->sieve_list == NULL) + return NULL; + + /* Iterate through all scripts in sieve_dir */ + while ((scriptname = sieve_storage_list_next(siter->sieve_list, &active)) + != NULL) { + if (active) + siter->have_active = TRUE; + str_truncate(siter->name, strlen(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES)); + str_append(siter->name, scriptname); + return str_c(siter->name); + } + if (sieve_storage_list_deinit(&siter->sieve_list) < 0) { + mail_storage_set_critical(siter->iter.box->storage, + "Failed to iterate sieve scripts: %s", + sieve_storage_get_last_error(svstorage, NULL)); + siter->failed = TRUE; + return NULL; + } + + /* Check whether active script is a proper symlink or a regular file */ + if ((ret=sieve_storage_is_singular(svstorage)) < 0) { + mail_storage_set_critical(siter->iter.box->storage, + "Failed to iterate sieve scripts: %s", + sieve_storage_get_last_error(svstorage, NULL)); + return NULL; + } + + /* Regular file */ + if (ret > 0) + return MAILBOX_ATTRIBUTE_SIEVE_DEFAULT; + + /* Symlink or none active */ + return siter->have_active ? MAILBOX_ATTRIBUTE_SIEVE_DEFAULT : NULL; +} + +static const char * +sieve_attribute_iter_next(struct mailbox_attribute_iter *iter) +{ + struct sieve_mailbox_attribute_iter *siter = + (struct sieve_mailbox_attribute_iter *)iter; + union mailbox_module_context *sbox = SIEVE_MAIL_CONTEXT(iter->box); + struct mail_user *user = iter->box->storage->user; + const char *key; + + if (siter->sieve_list != NULL) { + if ((key = sieve_attribute_iter_next_script(siter)) != NULL) { + if (user->mail_debug) { + i_debug("doveadm-sieve: Iterating Sieve mailbox attribute: %s", key); + } + return key; + } + } + return sbox->super.attribute_iter_next(siter->super); +} + +static int +sieve_attribute_iter_deinit(struct mailbox_attribute_iter *iter) +{ + struct sieve_mailbox_attribute_iter *siter = + (struct sieve_mailbox_attribute_iter *)iter; + union mailbox_module_context *sbox = SIEVE_MAIL_CONTEXT(iter->box); + int ret = siter->failed ? -1 : 0; + + if (siter->super != NULL) { + if (sbox->super.attribute_iter_deinit(siter->super) < 0) + ret = -1; + } + if (siter->sieve_list != NULL) + (void)sieve_storage_list_deinit(&siter->sieve_list); + if (siter->name != NULL) + str_free(&siter->name); + i_free(siter); + return ret; +} + +static void +sieve_mail_user_created(struct mail_user *user) +{ + struct sieve_mail_user *suser; + struct mail_user_vfuncs *v = user->vlast; + + suser = p_new(user->pool, struct sieve_mail_user, 1); + suser->module_ctx.super = *v; + user->vlast = &suser->module_ctx.super; + v->deinit = mail_sieve_user_deinit; + MODULE_CONTEXT_SET(user, sieve_user_module, suser); +} + +static void +sieve_mailbox_allocated(struct mailbox *box) +{ + struct mailbox_vfuncs *v = box->vlast; + union mailbox_module_context *sbox; + + /* attribute syncing is done via INBOX */ + if (!box->inbox_user) + return; + + sbox = p_new(box->pool, union mailbox_module_context, 1); + sbox->super = *v; + box->vlast = &sbox->super; + v->attribute_set = sieve_attribute_set; + v->attribute_get = sieve_attribute_get; + v->attribute_iter_init = sieve_attribute_iter_init; + v->attribute_iter_next = sieve_attribute_iter_next; + v->attribute_iter_deinit = sieve_attribute_iter_deinit; + MODULE_CONTEXT_SET_SELF(box, sieve_storage_module, sbox); +} + +static struct mail_storage_hooks doveadm_sieve_mail_storage_hooks = { + .mail_user_created = sieve_mail_user_created, + .mailbox_allocated = sieve_mailbox_allocated +}; + +void doveadm_sieve_sync_init(struct module *module) +{ + mail_storage_hooks_add_forced + (module, &doveadm_sieve_mail_storage_hooks); +} diff --git a/pigeonhole/src/plugins/imap-filter-sieve/Makefile.am b/pigeonhole/src/plugins/imap-filter-sieve/Makefile.am new file mode 100644 index 0000000..915e128 --- /dev/null +++ b/pigeonhole/src/plugins/imap-filter-sieve/Makefile.am @@ -0,0 +1,26 @@ +imap_moduledir = $(dovecot_moduledir) + +imap_module_LTLIBRARIES = lib95_imap_filter_sieve_plugin.la + +lib95_imap_filter_sieve_plugin_la_LDFLAGS = -module -avoid-version + +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + $(LIBDOVECOT_IMAP_INCLUDE) \ + $(LIBDOVECOT_LDA_INCLUDE) \ + $(LIBDOVECOT_INCLUDE) \ + -DPKG_RUNDIR=\""$(rundir)"\" + +lib95_imap_filter_sieve_plugin_la_SOURCES = \ + cmd-filter.c \ + cmd-filter-sieve.c \ + imap-filter.c \ + imap-filter-sieve.c \ + imap-filter-sieve-plugin.c +lib95_imap_filter_sieve_plugin_la_LIBADD = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la + +noinst_HEADERS = \ + imap-filter.h \ + imap-filter-sieve.h \ + imap-filter-sieve-plugin.h diff --git a/pigeonhole/src/plugins/imap-filter-sieve/Makefile.in b/pigeonhole/src/plugins/imap-filter-sieve/Makefile.in new file mode 100644 index 0000000..b74a15b --- /dev/null +++ b/pigeonhole/src/plugins/imap-filter-sieve/Makefile.in @@ -0,0 +1,771 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/plugins/imap-filter-sieve +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(imap_moduledir)" +LTLIBRARIES = $(imap_module_LTLIBRARIES) +lib95_imap_filter_sieve_plugin_la_DEPENDENCIES = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la +am_lib95_imap_filter_sieve_plugin_la_OBJECTS = cmd-filter.lo \ + cmd-filter-sieve.lo imap-filter.lo imap-filter-sieve.lo \ + imap-filter-sieve-plugin.lo +lib95_imap_filter_sieve_plugin_la_OBJECTS = \ + $(am_lib95_imap_filter_sieve_plugin_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +lib95_imap_filter_sieve_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) \ + --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ + $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(lib95_imap_filter_sieve_plugin_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/cmd-filter-sieve.Plo \ + ./$(DEPDIR)/cmd-filter.Plo \ + ./$(DEPDIR)/imap-filter-sieve-plugin.Plo \ + ./$(DEPDIR)/imap-filter-sieve.Plo ./$(DEPDIR)/imap-filter.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(lib95_imap_filter_sieve_plugin_la_SOURCES) +DIST_SOURCES = $(lib95_imap_filter_sieve_plugin_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +imap_moduledir = $(dovecot_moduledir) +imap_module_LTLIBRARIES = lib95_imap_filter_sieve_plugin.la +lib95_imap_filter_sieve_plugin_la_LDFLAGS = -module -avoid-version +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + $(LIBDOVECOT_IMAP_INCLUDE) \ + $(LIBDOVECOT_LDA_INCLUDE) \ + $(LIBDOVECOT_INCLUDE) \ + -DPKG_RUNDIR=\""$(rundir)"\" + +lib95_imap_filter_sieve_plugin_la_SOURCES = \ + cmd-filter.c \ + cmd-filter-sieve.c \ + imap-filter.c \ + imap-filter-sieve.c \ + imap-filter-sieve-plugin.c + +lib95_imap_filter_sieve_plugin_la_LIBADD = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la + +noinst_HEADERS = \ + imap-filter.h \ + imap-filter-sieve.h \ + imap-filter-sieve-plugin.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/imap-filter-sieve/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/plugins/imap-filter-sieve/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-imap_moduleLTLIBRARIES: $(imap_module_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(imap_module_LTLIBRARIES)'; test -n "$(imap_moduledir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(imap_moduledir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(imap_moduledir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(imap_moduledir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(imap_moduledir)"; \ + } + +uninstall-imap_moduleLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(imap_module_LTLIBRARIES)'; test -n "$(imap_moduledir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(imap_moduledir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(imap_moduledir)/$$f"; \ + done + +clean-imap_moduleLTLIBRARIES: + -test -z "$(imap_module_LTLIBRARIES)" || rm -f $(imap_module_LTLIBRARIES) + @list='$(imap_module_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +lib95_imap_filter_sieve_plugin.la: $(lib95_imap_filter_sieve_plugin_la_OBJECTS) $(lib95_imap_filter_sieve_plugin_la_DEPENDENCIES) $(EXTRA_lib95_imap_filter_sieve_plugin_la_DEPENDENCIES) + $(AM_V_CCLD)$(lib95_imap_filter_sieve_plugin_la_LINK) -rpath $(imap_moduledir) $(lib95_imap_filter_sieve_plugin_la_OBJECTS) $(lib95_imap_filter_sieve_plugin_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-filter-sieve.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-filter.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imap-filter-sieve-plugin.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imap-filter-sieve.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imap-filter.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(imap_moduledir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-imap_moduleLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-filter-sieve.Plo + -rm -f ./$(DEPDIR)/cmd-filter.Plo + -rm -f ./$(DEPDIR)/imap-filter-sieve-plugin.Plo + -rm -f ./$(DEPDIR)/imap-filter-sieve.Plo + -rm -f ./$(DEPDIR)/imap-filter.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-imap_moduleLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/cmd-filter-sieve.Plo + -rm -f ./$(DEPDIR)/cmd-filter.Plo + -rm -f ./$(DEPDIR)/imap-filter-sieve-plugin.Plo + -rm -f ./$(DEPDIR)/imap-filter-sieve.Plo + -rm -f ./$(DEPDIR)/imap-filter.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-imap_moduleLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-imap_moduleLTLIBRARIES clean-libtool \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-imap_moduleLTLIBRARIES install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-imap_moduleLTLIBRARIES + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/plugins/imap-filter-sieve/cmd-filter-sieve.c b/pigeonhole/src/plugins/imap-filter-sieve/cmd-filter-sieve.c new file mode 100644 index 0000000..6b96bd3 --- /dev/null +++ b/pigeonhole/src/plugins/imap-filter-sieve/cmd-filter-sieve.c @@ -0,0 +1,403 @@ +/* Copyright (c) 2017-2018 Pigeonhole authors, see the included COPYING file */ + +#include "imap-common.h" +#include "str.h" +#include "istream.h" +#include "istream-seekable.h" +#include "ostream.h" +#include "imap-commands.h" + +#include "imap-filter.h" +#include "imap-filter-sieve.h" + +#define FILTER_MAX_INMEM_SIZE (1024*128) + +static int cmd_filter_sieve_compile_script(struct imap_filter_context *ctx) +{ + struct client_command_context *cmd = ctx->cmd; + struct imap_filter_sieve_context *sctx = ctx->sieve; + struct client *client = cmd->client; + string_t *errors = NULL; + bool have_warnings = FALSE; + int ret = 0; + + ret = imap_filter_sieve_compile(sctx, &errors, &have_warnings); + if (ret >= 0 && !have_warnings) + return 0; + + o_stream_nsend_str(client->output, + t_strdup_printf("* FILTER (TAG %s) " + "%s {%zu}\r\n", + cmd->tag, (ret < 0 ? "ERRORS" : "WARNINGS"), + str_len(errors))); + o_stream_nsend(client->output, + str_data(errors), str_len(errors)); + o_stream_nsend_str(client->output, "\r\n"); + + if (ret < 0) { + ctx->compile_failure = TRUE; + ctx->failed = TRUE; + return -1; + } + return 0; +} + +static bool cmd_filter_sieve_delivery(struct client_command_context *cmd) +{ + struct imap_filter_context *ctx = cmd->context; + struct client *client = cmd->client; + struct imap_filter_sieve_context *sctx = ctx->sieve; + enum mail_error error; + const char *error_string; + int ret; + + if (cmd->cancel) { + imap_filter_deinit(ctx); + return TRUE; + } + + i_assert(sctx->filter_type == IMAP_FILTER_SIEVE_TYPE_DELIVERY); + ret = imap_filter_sieve_open_personal(sctx, NULL, + &error, &error_string); + if (ret < 0) { + client_send_tagline( + cmd, imap_get_error_string(cmd, error_string, error)); + imap_filter_deinit(ctx); + return TRUE; + } + if (cmd_filter_sieve_compile_script(ctx) < 0) { + client_send_tagline(cmd, "NO Failed to compile Sieve script"); + client->input_skip_line = TRUE; + imap_filter_deinit(ctx); + return TRUE; + } + + imap_parser_reset(ctx->parser); + cmd->func = imap_filter_search; + return imap_filter_search(cmd); +} + +static int +cmd_filter_sieve_script_parse_name_arg(struct imap_filter_context *ctx) +{ + struct client_command_context *cmd = ctx->cmd; + const struct imap_arg *args; + const char *error; + enum imap_parser_error parse_error; + int ret; + + ret = imap_parser_read_args(ctx->parser, 1, 0, &args); + if (ret < 0) { + if (ret == -2) + return 0; + error = imap_parser_get_error(ctx->parser, &parse_error); + switch (parse_error) { + case IMAP_PARSE_ERROR_NONE: + i_unreached(); + case IMAP_PARSE_ERROR_LITERAL_TOO_BIG: + client_disconnect_with_error(ctx->cmd->client, error); + break; + default: + client_send_command_error(ctx->cmd, error); + break; + } + return -1; + } + + switch (args[0].type) { + case IMAP_ARG_EOL: + client_send_command_error(ctx->cmd, "Script name missing"); + return -1; + case IMAP_ARG_NIL: + case IMAP_ARG_LIST: + client_send_command_error( + ctx->cmd, "Script name must be an atom or a string"); + return -1; + case IMAP_ARG_ATOM: + case IMAP_ARG_STRING: + /* We have the value already */ + if (ctx->failed) + return 1; + ctx->script_name = p_strdup(cmd->pool, + imap_arg_as_astring(&args[0])); + break; + case IMAP_ARG_LITERAL: + case IMAP_ARG_LITERAL_SIZE: + case IMAP_ARG_LITERAL_SIZE_NONSYNC: + i_unreached(); + } + return 1; +} + +static bool +cmd_filter_sieve_script_parse_name(struct client_command_context *cmd) +{ + struct imap_filter_context *ctx = cmd->context; + struct client *client = cmd->client; + struct imap_filter_sieve_context *sctx = ctx->sieve; + enum mail_error error; + const char *error_string; + int ret; + + if (cmd->cancel) { + imap_filter_deinit(ctx); + return TRUE; + } + + if ((ret = cmd_filter_sieve_script_parse_name_arg(ctx)) == 0) + return FALSE; + if (ret < 0) { + /* Already sent the error to client */ + imap_filter_deinit(ctx); + return TRUE; + } + + switch (sctx->filter_type) { + case IMAP_FILTER_SIEVE_TYPE_PERSONAL: + ret = imap_filter_sieve_open_personal(sctx, ctx->script_name, + &error, &error_string); + break; + case IMAP_FILTER_SIEVE_TYPE_GLOBAL: + ret = imap_filter_sieve_open_global(sctx, ctx->script_name, + &error, &error_string); + break; + case IMAP_FILTER_SIEVE_TYPE_DELIVERY: + case IMAP_FILTER_SIEVE_TYPE_SCRIPT: + i_unreached(); + } + if (ret < 0) { + client_send_tagline( + cmd, imap_get_error_string(cmd, error_string, error)); + imap_filter_deinit(ctx); + return TRUE; + } + if (cmd_filter_sieve_compile_script(ctx) < 0) { + client_send_tagline(cmd, "NO Failed to compile Sieve script"); + client->input_skip_line = TRUE; + imap_filter_deinit(ctx); + return TRUE; + } + + imap_parser_reset(ctx->parser); + cmd->func = imap_filter_search; + return imap_filter_search(cmd); +} + +static void +cmd_filter_sieve_compile_input(struct imap_filter_context *ctx, + struct istream *input) +{ + struct imap_filter_sieve_context *sctx = ctx->sieve; + + imap_filter_sieve_open_input(sctx, input); + (void)cmd_filter_sieve_compile_script(ctx); +} + +static int cmd_filter_sieve_script_read_stream(struct imap_filter_context *ctx) +{ + struct istream *input = ctx->script_input; + const unsigned char *data; + size_t size; + int ret; + + while ((ret = i_stream_read_more(input, &data, &size)) > 0) + i_stream_skip(input, size); + if (ret == 0) + return 0; + + if (input->v_offset != ctx->script_len) { + /* Client disconnected */ + i_assert(input->eof); + return -1; + } + /* Finished reading the value */ + i_stream_seek(input, 0); + + if (ctx->failed) { + i_stream_unref(&ctx->script_input); + return 1; + } + + cmd_filter_sieve_compile_input(ctx, ctx->script_input); + i_stream_unref(&ctx->script_input); + return 1; +} + +static int +cmd_filter_sieve_script_parse_value_arg(struct imap_filter_context *ctx) +{ + const struct imap_arg *args; + const char *value, *error; + enum imap_parser_error parse_error; + struct istream *input, *inputs[2]; + string_t *path; + int ret; + + ret = imap_parser_read_args(ctx->parser, 1, + IMAP_PARSE_FLAG_LITERAL_SIZE | + IMAP_PARSE_FLAG_LITERAL8, &args); + if (ret < 0) { + if (ret == -2) + return 0; + error = imap_parser_get_error(ctx->parser, &parse_error); + switch (parse_error) { + case IMAP_PARSE_ERROR_NONE: + i_unreached(); + case IMAP_PARSE_ERROR_LITERAL_TOO_BIG: + client_disconnect_with_error(ctx->cmd->client, error); + break; + default: + client_send_command_error(ctx->cmd, error); + break; + } + return -1; + } + + switch (args[0].type) { + case IMAP_ARG_EOL: + client_send_command_error(ctx->cmd, "Script value missing"); + return -1; + case IMAP_ARG_NIL: + case IMAP_ARG_ATOM: + case IMAP_ARG_LIST: + client_send_command_error(ctx->cmd, + "Script value must be a string"); + return -1; + case IMAP_ARG_STRING: + /* We have the value already */ + if (ctx->failed) + return 1; + value = imap_arg_as_astring(&args[0]); + input = i_stream_create_from_data(value, strlen(value)); + cmd_filter_sieve_compile_input(ctx, input); + i_stream_unref(&input); + return 1; + case IMAP_ARG_LITERAL_SIZE: + o_stream_nsend(ctx->cmd->client->output, "+ OK\r\n", 6); + o_stream_uncork(ctx->cmd->client->output); + o_stream_cork(ctx->cmd->client->output); + /* Fall through */ + case IMAP_ARG_LITERAL_SIZE_NONSYNC: + ctx->script_len = imap_arg_as_literal_size(&args[0]); + + inputs[0] = i_stream_create_limit(ctx->cmd->client->input, + ctx->script_len); + inputs[1] = NULL; + + path = t_str_new(128); + mail_user_set_get_temp_prefix(path, + ctx->cmd->client->user->set); + ctx->script_input = i_stream_create_seekable_path( + inputs, FILTER_MAX_INMEM_SIZE, str_c(path)); + i_stream_set_name(ctx->script_input, + i_stream_get_name(inputs[0])); + i_stream_unref(&inputs[0]); + break; + case IMAP_ARG_LITERAL: + i_unreached(); + } + return cmd_filter_sieve_script_read_stream(ctx); +} + +static bool +cmd_filter_sieve_script_parse_value(struct client_command_context *cmd) +{ + struct imap_filter_context *ctx = cmd->context; + struct client *client = cmd->client; + int ret; + + if (cmd->cancel) { + imap_filter_deinit(ctx); + return TRUE; + } + + if (ctx->script_input != NULL) { + if ((ret = cmd_filter_sieve_script_read_stream(ctx)) == 0) + return FALSE; + } else { + if ((ret = cmd_filter_sieve_script_parse_value_arg(ctx)) == 0) + return FALSE; + } + + if (ret < 0) { + /* Already sent the error to client */ ; + imap_filter_deinit(ctx); + return TRUE; + } else if (ctx->compile_failure) { + client_send_tagline(cmd, "NO Failed to compile Sieve script"); + client->input_skip_line = TRUE; + imap_filter_deinit(ctx); + return TRUE; + } + + imap_parser_reset(ctx->parser); + cmd->func = imap_filter_search; + return imap_filter_search(cmd); +} + +bool cmd_filter_sieve(struct client_command_context *cmd) +{ + struct imap_filter_context *ctx = cmd->context; + struct client *client = cmd->client; + enum imap_filter_sieve_type type; + const struct imap_arg *args; + const char *sieve_type; + + if (!client_read_args(cmd, 2, 0, &args)) + return FALSE; + args++; + + /* sieve-type */ + if (IMAP_ARG_IS_EOL(args)) { + client_send_command_error( + cmd, "Missing SIEVE filter sub-type."); + return TRUE; + } + if (!imap_arg_get_atom(args, &sieve_type)) { + client_send_command_error( + cmd, "SIEVE filter sub-type is not an atom."); + return TRUE; + } + if (strcasecmp(sieve_type, "DELIVERY") == 0) { + type = IMAP_FILTER_SIEVE_TYPE_DELIVERY; + } else if (strcasecmp(sieve_type, "PERSONAL") == 0) { + type = IMAP_FILTER_SIEVE_TYPE_PERSONAL; + } else if (strcasecmp(sieve_type, "GLOBAL") == 0) { + type = IMAP_FILTER_SIEVE_TYPE_GLOBAL; + } else if (strcasecmp(sieve_type, "SCRIPT") == 0) { + type = IMAP_FILTER_SIEVE_TYPE_SCRIPT; + } else { + client_send_command_error(cmd, t_strdup_printf( + "Unknown SIEVE filter sub-type `%s'", + sieve_type)); + return TRUE; + } + + ctx->sieve = imap_filter_sieve_context_create(ctx, type); + + /* We support large scripts, so read the values from client + asynchronously the same way as APPEND does. */ + client->input_lock = cmd; + ctx->parser = imap_parser_create(client->input, client->output, + client->set->imap_max_line_length); + if (client->set->imap_literal_minus) + imap_parser_enable_literal_minus(ctx->parser); + o_stream_unset_flush_callback(client->output); + + switch (type) { + case IMAP_FILTER_SIEVE_TYPE_DELIVERY: + cmd->func = cmd_filter_sieve_delivery; + break; + case IMAP_FILTER_SIEVE_TYPE_PERSONAL: + cmd->func = cmd_filter_sieve_script_parse_name; + break; + case IMAP_FILTER_SIEVE_TYPE_GLOBAL: + cmd->func = cmd_filter_sieve_script_parse_name; + break; + case IMAP_FILTER_SIEVE_TYPE_SCRIPT: + cmd->func = cmd_filter_sieve_script_parse_value; + break; + } + cmd->context = ctx; + return cmd->func(cmd); +} diff --git a/pigeonhole/src/plugins/imap-filter-sieve/cmd-filter.c b/pigeonhole/src/plugins/imap-filter-sieve/cmd-filter.c new file mode 100644 index 0000000..2458047 --- /dev/null +++ b/pigeonhole/src/plugins/imap-filter-sieve/cmd-filter.c @@ -0,0 +1,57 @@ +/* Copyright (c) 2017-2018 Pigeonhole authors, see the included COPYING file */ + +#include "imap-common.h" + +#include "imap-filter.h" +#include "imap-filter-sieve.h" + +static bool +cmd_filter_parse_spec(struct imap_filter_context *ctx, + const struct imap_arg **_args) +{ + const struct imap_arg *args = *_args; + struct client_command_context *cmd = ctx->cmd; + const char *filter_type; + + /* filter-type */ + if (IMAP_ARG_IS_EOL(args)) { + client_send_command_error(cmd, + "Missing filter type."); + return TRUE; + } + if (!imap_arg_get_atom(args, &filter_type)) { + client_send_command_error(cmd, + "Filter type is not an atom."); + return TRUE; + } + if (strcasecmp(filter_type, "SIEVE") != 0) { + client_send_command_error(cmd, t_strdup_printf( + "Unknown filter type `%s'", filter_type)); + return TRUE; + } + + cmd->func = cmd_filter_sieve; + cmd->context = ctx; + return cmd_filter_sieve(cmd); +} + +bool cmd_filter(struct client_command_context *cmd) +{ + struct imap_filter_context *ctx; + const struct imap_arg *args; + + if (!client_read_args(cmd, 1, 0, &args)) + return FALSE; + + if (!client_verify_open_mailbox(cmd)) + return TRUE; + + ctx = p_new(cmd->pool, struct imap_filter_context, 1); + ctx->cmd = cmd; + + if (!cmd_filter_parse_spec(ctx, &args)) + return FALSE; + + imap_filter_context_free(ctx); + return TRUE; +} diff --git a/pigeonhole/src/plugins/imap-filter-sieve/imap-filter-sieve-plugin.c b/pigeonhole/src/plugins/imap-filter-sieve/imap-filter-sieve-plugin.c new file mode 100644 index 0000000..3021dbe --- /dev/null +++ b/pigeonhole/src/plugins/imap-filter-sieve/imap-filter-sieve-plugin.c @@ -0,0 +1,56 @@ +/* Copyright (c) 2017-2018 Pigeonhole authors, see the included COPYING file */ + +#include "imap-common.h" +#include "str.h" + +#include "imap-filter-sieve.h" +#include "imap-filter-sieve-plugin.h" + +static struct module *imap_filter_sieve_module; +static imap_client_created_func_t *next_hook_client_created; + +/* + * Client + */ + +static void imap_filter_sieve_plugin_client_created(struct client **clientp) +{ + struct client *client = *clientp; + struct mail_user *user = client->user; + + if (mail_user_is_plugin_loaded(user, imap_filter_sieve_module)) { + client_add_capability(client, "FILTER=SIEVE"); + + imap_filter_sieve_client_created(client); + } + + if (next_hook_client_created != NULL) + next_hook_client_created(clientp); +} + +/* + * Plugin + */ + +const char *imap_filter_sieve_plugin_version = DOVECOT_ABI_VERSION; +const char imap_filter_sieve_plugin_binary_dependency[] = "imap"; + +void imap_filter_sieve_plugin_init(struct module *module) +{ + command_register("FILTER", cmd_filter, COMMAND_FLAG_USES_SEQS); + command_register("UID FILTER", cmd_filter, COMMAND_FLAG_BREAKS_SEQS); + + imap_filter_sieve_module = module; + next_hook_client_created = imap_client_created_hook_set( + imap_filter_sieve_plugin_client_created); + imap_filter_sieve_init(module); +} + +void imap_filter_sieve_plugin_deinit(void) +{ + command_unregister("FILTER"); + command_unregister("UID FILTER"); + + imap_filter_sieve_deinit(); + imap_client_created_hook_set(next_hook_client_created); +} diff --git a/pigeonhole/src/plugins/imap-filter-sieve/imap-filter-sieve-plugin.h b/pigeonhole/src/plugins/imap-filter-sieve/imap-filter-sieve-plugin.h new file mode 100644 index 0000000..59b4b11 --- /dev/null +++ b/pigeonhole/src/plugins/imap-filter-sieve/imap-filter-sieve-plugin.h @@ -0,0 +1,16 @@ +/* Copyright (c) 2017-2018 Pigeonhole authors, see the included COPYING file + */ + +#ifndef IMAP_FILTER_SIEVE_PLUGIN_H +#define IMAP_FILTER_SIEVE_PLUGIN_H + +struct module; + +extern const char imap_filter_sieve_plugin_binary_dependency[]; + +bool cmd_filter(struct client_command_context *cmd); + +void imap_filter_sieve_plugin_init(struct module *module); +void imap_filter_sieve_plugin_deinit(void); + +#endif diff --git a/pigeonhole/src/plugins/imap-filter-sieve/imap-filter-sieve.c b/pigeonhole/src/plugins/imap-filter-sieve/imap-filter-sieve.c new file mode 100644 index 0000000..62519f4 --- /dev/null +++ b/pigeonhole/src/plugins/imap-filter-sieve/imap-filter-sieve.c @@ -0,0 +1,1188 @@ +/* Copyright (c) 2017-2018 Pigeonhole authors, see the included COPYING file */ + +#include "imap-common.h" +#include "str.h" +#include "ioloop.h" +#include "time-util.h" +#include "module-context.h" +#include "message-address.h" +#include "mail-user.h" +#include "mail-duplicate.h" +#include "mail-storage-private.h" +#include "iostream-ssl.h" +#include "smtp-submit.h" +#include "sieve.h" +#include "sieve-storage.h" +#include "sieve-script.h" + +#include "imap-filter-sieve.h" + +#define DUPLICATE_DB_NAME "lda-dupes" + +#define IMAP_FILTER_SIEVE_USER_CONTEXT(obj) \ + MODULE_CONTEXT(obj, imap_filter_sieve_user_module) +#define IMAP_FILTER_SIEVE_USER_CONTEXT_REQUIRE(obj) \ + MODULE_CONTEXT_REQUIRE(obj, imap_filter_sieve_user_module) + +struct imap_filter_sieve_script { + struct sieve_script *script; + struct sieve_binary *binary; + + /* Compile failed once with this error; + don't try again for this transaction */ + enum sieve_error compile_error; + + /* Binary corrupt after recompile; don't recompile again */ + bool binary_corrupt:1; + /* Resource usage exceeded */ + bool rusage_exceeded:1; +}; + +struct imap_filter_sieve_user { + union mail_user_module_context module_ctx; + struct client *client; + + struct sieve_instance *svinst; + struct sieve_storage *storage; + struct sieve_storage *global_storage; + + struct mail_duplicate_db *dup_db; + + struct sieve_error_handler *master_ehandler; +}; + +static MODULE_CONTEXT_DEFINE_INIT(imap_filter_sieve_user_module, + &mail_user_module_register); + +/* + * + */ + +static const char * +imap_filter_sieve_get_setting(void *context, const char *identifier) +{ + struct imap_filter_sieve_user *ifsuser = context; + struct mail_user *user = ifsuser->client->user; + + return mail_user_plugin_getenv(user, identifier); +} + +static const struct sieve_callbacks imap_filter_sieve_callbacks = { + NULL, + imap_filter_sieve_get_setting +}; + +static struct sieve_instance * +imap_filter_sieve_get_svinst(struct imap_filter_sieve_context *sctx) +{ + struct mail_user *user = sctx->user; + struct imap_filter_sieve_user *ifsuser = + IMAP_FILTER_SIEVE_USER_CONTEXT_REQUIRE(user); + struct sieve_environment svenv; + const struct mail_storage_settings *mail_set; + bool debug = user->mail_debug; + + if (ifsuser->svinst != NULL) + return ifsuser->svinst; + + mail_set = mail_user_set_get_storage_set(user); + + ifsuser->dup_db = mail_duplicate_db_init(user, DUPLICATE_DB_NAME); + + i_zero(&svenv); + svenv.username = user->username; + (void)mail_user_get_home(user, &svenv.home_dir); + svenv.hostname = mail_set->hostname; + svenv.base_dir = user->set->base_dir; + svenv.event_parent = ifsuser->client->event; + svenv.flags = SIEVE_FLAG_HOME_RELATIVE; + svenv.location = SIEVE_ENV_LOCATION_MS; + svenv.delivery_phase = SIEVE_DELIVERY_PHASE_POST; + + ifsuser->svinst = sieve_init(&svenv, &imap_filter_sieve_callbacks, + ifsuser, debug); + + ifsuser->master_ehandler = + sieve_master_ehandler_create(ifsuser->svinst, 0); + sieve_error_handler_accept_infolog(ifsuser->master_ehandler, TRUE); + sieve_error_handler_accept_debuglog(ifsuser->master_ehandler, debug); + + return ifsuser->svinst; +} + +static void +imap_filter_sieve_init_trace_log(struct imap_filter_sieve_context *sctx, + struct sieve_trace_config *trace_config_r, + struct sieve_trace_log **trace_log_r) +{ + struct sieve_instance *svinst = imap_filter_sieve_get_svinst(sctx); + struct client_command_context *cmd = sctx->filter_context->cmd; + struct mail_user *user = sctx->user; + + if (sctx->trace_log_initialized) { + *trace_config_r = sctx->trace_config; + *trace_log_r = sctx->trace_log; + return; + } + sctx->trace_log_initialized = TRUE; + + if (sieve_trace_config_get(svinst, &sctx->trace_config) < 0 || + sieve_trace_log_open(svinst, &sctx->trace_log) < 0) { + i_zero(&sctx->trace_config); + sctx->trace_log = NULL; + + i_zero(trace_config_r); + *trace_log_r = NULL; + return; + } + + /* Write header for trace file */ + sieve_trace_log_printf(sctx->trace_log, + "Sieve trace log for IMAP FILTER=SIEVE:\n" + "\n" + " Username: %s\n", user->username); + if (user->session_id != NULL) { + sieve_trace_log_printf(sctx->trace_log, + " Session ID: %s\n", user->session_id); + } + sieve_trace_log_printf(sctx->trace_log, + " Mailbox: %s\n" + " Command: %s %s %s\n\n", + mailbox_get_vname(sctx->filter_context->box), + cmd->tag, cmd->name, + cmd->human_args != NULL ? cmd->human_args : ""); + + *trace_config_r = sctx->trace_config; + *trace_log_r = sctx->trace_log; +} + +static int +imap_filter_sieve_get_personal_storage(struct imap_filter_sieve_context *sctx, + struct sieve_storage **storage_r, + enum mail_error *error_code_r, + const char **error_r) +{ + struct mail_user *user = sctx->user; + struct imap_filter_sieve_user *ifsuser = + IMAP_FILTER_SIEVE_USER_CONTEXT_REQUIRE(user); + enum sieve_storage_flags storage_flags = 0; + struct sieve_instance *svinst; + enum sieve_error error; + + *error_code_r = MAIL_ERROR_NONE; + *error_r = NULL; + + if (ifsuser->storage != NULL) { + *storage_r = ifsuser->storage; + return 0; + } + + // FIXME: limit interval between retries + + svinst = imap_filter_sieve_get_svinst(sctx); + ifsuser->storage = sieve_storage_create_main(svinst, user, + storage_flags, &error); + if (ifsuser->storage != NULL) { + *storage_r = ifsuser->storage; + return 0; + } + + switch (error) { + case SIEVE_ERROR_NOT_POSSIBLE: + *error_r = "Sieve processing is disabled for this user"; + *error_code_r = MAIL_ERROR_NOTPOSSIBLE; + break; + case SIEVE_ERROR_NOT_FOUND: + *error_r = "Sieve script storage not accessible"; + *error_code_r = MAIL_ERROR_NOTFOUND; + break; + default: + *error_r = t_strflocaltime(MAIL_ERRSTR_CRITICAL_MSG_STAMP, + ioloop_time); + *error_code_r = MAIL_ERROR_TEMP; + break; + } + + return -1; +} + +static int +imap_filter_sieve_get_global_storage(struct imap_filter_sieve_context *sctx, + struct sieve_storage **storage_r, + enum mail_error *error_code_r, + const char **error_r) +{ + struct mail_user *user = sctx->user; + struct imap_filter_sieve_user *ifsuser = + IMAP_FILTER_SIEVE_USER_CONTEXT_REQUIRE(user); + struct sieve_instance *svinst; + const char *location; + enum sieve_error error; + + *error_code_r = MAIL_ERROR_NONE; + *error_r = NULL; + + if (ifsuser->global_storage != NULL) { + *storage_r = ifsuser->global_storage; + return 0; + } + + svinst = imap_filter_sieve_get_svinst(sctx); + + location = mail_user_plugin_getenv(user, "sieve_global"); + if (location == NULL) { + e_info(sieve_get_event(svinst), + "include: sieve_global is unconfigured; " + "include of `:global' script is therefore not possible"); + *error_code_r = MAIL_ERROR_NOTFOUND; + *error_r = "No global Sieve scripts available"; + return -1; + } + ifsuser->global_storage = + sieve_storage_create(svinst, location, 0, &error); + if (ifsuser->global_storage != NULL) { + *storage_r = ifsuser->global_storage; + return 0; + } + + switch (error) { + case SIEVE_ERROR_NOT_POSSIBLE: + case SIEVE_ERROR_NOT_FOUND: + *error_r = "No global Sieve scripts available"; + *error_code_r = MAIL_ERROR_NOTFOUND; + break; + default: + *error_r = t_strflocaltime(MAIL_ERRSTR_CRITICAL_MSG_STAMP, + ioloop_time); + *error_code_r = MAIL_ERROR_TEMP; + break; + } + + return -1; +} + +/* + * + */ + +struct imap_filter_sieve_context * +imap_filter_sieve_context_create(struct imap_filter_context *ctx, + enum imap_filter_sieve_type type) +{ + struct client_command_context *cmd = ctx->cmd; + struct imap_filter_sieve_context *sctx; + + sctx = p_new(cmd->pool, struct imap_filter_sieve_context, 1); + sctx->pool = cmd->pool; + sctx->filter_context = ctx; + sctx->filter_type = type; + sctx->user = ctx->cmd->client->user; + + return sctx; +} + +void imap_filter_sieve_context_free(struct imap_filter_sieve_context **_sctx) +{ + struct imap_filter_sieve_context *sctx = *_sctx; + struct imap_filter_sieve_script *scripts; + unsigned int i; + + *_sctx = NULL; + + if (sctx == NULL) + return; + + scripts = sctx->scripts; + for (i = 0; i < sctx->scripts_count; i++) { + if (scripts[i].binary != NULL) + sieve_close(&scripts[i].binary); + if (scripts[i].script != NULL) + sieve_script_unref(&scripts[i].script); + } + + if (sctx->trace_log != NULL) + sieve_trace_log_free(&sctx->trace_log); + + str_free(&sctx->errors); +} + +/* + * Error handling + */ + +static struct sieve_error_handler * +imap_filter_sieve_create_error_handler(struct imap_filter_sieve_context *sctx) +{ + struct sieve_instance *svinst = imap_filter_sieve_get_svinst(sctx); + + /* Prepare error handler */ + if (sctx->errors == NULL) + sctx->errors = str_new(default_pool, 1024); + else + str_truncate(sctx->errors, 0); + return sieve_strbuf_ehandler_create(svinst, sctx->errors, TRUE, + 10 /* client->set->_max_compile_errors */); +} + +/* + * + */ + +static struct sieve_binary * +imap_sieve_filter_open_script(struct imap_filter_sieve_context *sctx, + struct sieve_script *script, + enum sieve_compile_flags cpflags, + struct sieve_error_handler *user_ehandler, + bool recompile, enum sieve_error *error_r) +{ + struct mail_user *user = sctx->user; + struct imap_filter_sieve_user *ifsuser = + IMAP_FILTER_SIEVE_USER_CONTEXT_REQUIRE(user); + struct sieve_instance *svinst = imap_filter_sieve_get_svinst(sctx); + struct sieve_error_handler *ehandler; + struct sieve_binary *sbin; + const char *compile_name = "compile"; + + if (recompile) { + /* Warn */ + e_warning(sieve_get_event(svinst), + "Encountered corrupt binary: re-compiling script %s", + sieve_script_location(script)); + compile_name = "re-compile"; + } else { + e_debug(sieve_get_event(svinst), "Loading script %s", + sieve_script_location(script)); + } + + if (script == sctx->user_script) + ehandler = user_ehandler; + else + ehandler = ifsuser->master_ehandler; + sieve_error_handler_reset(ehandler); + + /* Load or compile the sieve script */ + if (recompile) { + sbin = sieve_compile_script(script, ehandler, cpflags, error_r); + } else { + sbin = sieve_open_script(script, ehandler, cpflags, error_r); + } + + /* Handle error */ + if (sbin == NULL) { + switch (*error_r) { + /* Script not found */ + case SIEVE_ERROR_NOT_FOUND: + e_debug(sieve_get_event(svinst), + "Script `%s' is missing for %s", + sieve_script_location(script), compile_name); + break; + /* Temporary failure */ + case SIEVE_ERROR_TEMP_FAILURE: + e_error(sieve_get_event(svinst), + "Failed to open script `%s' for %s " + "(temporary failure)", + sieve_script_location(script), compile_name); + break; + /* Compile failed */ + case SIEVE_ERROR_NOT_VALID: + if (script == sctx->user_script) + break; + e_error(sieve_get_event(svinst), + "Failed to %s script `%s'", + compile_name, sieve_script_location(script)); + break; + /* Cumulative resource limit exceeded */ + case SIEVE_ERROR_RESOURCE_LIMIT: + e_error(sieve_get_event(svinst), + "Failed to open script `%s' for %s " + "(cumulative resource limit exceeded)", + sieve_script_location(script), compile_name); + break; + /* Something else */ + default: + e_error(sieve_get_event(svinst), + "Failed to open script `%s' for %s", + sieve_script_location(script), compile_name); + break; + } + + return NULL; + } + + if (!recompile) + (void)sieve_save(sbin, FALSE, NULL); + return sbin; +} + +int imap_filter_sieve_compile(struct imap_filter_sieve_context *sctx, + string_t **errors_r, bool *have_warnings_r) +{ + struct imap_filter_sieve_script *scripts = sctx->scripts; + unsigned int count = sctx->scripts_count, i; + struct sieve_error_handler *ehandler; + enum sieve_error error; + int ret = 0; + + *errors_r = NULL; + *have_warnings_r = FALSE; + + /* Prepare error handler */ + ehandler = imap_filter_sieve_create_error_handler(sctx); + + for (i = 0; i < count; i++) { + struct sieve_script *script = scripts[i].script; + + i_assert(script != NULL); + + scripts[i].binary = + imap_sieve_filter_open_script(sctx, script, 0, ehandler, + FALSE, &error); + if (scripts[i].binary == NULL) { + if (error != SIEVE_ERROR_NOT_VALID) { + const char *errormsg = + sieve_script_get_last_error( + script, &error); + if (error != SIEVE_ERROR_NONE) { + str_truncate(sctx->errors, 0); + str_append(sctx->errors, errormsg); + } + } + ret = -1; + break; + } + } + + if (ret < 0 && str_len(sctx->errors) == 0) { + /* Failed, but no user error was logged: log a generic internal + error instead. */ + sieve_internal_error(ehandler, NULL, NULL); + } + + *have_warnings_r = (sieve_get_warnings(ehandler) > 0); + *errors_r = sctx->errors; + + sieve_error_handler_unref(&ehandler); + return ret; +} + +void imap_filter_sieve_open_input(struct imap_filter_sieve_context *sctx, + struct istream *input) +{ + struct sieve_instance *svinst; + struct sieve_script *script; + + svinst = imap_filter_sieve_get_svinst(sctx); + script = sieve_data_script_create_from_input(svinst, "script", input); + + sctx->user_script = script; + sctx->scripts = p_new(sctx->pool, struct imap_filter_sieve_script, 1); + sctx->scripts_count = 1; + sctx->scripts[0].script = script; +} + +int imap_filter_sieve_open_personal(struct imap_filter_sieve_context *sctx, + const char *name, + enum mail_error *error_code_r, + const char **error_r) +{ + struct sieve_storage *storage; + struct sieve_script *script; + enum sieve_error error; + + if (imap_filter_sieve_get_personal_storage(sctx, &storage, + error_code_r, error_r) < 0) + return -1; + + if (name == NULL) + script = sieve_storage_active_script_open(storage, NULL); + else + script = sieve_storage_open_script(storage, name, NULL); + if (script == NULL) { + *error_r = sieve_storage_get_last_error(storage, &error); + + switch (error) { + case SIEVE_ERROR_NOT_FOUND: + *error_code_r = MAIL_ERROR_NOTFOUND; + break; + case SIEVE_ERROR_NOT_POSSIBLE: + *error_code_r = MAIL_ERROR_NOTPOSSIBLE; + break; + default: + *error_code_r = MAIL_ERROR_TEMP; + } + return -1; + } + + sctx->user_script = script; + sctx->scripts = p_new(sctx->pool, struct imap_filter_sieve_script, 1); + sctx->scripts_count = 1; + sctx->scripts[0].script = script; + return 0; +} + +int imap_filter_sieve_open_global(struct imap_filter_sieve_context *sctx, + const char *name, + enum mail_error *error_code_r, + const char **error_r) +{ + struct sieve_storage *storage; + struct sieve_script *script; + enum sieve_error error; + + if (imap_filter_sieve_get_global_storage(sctx, &storage, + error_code_r, error_r) < 0) + return -1; + + script = sieve_storage_open_script(storage, name, NULL); + if (script == NULL) { + *error_r = sieve_storage_get_last_error(storage, &error); + + switch (error) { + case SIEVE_ERROR_NOT_FOUND: + *error_code_r = MAIL_ERROR_NOTFOUND; + break; + case SIEVE_ERROR_NOT_POSSIBLE: + *error_code_r = MAIL_ERROR_NOTPOSSIBLE; + break; + default: + *error_code_r = MAIL_ERROR_TEMP; + } + return -1; + } + + sctx->user_script = script; + sctx->scripts = p_new(sctx->pool, struct imap_filter_sieve_script, 1); + sctx->scripts_count = 1; + sctx->scripts[0].script = script; + return 0; +} + +/* + * Mail transmission + */ + +static void * +imap_filter_sieve_smtp_start(const struct sieve_script_env *senv, + const struct smtp_address *mail_from) +{ + struct imap_filter_sieve_context *sctx = senv->script_context; + struct mail_user *user = sctx->user; + struct imap_filter_sieve_user *ifsuser = + IMAP_FILTER_SIEVE_USER_CONTEXT_REQUIRE(user); + const struct smtp_submit_settings *smtp_set = ifsuser->client->smtp_set; + struct ssl_iostream_settings ssl_set; + struct smtp_submit_input submit_input; + + i_zero(&ssl_set); + mail_user_init_ssl_client_settings(user, &ssl_set); + + i_zero(&submit_input); + submit_input.ssl = &ssl_set; + + return (void *)smtp_submit_init_simple(&submit_input, smtp_set, + mail_from); +} + +static void +imap_filter_sieve_smtp_add_rcpt(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle, + const struct smtp_address *rcpt_to) +{ + struct smtp_submit *smtp_submit = handle; + + smtp_submit_add_rcpt(smtp_submit, rcpt_to); +} + +static struct ostream * +imap_filter_sieve_smtp_send(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle) +{ + struct smtp_submit *smtp_submit = handle; + + return smtp_submit_send(smtp_submit); +} + +static void +imap_filter_sieve_smtp_abort(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle) +{ + struct smtp_submit *smtp_submit = handle; + + smtp_submit_deinit(&smtp_submit); +} + +static int +imap_filter_sieve_smtp_finish(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle, const char **error_r) +{ + struct smtp_submit *smtp_submit = handle; + int ret; + + ret = smtp_submit_run(smtp_submit, error_r); + smtp_submit_deinit(&smtp_submit); + return ret; +} + +/* + * Duplicate checking + */ + +static void * +imap_filter_sieve_duplicate_transaction_begin( + const struct sieve_script_env *senv) +{ + struct imap_filter_sieve_context *sctx = senv->script_context; + struct imap_filter_sieve_user *ifsuser = + IMAP_FILTER_SIEVE_USER_CONTEXT_REQUIRE(sctx->user); + + return mail_duplicate_transaction_begin(ifsuser->dup_db); +} + +static void imap_filter_sieve_duplicate_transaction_commit(void **_dup_trans) +{ + struct mail_duplicate_transaction *dup_trans = *_dup_trans; + + *_dup_trans = NULL; + + mail_duplicate_transaction_commit(&dup_trans); +} + +static void imap_filter_sieve_duplicate_transaction_rollback(void **_dup_trans) +{ + struct mail_duplicate_transaction *dup_trans = *_dup_trans; + + *_dup_trans = NULL; + + mail_duplicate_transaction_rollback(&dup_trans); +} + +static enum sieve_duplicate_check_result +imap_filter_sieve_duplicate_check(void *_dup_trans, + const struct sieve_script_env *senv, + const void *id, size_t id_size) +{ + struct mail_duplicate_transaction *dup_trans = _dup_trans; + + switch (mail_duplicate_check(dup_trans, id, id_size, + senv->user->username)) { + case MAIL_DUPLICATE_CHECK_RESULT_EXISTS: + return SIEVE_DUPLICATE_CHECK_RESULT_EXISTS; + case MAIL_DUPLICATE_CHECK_RESULT_NOT_FOUND: + return SIEVE_DUPLICATE_CHECK_RESULT_NOT_FOUND; + case MAIL_DUPLICATE_CHECK_RESULT_DEADLOCK: + case MAIL_DUPLICATE_CHECK_RESULT_LOCK_TIMEOUT: + return SIEVE_DUPLICATE_CHECK_RESULT_TEMP_FAILURE; + case MAIL_DUPLICATE_CHECK_RESULT_IO_ERROR: + case MAIL_DUPLICATE_CHECK_RESULT_TOO_MANY_LOCKS: + break; + } + return SIEVE_DUPLICATE_CHECK_RESULT_FAILURE; +} + +static void +imap_filter_sieve_duplicate_mark(void *_dup_trans, + const struct sieve_script_env *senv, + const void *id, size_t id_size, time_t time) +{ + struct mail_duplicate_transaction *dup_trans = _dup_trans; + + mail_duplicate_mark(dup_trans, id, id_size, senv->user->username, time); +} + +/* + * Result logging + */ + +static const char * +imap_filter_sieve_result_amend_log_message(const struct sieve_script_env *senv, + enum log_type log_type ATTR_UNUSED, + const char *message) +{ + struct imap_filter_sieve_context *sctx = senv->script_context; + string_t *str; + + if (sctx->mail == NULL) + return message; + + str = t_str_new(256); + str_printfa(str, "uid=%u: ", sctx->mail->uid); + str_append(str, message); + return str_c(str); +} + +/* + * + */ + +static int +imap_sieve_filter_handle_exec_status(struct imap_filter_sieve_context *sctx, + struct sieve_script *script, int status, + struct sieve_exec_status *estatus, + bool *fatal_r) +{ + struct imap_filter_sieve_user *ifsuser = + IMAP_FILTER_SIEVE_USER_CONTEXT_REQUIRE(sctx->user); + struct sieve_instance *svinst = ifsuser->svinst; + enum log_type log_level, user_log_level; + enum mail_error mail_error = MAIL_ERROR_NONE; + int ret = -1; + + *fatal_r = FALSE; + + log_level = user_log_level = LOG_TYPE_ERROR; + + if (estatus->last_storage != NULL && estatus->store_failed) { + (void)mail_storage_get_last_error(estatus->last_storage, + &mail_error); + + /* Don't bother administrator too much with benign errors */ + if (mail_error == MAIL_ERROR_NOQUOTA) { + log_level = LOG_TYPE_INFO; + user_log_level = LOG_TYPE_INFO; + } + } + + switch (status) { + case SIEVE_EXEC_FAILURE: + e_log(sieve_get_event(svinst), user_log_level, + "Execution of script %s failed", + sieve_script_location(script)); + ret = -1; + break; + case SIEVE_EXEC_TEMP_FAILURE: + e_log(sieve_get_event(svinst), log_level, + "Execution of script %s was aborted " + "due to temporary failure", + sieve_script_location(script)); + *fatal_r = TRUE; + ret = -1; + break; + case SIEVE_EXEC_BIN_CORRUPT: + e_error(sieve_get_event(svinst), + "!!BUG!!: Binary compiled from %s is still corrupt; " + "bailing out and reverting to default action", + sieve_script_location(script)); + *fatal_r = TRUE; + ret = -1; + break; + case SIEVE_EXEC_RESOURCE_LIMIT: + e_error(sieve_get_event(svinst), + "Execution of script %s was aborted " + "due to excessive resource usage", + sieve_script_location(script)); + *fatal_r = TRUE; + ret = -1; + break; + case SIEVE_EXEC_KEEP_FAILED: + e_log(sieve_get_event(svinst), log_level, + "Execution of script %s failed " + "with unsuccessful implicit keep", + sieve_script_location(script)); + ret = -1; + break; + case SIEVE_EXEC_OK: + ret = (estatus->keep_original ? 0 : 1); + break; + } + + return ret; +} + +static int +imap_sieve_filter_run_scripts(struct imap_filter_sieve_context *sctx, + struct sieve_error_handler *user_ehandler, + const struct sieve_message_data *msgdata, + const struct sieve_script_env *scriptenv, + bool *fatal_r) +{ + struct mail_user *user = sctx->user; + struct imap_filter_sieve_user *ifsuser = + IMAP_FILTER_SIEVE_USER_CONTEXT_REQUIRE(user); + struct sieve_instance *svinst = ifsuser->svinst; + struct imap_filter_sieve_script *scripts = sctx->scripts; + unsigned int count = sctx->scripts_count; + struct sieve_resource_usage *rusage = + &scriptenv->exec_status->resource_usage; + struct sieve_multiscript *mscript; + struct sieve_error_handler *ehandler; + struct sieve_script *last_script = NULL; + bool user_script = FALSE, more = TRUE, rusage_exceeded = FALSE; + enum sieve_compile_flags cpflags; + enum sieve_execute_flags exflags; + enum sieve_error compile_error = SIEVE_ERROR_NONE; + unsigned int i; + int ret; + + *fatal_r = FALSE; + + /* Start execution */ + mscript = sieve_multiscript_start_execute(svinst, msgdata, scriptenv); + + /* Execute scripts */ + for (i = 0; i < count && more; i++) { + struct sieve_script *script = scripts[i].script; + struct sieve_binary *sbin = scripts[i].binary; + int mstatus; + + if (sbin == NULL) { + e_debug(sieve_get_event(svinst), + "Skipping script from `%s'", + sieve_script_location(script)); + continue; + } + + cpflags = 0; + exflags = SIEVE_EXECUTE_FLAG_SKIP_RESPONSES; + + user_script = (script == sctx->user_script); + last_script = script; + + if (scripts[i].rusage_exceeded) { + rusage_exceeded = TRUE; + break; + } + + sieve_resource_usage_init(rusage); + if (user_script) { + cpflags |= SIEVE_COMPILE_FLAG_NOGLOBAL; + exflags |= SIEVE_EXECUTE_FLAG_NOGLOBAL; + ehandler = user_ehandler; + } else { + ehandler = ifsuser->master_ehandler; + } + + /* Execute */ + e_debug(sieve_get_event(svinst), + "Executing script from `%s'", + sieve_get_source(sbin)); + more = sieve_multiscript_run(mscript, + sbin, ehandler, ehandler, exflags); + + mstatus = sieve_multiscript_status(mscript); + if (!more && mstatus == SIEVE_EXEC_BIN_CORRUPT && + !scripts[i].binary_corrupt && sieve_is_loaded(sbin)) { + /* Close corrupt script */ + sieve_close(&sbin); + + /* Recompile */ + scripts[i].binary = sbin = + imap_sieve_filter_open_script( + sctx, script, cpflags, user_ehandler, + FALSE, &compile_error); + if (sbin == NULL) { + scripts[i].compile_error = compile_error; + break; + } + + /* Execute again */ + more = sieve_multiscript_run(mscript, sbin, + ehandler, ehandler, + exflags); + + /* Save new version */ + + mstatus = sieve_multiscript_status(mscript); + if (mstatus == SIEVE_EXEC_BIN_CORRUPT) + scripts[i].binary_corrupt = TRUE; + else if (more) + (void)sieve_save(sbin, FALSE, NULL); + } + + if (user_script && !sieve_record_resource_usage(sbin, rusage)) { + rusage_exceeded = ((i + 1) < count && more); + scripts[i].rusage_exceeded = TRUE; + break; + } + } + + /* Finish execution */ + exflags = SIEVE_EXECUTE_FLAG_SKIP_RESPONSES; + ehandler = (user_ehandler != NULL ? + user_ehandler : ifsuser->master_ehandler); + if (compile_error == SIEVE_ERROR_TEMP_FAILURE) { + ret = sieve_multiscript_finish(&mscript, ehandler, exflags, + SIEVE_EXEC_TEMP_FAILURE); + } else if (rusage_exceeded) { + i_assert(last_script != NULL); + (void)sieve_multiscript_finish(&mscript, ehandler, exflags, + SIEVE_EXEC_TEMP_FAILURE); + sieve_error(ehandler, sieve_script_name(last_script), + "cumulative resource usage limit exceeded"); + ret = SIEVE_EXEC_RESOURCE_LIMIT; + } else { + ret = sieve_multiscript_finish(&mscript, ehandler, exflags, + SIEVE_EXEC_OK); + } + + /* Don't log additional messages about compile failure */ + if (compile_error != SIEVE_ERROR_NONE && + ret == SIEVE_EXEC_FAILURE) { + e_info(sieve_get_event(svinst), + "Aborted script execution sequence " + "with successful implicit keep"); + return 0; + } + + if (last_script == NULL && ret == SIEVE_EXEC_OK) + return 0; + i_assert(last_script != NULL); /* at least one script is executed */ + return imap_sieve_filter_handle_exec_status(sctx, last_script, ret, + scriptenv->exec_status, + fatal_r); +} + +static int +parse_address(const char *address, const struct smtp_address **addr_r) +{ + struct message_address *msg_addr; + struct smtp_address *smtp_addr; + + if (message_address_parse_path(pool_datastack_create(), + (const unsigned char *)address, + strlen(address), &msg_addr) < 0) { + *addr_r = NULL; + return -1; + } + if (smtp_address_create_from_msg_temp(msg_addr, &smtp_addr) < 0) { + *addr_r = NULL; + return -1; + } + + *addr_r = smtp_addr; + return 1; +} + +int imap_sieve_filter_run_init(struct imap_filter_sieve_context *sctx) +{ + struct sieve_instance *svinst = imap_filter_sieve_get_svinst(sctx); + struct sieve_script_env *scriptenv = &sctx->scriptenv; + struct mail_user *user = sctx->user; + const char *error; + + if (sieve_script_env_init(scriptenv, user, &error) < 0) { + e_error(sieve_get_event(svinst), + "Failed to initialize script execution: %s", + error); + return -1; + } + + scriptenv->smtp_start = imap_filter_sieve_smtp_start; + scriptenv->smtp_add_rcpt = imap_filter_sieve_smtp_add_rcpt; + scriptenv->smtp_send = imap_filter_sieve_smtp_send; + scriptenv->smtp_abort = imap_filter_sieve_smtp_abort; + scriptenv->smtp_finish = imap_filter_sieve_smtp_finish; + scriptenv->duplicate_transaction_begin = + imap_filter_sieve_duplicate_transaction_begin; + scriptenv->duplicate_transaction_commit = + imap_filter_sieve_duplicate_transaction_commit; + scriptenv->duplicate_transaction_rollback = + imap_filter_sieve_duplicate_transaction_rollback; + scriptenv->duplicate_mark = imap_filter_sieve_duplicate_mark; + scriptenv->duplicate_check = imap_filter_sieve_duplicate_check; + scriptenv->script_context = sctx; + return 0; +} + +static void +imap_sieve_filter_get_msgdata(struct imap_filter_sieve_context *sctx, + struct mail *mail, + struct sieve_message_data *msgdata_r) +{ + struct sieve_instance *svinst = imap_filter_sieve_get_svinst(sctx); + struct mail_user *user = sctx->user; + const char *address, *error; + const struct smtp_address *mail_from, *rcpt_to; + struct smtp_address *user_addr; + int ret; + + mail_from = NULL; + if ((ret = mail_get_special(mail, MAIL_FETCH_FROM_ENVELOPE, + &address)) > 0 && + (ret = parse_address(address, &mail_from)) < 0) { + e_warning(sieve_get_event(svinst), + "Failed to parse message FROM_ENVELOPE"); + } + if (ret <= 0 && + mail_get_first_header(mail, "Return-Path", + &address) > 0 && + parse_address(address, &mail_from) < 0) { + e_info(sieve_get_event(svinst), + "Failed to parse Return-Path header"); + } + + rcpt_to = NULL; + if (mail_get_first_header(mail, "Delivered-To", + &address) > 0 && + parse_address(address, &rcpt_to) < 0) { + e_info(sieve_get_event(svinst), + "Failed to parse Delivered-To header"); + } + if (rcpt_to == NULL) { + if (svinst->user_email != NULL) + rcpt_to = svinst->user_email; + else if (smtp_address_parse_username(sctx->pool, user->username, + &user_addr, &error) < 0) { + e_warning(sieve_get_event(svinst), + "Cannot obtain SMTP address from username `%s': %s", + user->username, error); + } else { + if (user_addr->domain == NULL) + user_addr->domain = svinst->domainname; + rcpt_to = user_addr; + } + } + + // FIXME: maybe parse top Received header. + + i_zero(msgdata_r); + msgdata_r->mail = mail; + msgdata_r->envelope.mail_from = mail_from; + msgdata_r->envelope.rcpt_to = rcpt_to; + msgdata_r->auth_user = user->username; + (void)mail_get_message_id(mail, &msgdata_r->id); +} + +int imap_sieve_filter_run_mail(struct imap_filter_sieve_context *sctx, + struct mail *mail, string_t **errors_r, + bool *have_warnings_r, bool *have_changes_r, + bool *fatal_r) +{ + struct sieve_error_handler *user_ehandler; + struct sieve_message_data msgdata; + struct sieve_script_env *scriptenv = &sctx->scriptenv; + struct sieve_exec_status estatus; + struct sieve_trace_config trace_config; + struct sieve_trace_log *trace_log; + int ret; + + *errors_r = NULL; + *have_warnings_r = FALSE; + *have_changes_r = FALSE; + i_zero(&estatus); + + sctx->mail = mail; + + /* Prepare error handler */ + user_ehandler = imap_filter_sieve_create_error_handler(sctx); + + /* Initialize trace logging */ + imap_filter_sieve_init_trace_log(sctx, &trace_config, &trace_log); + + T_BEGIN { + if (trace_log != NULL) { + /* Write trace header for message */ + sieve_trace_log_printf(trace_log, + "Filtering message:\n" + "\n" + " UID: %u\n", mail->uid); + } + + /* Collect necessary message data */ + + imap_sieve_filter_get_msgdata(sctx, mail, &msgdata); + + /* Complete script execution environment */ + + scriptenv->default_mailbox = mailbox_get_vname(mail->box); + scriptenv->result_amend_log_message = + imap_filter_sieve_result_amend_log_message; + scriptenv->trace_log = trace_log; + scriptenv->trace_config = trace_config; + scriptenv->script_context = sctx; + + scriptenv->exec_status = &estatus; + + /* Execute script(s) */ + + ret = imap_sieve_filter_run_scripts(sctx, user_ehandler, + &msgdata, scriptenv, + fatal_r); + } T_END; + + if (ret < 0 && str_len(sctx->errors) == 0) { + /* Failed, but no user error was logged: log a generic internal + error instead. */ + sieve_internal_error(user_ehandler, NULL, NULL); + } + + *have_warnings_r = (sieve_get_warnings(user_ehandler) > 0); + *have_changes_r = estatus.significant_action_executed; + *errors_r = sctx->errors; + + sieve_error_handler_unref(&user_ehandler); + + sctx->mail = NULL; + + return ret; +} + +/* + * User + */ + +static void imap_filter_sieve_user_deinit(struct mail_user *user) +{ + struct imap_filter_sieve_user *ifsuser = + IMAP_FILTER_SIEVE_USER_CONTEXT_REQUIRE(user); + + sieve_error_handler_unref(&ifsuser->master_ehandler); + + if (ifsuser->storage != NULL) + sieve_storage_unref(&ifsuser->storage); + if (ifsuser->global_storage != NULL) + sieve_storage_unref(&ifsuser->global_storage); + if (ifsuser->svinst != NULL) + sieve_deinit(&ifsuser->svinst); + if (ifsuser->dup_db != NULL) + mail_duplicate_db_deinit(&ifsuser->dup_db); + + ifsuser->module_ctx.super.deinit(user); +} + +static void imap_filter_sieve_user_created(struct mail_user *user) +{ + struct imap_filter_sieve_user *ifsuser; + struct mail_user_vfuncs *v = user->vlast; + + ifsuser = p_new(user->pool, struct imap_filter_sieve_user, 1); + ifsuser->module_ctx.super = *v; + user->vlast = &ifsuser->module_ctx.super; + v->deinit = imap_filter_sieve_user_deinit; + MODULE_CONTEXT_SET(user, imap_filter_sieve_user_module, ifsuser); +} + +/* + * Hooks + */ + +static struct mail_storage_hooks imap_filter_sieve_mail_storage_hooks = { + .mail_user_created = imap_filter_sieve_user_created, +}; + +/* + * Client + */ + +void imap_filter_sieve_client_created(struct client *client) +{ + struct imap_filter_sieve_user *ifsuser = + IMAP_FILTER_SIEVE_USER_CONTEXT_REQUIRE(client->user); + + ifsuser->client = client; +} + +/* + * + */ + +void imap_filter_sieve_init(struct module *module) +{ + mail_storage_hooks_add(module, &imap_filter_sieve_mail_storage_hooks); +} + +void imap_filter_sieve_deinit(void) +{ + mail_storage_hooks_remove(&imap_filter_sieve_mail_storage_hooks); +} + + diff --git a/pigeonhole/src/plugins/imap-filter-sieve/imap-filter-sieve.h b/pigeonhole/src/plugins/imap-filter-sieve/imap-filter-sieve.h new file mode 100644 index 0000000..c06cbdb --- /dev/null +++ b/pigeonhole/src/plugins/imap-filter-sieve/imap-filter-sieve.h @@ -0,0 +1,97 @@ +#ifndef IMAP_FILTER_SIEVE_H +#define IMAP_FILTER_SIEVE_H + +#include "sieve.h" +#include "imap-filter.h" + +struct imap_filter_sieve_script; +struct imap_filter_sieve_context; + +enum imap_filter_sieve_type { + IMAP_FILTER_SIEVE_TYPE_DELIVERY, + IMAP_FILTER_SIEVE_TYPE_PERSONAL, + IMAP_FILTER_SIEVE_TYPE_GLOBAL, + IMAP_FILTER_SIEVE_TYPE_SCRIPT, +}; + +struct imap_filter_sieve_context { + pool_t pool; + + struct imap_filter_context *filter_context; + enum imap_filter_sieve_type filter_type; + + struct mail_user *user; + + struct sieve_script *user_script; + struct imap_filter_sieve_script *scripts; + unsigned int scripts_count; + + struct mail *mail; + + struct sieve_script_env scriptenv; + struct sieve_trace_config trace_config; + struct sieve_trace_log *trace_log; + + string_t *errors; + + bool warnings:1; + bool trace_log_initialized:1; +}; + +/* + * FILTER Command + */ + +bool cmd_filter_sieve(struct client_command_context *cmd); + +/* + * Context + */ + +struct imap_filter_sieve_context * +imap_filter_sieve_context_create(struct imap_filter_context *ctx, + enum imap_filter_sieve_type type); +void imap_filter_sieve_context_free(struct imap_filter_sieve_context **_sctx); + +/* + * Compile + */ + +int imap_filter_sieve_compile(struct imap_filter_sieve_context *sctx, + string_t **errors_r, bool *have_warnings_r); + +/* + * Open + */ + +void imap_filter_sieve_open_input(struct imap_filter_sieve_context *sctx, + struct istream *input); +int imap_filter_sieve_open_personal(struct imap_filter_sieve_context *sctx, + const char *name, + enum mail_error *error_code_r, + const char **error_r) ATTR_NULL(2); +int imap_filter_sieve_open_global(struct imap_filter_sieve_context *sctx, + const char *name, + enum mail_error *error_code_r, + const char **error_r); + +/* + * Run + */ + +int imap_sieve_filter_run_init(struct imap_filter_sieve_context *sctx); +int imap_sieve_filter_run_mail(struct imap_filter_sieve_context *sctx, + struct mail *mail, string_t **errors_r, + bool *have_warnings_r, bool *have_changes_r, + bool *fatal_r); + +/* + * + */ + +void imap_filter_sieve_client_created(struct client *client); + +void imap_filter_sieve_init(struct module *module); +void imap_filter_sieve_deinit(void); + +#endif diff --git a/pigeonhole/src/plugins/imap-filter-sieve/imap-filter.c b/pigeonhole/src/plugins/imap-filter-sieve/imap-filter.c new file mode 100644 index 0000000..fd7d758 --- /dev/null +++ b/pigeonhole/src/plugins/imap-filter-sieve/imap-filter.c @@ -0,0 +1,273 @@ +/* Copyright (c) 2017-2018 Pigeonhole authors, see the included COPYING file */ + +#include "imap-common.h" +#include "str.h" +#include "ostream.h" +#include "time-util.h" +#include "imap-resp-code.h" +#include "imap-search-args.h" + +#include "imap-filter.h" +#include "imap-filter-sieve.h" + +static void imap_filter_args_check(struct imap_filter_context *ctx, + const struct mail_search_arg *sargs) +{ + for (; sargs != NULL; sargs = sargs->next) { + switch (sargs->type) { + case SEARCH_SEQSET: + ctx->have_seqsets = TRUE; + break; + case SEARCH_MODSEQ: + ctx->have_modseqs = TRUE; + break; + case SEARCH_OR: + case SEARCH_SUB: + imap_filter_args_check(ctx, sargs->value.subargs); + break; + default: + break; + } + } +} + +static bool +imap_filter_mail(struct client_command_context *cmd, struct mail *mail) +{ + struct imap_filter_context *ctx = cmd->context; + struct client *client = cmd->client; + string_t *errors = NULL; + bool have_warnings = FALSE, have_changes = FALSE, fatal = FALSE; + string_t *reply = t_str_new(128); + int ret; + + ret = imap_sieve_filter_run_mail(ctx->sieve, mail, &errors, + &have_warnings, &have_changes, &fatal); + + str_printfa(reply, "* %u FILTERED (TAG %s) UID %u ", + mail->seq, cmd->tag, mail->uid); + if (ret < 0 || have_warnings) { + str_printfa(reply, "%s {%zu}\r\n", + (ret < 0 ? "ERRORS" : "WARNINGS"), + str_len(errors)); + str_append_str(reply, errors); + str_append(reply, "\r\n"); + } else if (have_changes || ret > 0) { + str_append(reply, "OK\r\n"); + } else { + str_truncate(reply, 0); + } + if (str_len(reply) > 0) + o_stream_nsend(client->output, str_data(reply), str_len(reply)); + + /* Handle the result */ + if (ret < 0) { + /* Sieve error; keep */ + } else { + if (ret > 0) { + /* Discard */ + mail_update_flags(mail, MODIFY_ADD, MAIL_DELETED); + } + } + + return !fatal; +} + +static bool imap_filter_more(struct client_command_context *cmd) +{ + struct imap_filter_context *ctx = cmd->context; + struct mail *mail; + enum mailbox_sync_flags sync_flags; + const char *ok_reply; + bool tryagain, lost_data; + + if (cmd->cancel) { + (void)imap_filter_deinit(ctx); + return TRUE; + } + + while (mailbox_search_next_nonblock(ctx->search_ctx, + &mail, &tryagain)) { + bool ret; + T_BEGIN { + ret = imap_filter_mail(cmd, mail); + } T_END; + if (!ret) + break; + } + if (tryagain) + return FALSE; + + lost_data = mailbox_search_seen_lost_data(ctx->search_ctx); + if (imap_filter_deinit(ctx) < 0) { + client_send_box_error(cmd, cmd->client->mailbox); + return TRUE; + } + + sync_flags = MAILBOX_SYNC_FLAG_FAST; + if (!cmd->uid || ctx->have_seqsets) + sync_flags |= MAILBOX_SYNC_FLAG_NO_EXPUNGES; + ok_reply = t_strdup_printf("OK %sFilter completed", + lost_data ? "["IMAP_RESP_CODE_EXPUNGEISSUED"] " : ""); + return cmd_sync(cmd, sync_flags, 0, ok_reply); +} + +static void imap_filter_more_callback(struct client_command_context *cmd) +{ + struct client *client = cmd->client; + bool finished; + + o_stream_cork(client->output); + finished = command_exec(cmd); + o_stream_uncork(client->output); + + if (!finished) + (void)client_handle_unfinished_cmd(cmd); + else + client_command_free(&cmd); + cmd_sync_delayed(client); + + if (client->disconnected) + client_destroy(client, NULL); + else + client_continue_pending_input(client); +} + +static bool +imap_filter_start(struct imap_filter_context *ctx, + struct mail_search_args *sargs) +{ + struct client_command_context *cmd = ctx->cmd; + + imap_filter_args_check(ctx, sargs->args); + + if (ctx->have_modseqs) + (void)client_enable(cmd->client, MAILBOX_FEATURE_CONDSTORE); + + ctx->box = cmd->client->mailbox; + ctx->trans = mailbox_transaction_begin(ctx->box, 0, + imap_client_command_get_reason(cmd)); + ctx->sargs = sargs; + ctx->search_ctx = mailbox_search_init(ctx->trans, sargs, NULL, 0, NULL); + + if (imap_sieve_filter_run_init(ctx->sieve) < 0) { + const char *error = t_strflocaltime( + MAIL_ERRSTR_CRITICAL_MSG_STAMP, ioloop_time); + + o_stream_nsend_str(cmd->client->output, + t_strdup_printf("* FILTER (TAG %s) " + "ERRORS {%zu}\r\n%s\r\n", + cmd->tag, strlen(error), error)); + client_send_tagline(cmd, + "NO Failed to initialize script execution"); + (void)imap_filter_deinit(ctx); + return TRUE; + } + + cmd->func = imap_filter_more; + cmd->context = ctx; + + if (imap_filter_more(cmd)) + return TRUE; + + /* we may have moved onto syncing by now */ + if (cmd->func == imap_filter_more) { + ctx->to = timeout_add(0, imap_filter_more_callback, cmd); + cmd->state = CLIENT_COMMAND_STATE_WAIT_EXTERNAL; + } + return FALSE; +} + +static bool +imap_filter_parse_search(struct imap_filter_context *ctx, + const struct imap_arg *args) +{ + struct client_command_context *cmd = ctx->cmd; + struct mail_search_args *sargs; + const char *charset; + int ret; + + if (imap_arg_atom_equals(args, "CHARSET")) { + /* CHARSET specified */ + if (!imap_arg_get_astring(&args[1], &charset)) { + client_send_command_error(cmd, + "Invalid charset argument."); + imap_filter_context_free(ctx); + return TRUE; + } + args += 2; + } else { + charset = "UTF-8"; + } + + ret = imap_search_args_build(cmd, args, charset, &sargs); + if (ret <= 0) { + imap_filter_context_free(ctx); + return ret < 0; + } + + return imap_filter_start(ctx, sargs); +} + +bool imap_filter_search(struct client_command_context *cmd) +{ + struct imap_filter_context *ctx = cmd->context; + const struct imap_arg *args; + const char *error; + enum imap_parser_error parse_error; + int ret; + + ret = imap_parser_read_args(ctx->parser, 0, 0, &args); + if (ret < 0) { + if (ret == -2) + return FALSE; + error = imap_parser_get_error(ctx->parser, &parse_error); + switch (parse_error) { + case IMAP_PARSE_ERROR_NONE: + i_unreached(); + case IMAP_PARSE_ERROR_LITERAL_TOO_BIG: + client_disconnect_with_error(ctx->cmd->client, error); + break; + default: + client_send_command_error(ctx->cmd, error); + break; + } + return TRUE; + } + return imap_filter_parse_search(ctx, args); +} + +int imap_filter_deinit(struct imap_filter_context *ctx) +{ + int ret = 0; + + o_stream_set_flush_callback(ctx->cmd->client->output, + client_output, ctx->cmd->client); + ctx->cmd->client->input_lock = NULL; + imap_parser_unref(&ctx->parser); + + if (ctx->search_ctx != NULL && + mailbox_search_deinit(&ctx->search_ctx) < 0) + ret = -1; + + if (ctx->trans != NULL) + (void)mailbox_transaction_commit(&ctx->trans); + + timeout_remove(&ctx->to); + if (ctx->sargs != NULL) { + mail_search_args_deinit(ctx->sargs); + mail_search_args_unref(&ctx->sargs); + } + imap_filter_context_free(ctx); + + ctx->cmd->context = NULL; + return ret; +} + +void imap_filter_context_free(struct imap_filter_context *ctx) +{ + imap_filter_sieve_context_free(&ctx->sieve); +} + + + diff --git a/pigeonhole/src/plugins/imap-filter-sieve/imap-filter.h b/pigeonhole/src/plugins/imap-filter-sieve/imap-filter.h new file mode 100644 index 0000000..d504704 --- /dev/null +++ b/pigeonhole/src/plugins/imap-filter-sieve/imap-filter.h @@ -0,0 +1,43 @@ +#ifndef IMAP_FILTER_H +#define IMAP_FILTER_H + +struct mail_duplicate_db; + +struct sieve_script; +struct sieve_storage; +struct sieve_binary; + +struct imap_filter_context { + struct client_command_context *cmd; + struct mailbox *box; + struct mailbox_transaction_context *trans; + struct mail_search_context *search_ctx; + + struct imap_parser *parser; + + struct imap_filter_sieve_context *sieve; + const char *script_name; + uoff_t script_len; + struct istream *script_input; + + struct mail_search_args *sargs; + + struct timeout *to; + + bool failed:1; + bool compile_failure:1; + bool have_seqsets:1; + bool have_modseqs:1; +}; + +bool imap_filter_search(struct client_command_context *cmd); + +int imap_filter_deinit(struct imap_filter_context *ctx); + +void imap_filter_context_free(struct imap_filter_context *ctx); + +/* Commands */ + +bool cmd_filter(struct client_command_context *cmd); + +#endif diff --git a/pigeonhole/src/plugins/imapsieve/Makefile.am b/pigeonhole/src/plugins/imapsieve/Makefile.am new file mode 100644 index 0000000..1fea23e --- /dev/null +++ b/pigeonhole/src/plugins/imapsieve/Makefile.am @@ -0,0 +1,40 @@ +imap_moduledir = $(dovecot_moduledir) +sieve_plugindir = $(dovecot_moduledir)/sieve + +imap_module_LTLIBRARIES = lib95_imap_sieve_plugin.la +sieve_plugin_LTLIBRARIES = lib90_sieve_imapsieve_plugin.la + +lib95_imap_sieve_plugin_la_LDFLAGS = -module -avoid-version +lib90_sieve_imapsieve_plugin_la_LDFLAGS = -module -avoid-version + +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + -I$(top_srcdir)/src/lib-sieve/util \ + -I$(top_srcdir)/src/lib-sieve/plugins/environment \ + $(LIBDOVECOT_IMAP_INCLUDE) \ + $(LIBDOVECOT_LDA_INCLUDE) \ + $(LIBDOVECOT_INCLUDE) \ + -DPKG_RUNDIR=\""$(rundir)"\" + +lib95_imap_sieve_plugin_la_SOURCES = \ + ext-imapsieve.c \ + ext-imapsieve-environment.c \ + imap-sieve.c \ + imap-sieve-storage.c \ + imap-sieve-plugin.c +lib95_imap_sieve_plugin_la_LIBADD = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la + +lib90_sieve_imapsieve_plugin_la_SOURCES = \ + ext-imapsieve.c \ + sieve-imapsieve-plugin.c +lib90_sieve_imapsieve_plugin_la_CPPFLAGS = \ + ${AM_CPPFLAGS} \ + -D__IMAPSIEVE_DUMMY + +noinst_HEADERS = \ + ext-imapsieve-common.h \ + imap-sieve.h \ + imap-sieve-storage.h \ + imap-sieve-plugin.h \ + sieve-imapsieve-plugin.h diff --git a/pigeonhole/src/plugins/imapsieve/Makefile.in b/pigeonhole/src/plugins/imapsieve/Makefile.in new file mode 100644 index 0000000..648975b --- /dev/null +++ b/pigeonhole/src/plugins/imapsieve/Makefile.in @@ -0,0 +1,864 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/plugins/imapsieve +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(imap_moduledir)" \ + "$(DESTDIR)$(sieve_plugindir)" +LTLIBRARIES = $(imap_module_LTLIBRARIES) $(sieve_plugin_LTLIBRARIES) +lib90_sieve_imapsieve_plugin_la_LIBADD = +am_lib90_sieve_imapsieve_plugin_la_OBJECTS = \ + lib90_sieve_imapsieve_plugin_la-ext-imapsieve.lo \ + lib90_sieve_imapsieve_plugin_la-sieve-imapsieve-plugin.lo +lib90_sieve_imapsieve_plugin_la_OBJECTS = \ + $(am_lib90_sieve_imapsieve_plugin_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +lib90_sieve_imapsieve_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) \ + $(lib90_sieve_imapsieve_plugin_la_LDFLAGS) $(LDFLAGS) -o $@ +lib95_imap_sieve_plugin_la_DEPENDENCIES = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la +am_lib95_imap_sieve_plugin_la_OBJECTS = ext-imapsieve.lo \ + ext-imapsieve-environment.lo imap-sieve.lo \ + imap-sieve-storage.lo imap-sieve-plugin.lo +lib95_imap_sieve_plugin_la_OBJECTS = \ + $(am_lib95_imap_sieve_plugin_la_OBJECTS) +lib95_imap_sieve_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib95_imap_sieve_plugin_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ext-imapsieve-environment.Plo \ + ./$(DEPDIR)/ext-imapsieve.Plo \ + ./$(DEPDIR)/imap-sieve-plugin.Plo \ + ./$(DEPDIR)/imap-sieve-storage.Plo ./$(DEPDIR)/imap-sieve.Plo \ + ./$(DEPDIR)/lib90_sieve_imapsieve_plugin_la-ext-imapsieve.Plo \ + ./$(DEPDIR)/lib90_sieve_imapsieve_plugin_la-sieve-imapsieve-plugin.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(lib90_sieve_imapsieve_plugin_la_SOURCES) \ + $(lib95_imap_sieve_plugin_la_SOURCES) +DIST_SOURCES = $(lib90_sieve_imapsieve_plugin_la_SOURCES) \ + $(lib95_imap_sieve_plugin_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +imap_moduledir = $(dovecot_moduledir) +sieve_plugindir = $(dovecot_moduledir)/sieve +imap_module_LTLIBRARIES = lib95_imap_sieve_plugin.la +sieve_plugin_LTLIBRARIES = lib90_sieve_imapsieve_plugin.la +lib95_imap_sieve_plugin_la_LDFLAGS = -module -avoid-version +lib90_sieve_imapsieve_plugin_la_LDFLAGS = -module -avoid-version +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + -I$(top_srcdir)/src/lib-sieve/util \ + -I$(top_srcdir)/src/lib-sieve/plugins/environment \ + $(LIBDOVECOT_IMAP_INCLUDE) \ + $(LIBDOVECOT_LDA_INCLUDE) \ + $(LIBDOVECOT_INCLUDE) \ + -DPKG_RUNDIR=\""$(rundir)"\" + +lib95_imap_sieve_plugin_la_SOURCES = \ + ext-imapsieve.c \ + ext-imapsieve-environment.c \ + imap-sieve.c \ + imap-sieve-storage.c \ + imap-sieve-plugin.c + +lib95_imap_sieve_plugin_la_LIBADD = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la + +lib90_sieve_imapsieve_plugin_la_SOURCES = \ + ext-imapsieve.c \ + sieve-imapsieve-plugin.c + +lib90_sieve_imapsieve_plugin_la_CPPFLAGS = \ + ${AM_CPPFLAGS} \ + -D__IMAPSIEVE_DUMMY + +noinst_HEADERS = \ + ext-imapsieve-common.h \ + imap-sieve.h \ + imap-sieve-storage.h \ + imap-sieve-plugin.h \ + sieve-imapsieve-plugin.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/imapsieve/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/plugins/imapsieve/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-imap_moduleLTLIBRARIES: $(imap_module_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(imap_module_LTLIBRARIES)'; test -n "$(imap_moduledir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(imap_moduledir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(imap_moduledir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(imap_moduledir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(imap_moduledir)"; \ + } + +uninstall-imap_moduleLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(imap_module_LTLIBRARIES)'; test -n "$(imap_moduledir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(imap_moduledir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(imap_moduledir)/$$f"; \ + done + +clean-imap_moduleLTLIBRARIES: + -test -z "$(imap_module_LTLIBRARIES)" || rm -f $(imap_module_LTLIBRARIES) + @list='$(imap_module_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-sieve_pluginLTLIBRARIES: $(sieve_plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(sieve_plugin_LTLIBRARIES)'; test -n "$(sieve_plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(sieve_plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sieve_plugindir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(sieve_plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(sieve_plugindir)"; \ + } + +uninstall-sieve_pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(sieve_plugin_LTLIBRARIES)'; test -n "$(sieve_plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(sieve_plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(sieve_plugindir)/$$f"; \ + done + +clean-sieve_pluginLTLIBRARIES: + -test -z "$(sieve_plugin_LTLIBRARIES)" || rm -f $(sieve_plugin_LTLIBRARIES) + @list='$(sieve_plugin_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +lib90_sieve_imapsieve_plugin.la: $(lib90_sieve_imapsieve_plugin_la_OBJECTS) $(lib90_sieve_imapsieve_plugin_la_DEPENDENCIES) $(EXTRA_lib90_sieve_imapsieve_plugin_la_DEPENDENCIES) + $(AM_V_CCLD)$(lib90_sieve_imapsieve_plugin_la_LINK) -rpath $(sieve_plugindir) $(lib90_sieve_imapsieve_plugin_la_OBJECTS) $(lib90_sieve_imapsieve_plugin_la_LIBADD) $(LIBS) + +lib95_imap_sieve_plugin.la: $(lib95_imap_sieve_plugin_la_OBJECTS) $(lib95_imap_sieve_plugin_la_DEPENDENCIES) $(EXTRA_lib95_imap_sieve_plugin_la_DEPENDENCIES) + $(AM_V_CCLD)$(lib95_imap_sieve_plugin_la_LINK) -rpath $(imap_moduledir) $(lib95_imap_sieve_plugin_la_OBJECTS) $(lib95_imap_sieve_plugin_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-imapsieve-environment.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-imapsieve.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imap-sieve-plugin.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imap-sieve-storage.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imap-sieve.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib90_sieve_imapsieve_plugin_la-ext-imapsieve.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib90_sieve_imapsieve_plugin_la-sieve-imapsieve-plugin.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +lib90_sieve_imapsieve_plugin_la-ext-imapsieve.lo: ext-imapsieve.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib90_sieve_imapsieve_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib90_sieve_imapsieve_plugin_la-ext-imapsieve.lo -MD -MP -MF $(DEPDIR)/lib90_sieve_imapsieve_plugin_la-ext-imapsieve.Tpo -c -o lib90_sieve_imapsieve_plugin_la-ext-imapsieve.lo `test -f 'ext-imapsieve.c' || echo '$(srcdir)/'`ext-imapsieve.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib90_sieve_imapsieve_plugin_la-ext-imapsieve.Tpo $(DEPDIR)/lib90_sieve_imapsieve_plugin_la-ext-imapsieve.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ext-imapsieve.c' object='lib90_sieve_imapsieve_plugin_la-ext-imapsieve.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib90_sieve_imapsieve_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib90_sieve_imapsieve_plugin_la-ext-imapsieve.lo `test -f 'ext-imapsieve.c' || echo '$(srcdir)/'`ext-imapsieve.c + +lib90_sieve_imapsieve_plugin_la-sieve-imapsieve-plugin.lo: sieve-imapsieve-plugin.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib90_sieve_imapsieve_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib90_sieve_imapsieve_plugin_la-sieve-imapsieve-plugin.lo -MD -MP -MF $(DEPDIR)/lib90_sieve_imapsieve_plugin_la-sieve-imapsieve-plugin.Tpo -c -o lib90_sieve_imapsieve_plugin_la-sieve-imapsieve-plugin.lo `test -f 'sieve-imapsieve-plugin.c' || echo '$(srcdir)/'`sieve-imapsieve-plugin.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib90_sieve_imapsieve_plugin_la-sieve-imapsieve-plugin.Tpo $(DEPDIR)/lib90_sieve_imapsieve_plugin_la-sieve-imapsieve-plugin.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sieve-imapsieve-plugin.c' object='lib90_sieve_imapsieve_plugin_la-sieve-imapsieve-plugin.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib90_sieve_imapsieve_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib90_sieve_imapsieve_plugin_la-sieve-imapsieve-plugin.lo `test -f 'sieve-imapsieve-plugin.c' || echo '$(srcdir)/'`sieve-imapsieve-plugin.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(imap_moduledir)" "$(DESTDIR)$(sieve_plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-imap_moduleLTLIBRARIES clean-libtool \ + clean-sieve_pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-imapsieve-environment.Plo + -rm -f ./$(DEPDIR)/ext-imapsieve.Plo + -rm -f ./$(DEPDIR)/imap-sieve-plugin.Plo + -rm -f ./$(DEPDIR)/imap-sieve-storage.Plo + -rm -f ./$(DEPDIR)/imap-sieve.Plo + -rm -f ./$(DEPDIR)/lib90_sieve_imapsieve_plugin_la-ext-imapsieve.Plo + -rm -f ./$(DEPDIR)/lib90_sieve_imapsieve_plugin_la-sieve-imapsieve-plugin.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-imap_moduleLTLIBRARIES \ + install-sieve_pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ext-imapsieve-environment.Plo + -rm -f ./$(DEPDIR)/ext-imapsieve.Plo + -rm -f ./$(DEPDIR)/imap-sieve-plugin.Plo + -rm -f ./$(DEPDIR)/imap-sieve-storage.Plo + -rm -f ./$(DEPDIR)/imap-sieve.Plo + -rm -f ./$(DEPDIR)/lib90_sieve_imapsieve_plugin_la-ext-imapsieve.Plo + -rm -f ./$(DEPDIR)/lib90_sieve_imapsieve_plugin_la-sieve-imapsieve-plugin.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-imap_moduleLTLIBRARIES \ + uninstall-sieve_pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-imap_moduleLTLIBRARIES clean-libtool \ + clean-sieve_pluginLTLIBRARIES cscopelist-am ctags ctags-am \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am \ + install-imap_moduleLTLIBRARIES install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-sieve_pluginLTLIBRARIES install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am \ + uninstall-imap_moduleLTLIBRARIES \ + uninstall-sieve_pluginLTLIBRARIES + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/plugins/imapsieve/ext-imapsieve-common.h b/pigeonhole/src/plugins/imapsieve/ext-imapsieve-common.h new file mode 100644 index 0000000..d3e69cd --- /dev/null +++ b/pigeonhole/src/plugins/imapsieve/ext-imapsieve-common.h @@ -0,0 +1,29 @@ +#ifndef EXT_IMAPSIEVE_COMMON_H +#define EXT_IMAPSIEVE_COMMON_H + +#include "sieve-extensions.h" + +#include "imap-sieve.h" + +/* + * Extensions + */ + +extern const struct sieve_extension_def imapsieve_extension; +extern const struct sieve_extension_def imapsieve_extension_dummy; + +extern const struct sieve_extension_def vnd_imapsieve_extension; +extern const struct sieve_extension_def vnd_imapsieve_extension_dummy; + +/* + * Environment items + */ + +void ext_imapsieve_environment_items_register + (const struct sieve_extension *ext, + const struct sieve_runtime_env *renv); +void ext_imapsieve_environment_vendor_items_register + (const struct sieve_extension *ext, + const struct sieve_runtime_env *renv); + +#endif diff --git a/pigeonhole/src/plugins/imapsieve/ext-imapsieve-environment.c b/pigeonhole/src/plugins/imapsieve/ext-imapsieve-environment.c new file mode 100644 index 0000000..2b61cd4 --- /dev/null +++ b/pigeonhole/src/plugins/imapsieve/ext-imapsieve-environment.c @@ -0,0 +1,184 @@ +/* Copyright (c) 2016-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "mail-storage.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-runtime.h" + +#include "sieve-ext-environment.h" + +#include "ext-imapsieve-common.h" + +/* + * Environment items + */ + +/* imap.user */ + +static const char * +envit_imap_user_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + return eenv->svinst->username; +} + +const struct sieve_environment_item imap_user_env_item = { + .name = "imap.user", + .get_value = envit_imap_user_get_value +}; + +/* imap.email */ + +static const char * +envit_imap_email_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct smtp_address *user_email = + sieve_get_user_email(eenv->svinst); + + if (user_email == NULL) + return NULL; + return smtp_address_encode(user_email); +} + +const struct sieve_environment_item imap_email_env_item = { + .name = "imap.email", + .get_value = envit_imap_email_get_value +}; + +/* imap.cause */ + +static const char * +envit_imap_cause_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_script_env *senv = eenv->scriptenv; + struct imap_sieve_context *isctx = + (struct imap_sieve_context *)senv->script_context; + + return isctx->event.cause; +} + +const struct sieve_environment_item imap_cause_env_item = { + .name = "imap.cause", + .get_value = envit_imap_cause_get_value +}; + +/* imap.mailbox */ + +static const char * +envit_imap_mailbox_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_message_data *msgdata = eenv->msgdata; + + return mailbox_get_vname(msgdata->mail->box); +} + +const struct sieve_environment_item imap_mailbox_env_item = { + .name = "imap.mailbox", + .get_value = envit_imap_mailbox_get_value +}; + + +/* imap.changedflags */ + +static const char * +envit_imap_changedflags_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_script_env *senv = eenv->scriptenv; + struct imap_sieve_context *isctx = + (struct imap_sieve_context *)senv->script_context; + + return isctx->event.changed_flags; +} + +const struct sieve_environment_item imap_changedflags_env_item = { + .name = "imap.changedflags", + .get_value = envit_imap_changedflags_get_value +}; + +/* vnd.dovecot.mailbox-from */ + +static const char * +envit_vnd_mailbox_from_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_script_env *senv = eenv->scriptenv; + struct imap_sieve_context *isctx = + (struct imap_sieve_context *)senv->script_context; + + return mailbox_get_vname(isctx->event.src_mailbox); +} + +const struct sieve_environment_item vnd_mailbox_from_env_item = { + .name = "vnd.dovecot.mailbox-from", + .get_value = envit_vnd_mailbox_from_get_value +}; + +/* vnd.dovecot.mailbox-to */ + +static const char * +envit_vnd_mailbox_to_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_script_env *senv = eenv->scriptenv; + struct imap_sieve_context *isctx = + (struct imap_sieve_context *)senv->script_context; + + return mailbox_get_vname(isctx->event.dest_mailbox); +} + +const struct sieve_environment_item vnd_mailbox_to_env_item = { + .name = "vnd.dovecot.mailbox-to", + .get_value = envit_vnd_mailbox_to_get_value +}; + +/* + * Register + */ + +void ext_imapsieve_environment_items_register( + const struct sieve_extension *ext, const struct sieve_runtime_env *renv) +{ + const struct sieve_extension *env_ext = + (const struct sieve_extension *)ext->context; + + sieve_environment_item_register(env_ext, renv->interp, + &imap_user_env_item); + sieve_environment_item_register(env_ext, renv->interp, + &imap_email_env_item); + sieve_environment_item_register(env_ext, renv->interp, + &imap_cause_env_item); + sieve_environment_item_register(env_ext, renv->interp, + &imap_mailbox_env_item); + sieve_environment_item_register(env_ext, renv->interp, + &imap_changedflags_env_item); +} + +void ext_imapsieve_environment_vendor_items_register +(const struct sieve_extension *ext, const struct sieve_runtime_env *renv) +{ + const struct sieve_extension *env_ext = + (const struct sieve_extension *)ext->context; + + sieve_environment_item_register(env_ext, renv->interp, + &vnd_mailbox_from_env_item); + sieve_environment_item_register(env_ext, renv->interp, + &vnd_mailbox_to_env_item); +} diff --git a/pigeonhole/src/plugins/imapsieve/ext-imapsieve.c b/pigeonhole/src/plugins/imapsieve/ext-imapsieve.c new file mode 100644 index 0000000..64dfc07 --- /dev/null +++ b/pigeonhole/src/plugins/imapsieve/ext-imapsieve.c @@ -0,0 +1,168 @@ +/* Copyright (c) 2016-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension imapsieve + * ------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 6785 + * Implementation: full + * Status: experimental + * + */ + +#include "lib.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-binary.h" + +#include "sieve-validator.h" +#include "sieve-interpreter.h" + +#include "sieve-ext-environment.h" + +#include "ext-imapsieve-common.h" + +/* + * Extension + */ + +static bool ext_imapsieve_load + (const struct sieve_extension *ext, void **context); +static bool ext_vnd_imapsieve_load + (const struct sieve_extension *ext, void **context); +static bool ext_vnd_imapsieve_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +static bool ext_imapsieve_interpreter_load + (const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED); + +#ifdef __IMAPSIEVE_DUMMY +const struct sieve_extension_def imapsieve_extension_dummy = { +#else +const struct sieve_extension_def imapsieve_extension = { +#endif + .name = "imapsieve", + .load = ext_imapsieve_load, + .interpreter_load = ext_imapsieve_interpreter_load +}; + +#ifdef __IMAPSIEVE_DUMMY +const struct sieve_extension_def vnd_imapsieve_extension_dummy = { +#else +const struct sieve_extension_def vnd_imapsieve_extension = { +#endif + .name = "vnd.dovecot.imapsieve", + .load = ext_vnd_imapsieve_load, + .interpreter_load = ext_imapsieve_interpreter_load, + .validator_load = ext_vnd_imapsieve_validator_load +}; + +/* + * Context + */ + +static bool ext_imapsieve_load +(const struct sieve_extension *ext, void **context) +{ + *context = (void*) + sieve_ext_environment_require_extension(ext->svinst); + return TRUE; +} + +static bool ext_vnd_imapsieve_load +(const struct sieve_extension *ext, void **context) +{ + *context = (void*)sieve_extension_require +#ifdef __IMAPSIEVE_DUMMY + (ext->svinst, &imapsieve_extension_dummy, TRUE); +#else + (ext->svinst, &imapsieve_extension, TRUE); +#endif + return TRUE; +} + +/* + * Validator + */ + +static bool ext_vnd_imapsieve_validator_load +(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_validator *valdtr) +{ + const struct sieve_extension *ims_ext; + + /* Load environment extension implicitly */ + + ims_ext = sieve_validator_extension_load_implicit +#ifdef __IMAPSIEVE_DUMMY + (valdtr, imapsieve_extension_dummy.name); +#else + (valdtr, imapsieve_extension.name); +#endif + if ( ims_ext == NULL ) + return FALSE; + + return TRUE; +} + +/* + * Interpreter + */ + +static int ext_imapsieve_interpreter_run + (const struct sieve_extension *this_ext, + const struct sieve_runtime_env *renv, + void *context, bool deferred); + +const struct sieve_interpreter_extension +imapsieve_interpreter_extension = { +#ifdef __IMAPSIEVE_DUMMY + .ext_def = &imapsieve_extension_dummy, +#else + .ext_def = &imapsieve_extension, +#endif + .run = ext_imapsieve_interpreter_run +}; + +static bool ext_imapsieve_interpreter_load +(const struct sieve_extension *ext ATTR_UNUSED, + const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + sieve_interpreter_extension_register(renv->interp, + ext, &imapsieve_interpreter_extension, NULL); + return TRUE; +} + +#ifdef __IMAPSIEVE_DUMMY +static int ext_imapsieve_interpreter_run +(const struct sieve_extension *ext ATTR_UNUSED, + const struct sieve_runtime_env *renv, + void *context ATTR_UNUSED, bool deferred) +{ + if ( !deferred ) { + sieve_runtime_error(renv, NULL, + "the imapsieve extension cannot be used outside IMAP"); + } + return SIEVE_EXEC_FAILURE; +} +#else +static int ext_imapsieve_interpreter_run +(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + void *context ATTR_UNUSED, bool deferred ATTR_UNUSED) +{ + if (ext->def == &vnd_imapsieve_extension) { + const struct sieve_extension *ims_ext = + (const struct sieve_extension *)ext->context; + ext_imapsieve_environment_vendor_items_register(ims_ext, renv); + } else { + ext_imapsieve_environment_items_register(ext, renv); + } + return SIEVE_EXEC_OK; +} +#endif diff --git a/pigeonhole/src/plugins/imapsieve/imap-sieve-plugin.c b/pigeonhole/src/plugins/imapsieve/imap-sieve-plugin.c new file mode 100644 index 0000000..0c9b52e --- /dev/null +++ b/pigeonhole/src/plugins/imapsieve/imap-sieve-plugin.c @@ -0,0 +1,60 @@ +/* Copyright (c) 2016-2018 Pigeonhole authors, see the included COPYING file */ + +#include "imap-common.h" +#include "str.h" + +#include "imap-sieve.h" +#include "imap-sieve-storage.h" + +#include "imap-sieve-plugin.h" + +static struct module *imap_sieve_module; +static imap_client_created_func_t *next_hook_client_created; + +/* + * Client + */ + +static void imap_sieve_client_created(struct client **clientp) +{ + struct client *client = *clientp; + struct mail_user *user = client->user; + const char *url = NULL; + + if (mail_user_is_plugin_loaded(user, imap_sieve_module)) { + url = mail_user_plugin_getenv(user, "imapsieve_url"); + // FIXME: parse the URL and report error if it is bad + if (url != NULL && strncasecmp(url, "sieve:", 6) == 0) { + client_add_capability(client, t_strconcat( + "IMAPSIEVE=", url, NULL)); + } else { + url = NULL; + } + + imap_sieve_storage_client_created(client, (url != NULL)); + } + + if (next_hook_client_created != NULL) + next_hook_client_created(clientp); +} + +/* + * Plugin + */ + +const char *imap_sieve_plugin_version = DOVECOT_ABI_VERSION; +const char imap_sieve_plugin_binary_dependency[] = "imap"; + +void imap_sieve_plugin_init(struct module *module) +{ + imap_sieve_module = module; + next_hook_client_created = + imap_client_created_hook_set(imap_sieve_client_created); + imap_sieve_storage_init(module); +} + +void imap_sieve_plugin_deinit(void) +{ + imap_sieve_storage_deinit(); + imap_client_created_hook_set(next_hook_client_created); +} diff --git a/pigeonhole/src/plugins/imapsieve/imap-sieve-plugin.h b/pigeonhole/src/plugins/imapsieve/imap-sieve-plugin.h new file mode 100644 index 0000000..0271710 --- /dev/null +++ b/pigeonhole/src/plugins/imapsieve/imap-sieve-plugin.h @@ -0,0 +1,11 @@ +#ifndef IMAP_SIEVE_PLUGIN_H +#define IMAP_SIEVE_PLUGIN_H + +struct module; + +extern const char imap_sieve_plugin_binary_dependency[]; + +void imap_sieve_plugin_init(struct module *module); +void imap_sieve_plugin_deinit(void); + +#endif diff --git a/pigeonhole/src/plugins/imapsieve/imap-sieve-storage.c b/pigeonhole/src/plugins/imapsieve/imap-sieve-storage.c new file mode 100644 index 0000000..f8e5efe --- /dev/null +++ b/pigeonhole/src/plugins/imapsieve/imap-sieve-storage.c @@ -0,0 +1,1273 @@ +/* Copyright (c) 2016-2018 Pigeonhole authors, see the included COPYING file */ + +#include "imap-common.h" +#include "array.h" +#include "hash.h" +#include "str.h" +#include "istream.h" +#include "ostream.h" +#include "module-context.h" +#include "mail-user.h" +#include "mail-storage-private.h" +#include "mailbox-attribute.h" +#include "mailbox-list-private.h" +#include "imap-match.h" +#include "imap-util.h" + +#include "imap-sieve.h" +#include "imap-sieve-storage.h" + +#define MAILBOX_ATTRIBUTE_IMAPSIEVE_SCRIPT "imapsieve/script" +#define MAIL_SERVER_ATTRIBUTE_IMAPSIEVE_SCRIPT "imapsieve/script" + +#define IMAP_SIEVE_USER_CONTEXT(obj) \ + MODULE_CONTEXT(obj, imap_sieve_user_module) +#define IMAP_SIEVE_USER_CONTEXT_REQUIRE(obj) \ + MODULE_CONTEXT_REQUIRE(obj, imap_sieve_user_module) +#define IMAP_SIEVE_CONTEXT(obj) \ + MODULE_CONTEXT(obj, imap_sieve_storage_module) +#define IMAP_SIEVE_CONTEXT_REQUIRE(obj) \ + MODULE_CONTEXT_REQUIRE(obj, imap_sieve_storage_module) +#define IMAP_SIEVE_MAIL_CONTEXT(obj) \ + MODULE_CONTEXT_REQUIRE(obj, imap_sieve_mail_module) + +struct imap_sieve_mailbox_rule; +struct imap_sieve_user; +struct imap_sieve_mailbox_event; +struct imap_sieve_mailbox_transaction; +struct imap_sieve_mail; + +enum imap_sieve_command { + IMAP_SIEVE_CMD_NONE = 0, + IMAP_SIEVE_CMD_APPEND, + IMAP_SIEVE_CMD_COPY, + IMAP_SIEVE_CMD_MOVE, + IMAP_SIEVE_CMD_STORE, + IMAP_SIEVE_CMD_OTHER +}; + +ARRAY_DEFINE_TYPE(imap_sieve_mailbox_rule, + struct imap_sieve_mailbox_rule *); +ARRAY_DEFINE_TYPE(imap_sieve_mailbox_event, + struct imap_sieve_mailbox_event); + +HASH_TABLE_DEFINE_TYPE(imap_sieve_mailbox_rule, + struct imap_sieve_mailbox_rule *, + struct imap_sieve_mailbox_rule *); + +struct imap_sieve_mailbox_rule { + unsigned int index; + const char *mailbox; + const char *from; + const char *const *causes; + const char *before, *after; + const char *copy_source_after; +}; + +struct imap_sieve_user { + union mail_user_module_context module_ctx; + struct client *client; + struct imap_sieve *isieve; + + enum imap_sieve_command cur_cmd; + + HASH_TABLE_TYPE(imap_sieve_mailbox_rule) mbox_rules; + ARRAY_TYPE(imap_sieve_mailbox_rule) mbox_patterns; + + bool sieve_active:1; + bool user_script:1; + bool expunge_discarded:1; +}; + +struct imap_sieve_mailbox_event { + uint32_t dest_mail_uid, src_mail_uid; + unsigned int save_seq; + + const char *changed_flags; +}; + +struct imap_sieve_mailbox_transaction { + pool_t pool; + + union mailbox_transaction_module_context module_ctx; + + struct mailbox *src_box; + struct mailbox_transaction_context *src_mail_trans; + + ARRAY_TYPE(imap_sieve_mailbox_event) events; +}; + +struct imap_sieve_mail { + union mail_module_context module_ctx; + + string_t *flags; +}; + +static MODULE_CONTEXT_DEFINE_INIT(imap_sieve_user_module, + &mail_user_module_register); +static MODULE_CONTEXT_DEFINE_INIT(imap_sieve_storage_module, + &mail_storage_module_register); +static MODULE_CONTEXT_DEFINE_INIT(imap_sieve_mail_module, + &mail_module_register); + +static void +imap_sieve_mailbox_rules_get(struct mail_user *user, + struct mailbox *dst_box, struct mailbox *src_box, + const char *cause, + ARRAY_TYPE(imap_sieve_mailbox_rule) *rules); + +/* + * Logging + */ + +static inline void +imap_sieve_debug(struct mail_user *user, + const char *format, ...) ATTR_FORMAT(2, 3); +static inline void +imap_sieve_debug(struct mail_user *user, + const char *format, ...) +{ + va_list args; + + if (user->mail_debug) { + va_start(args, format); + i_debug("imapsieve: %s", + t_strdup_vprintf(format, args)); + va_end(args); + } +} + +static inline void +imap_sieve_warning(struct mail_user *user ATTR_UNUSED, + const char *format, ...) ATTR_FORMAT(2, 3); +static inline void +imap_sieve_warning(struct mail_user *user ATTR_UNUSED, + const char *format, ...) +{ + va_list args; + + va_start(args, format); + i_warning("imapsieve: %s", + t_strdup_vprintf(format, args)); + va_end(args); +} + +static inline void +imap_sieve_mailbox_debug(struct mailbox *box, + const char *format, ...) ATTR_FORMAT(2, 3); +static inline void +imap_sieve_mailbox_debug(struct mailbox *box, + const char *format, ...) +{ + va_list args; + + if (box->storage->user->mail_debug) { + va_start(args, format); + i_debug("imapsieve: mailbox %s: %s", + mailbox_get_vname(box), + t_strdup_vprintf(format, args)); + va_end(args); + } +} + +static inline void +imap_sieve_mailbox_warning(struct mailbox *box, + const char *format, ...) ATTR_FORMAT(2, 3); +static inline void +imap_sieve_mailbox_warning(struct mailbox *box, + const char *format, ...) +{ + va_list args; + + va_start(args, format); + i_warning("imapsieve: mailbox %s: %s", + mailbox_get_vname(box), + t_strdup_vprintf(format, args)); + va_end(args); +} + +static inline void +imap_sieve_mailbox_error(struct mailbox *box, + const char *format, ...) ATTR_FORMAT(2, 3); +static inline void +imap_sieve_mailbox_error(struct mailbox *box, + const char *format, ...) +{ + va_list args; + + va_start(args, format); + i_error("imapsieve: mailbox %s: %s", + mailbox_get_vname(box), + t_strdup_vprintf(format, args)); + va_end(args); +} + +/* + * Events + */ + +static int imap_sieve_mailbox_get_script_real +(struct mailbox *box, + const char **script_name_r) +{ + struct mail_user *user = box->storage->user; + struct mail_attribute_value value; + int ret; + + *script_name_r = NULL; + + /* get the name of the Sieve script from mailbox METADATA */ + if ((ret=mailbox_attribute_get(box, MAIL_ATTRIBUTE_TYPE_SHARED, + MAILBOX_ATTRIBUTE_IMAPSIEVE_SCRIPT, &value)) < 0) { + imap_sieve_mailbox_error(box, + "Failed to read /shared/" + MAILBOX_ATTRIBUTE_IMAPSIEVE_SCRIPT" " + "mailbox attribute: %s", + mailbox_get_last_internal_error(box, NULL)); + return -1; + } + + if (ret > 0) { + imap_sieve_mailbox_debug(box, + "Mailbox attribute /shared/" + MAILBOX_ATTRIBUTE_IMAPSIEVE_SCRIPT" " + "points to Sieve script `%s'", value.value); + + /* if not found, get the name of the Sieve script from + server METADATA */ + } else { + struct mail_namespace *ns; + struct mailbox *inbox; + + imap_sieve_mailbox_debug(box, + "Mailbox attribute /shared/" + MAILBOX_ATTRIBUTE_IMAPSIEVE_SCRIPT" " + "not found"); + + ns = mail_namespace_find_inbox(user->namespaces); + inbox = mailbox_alloc(ns->list, "INBOX", + MAILBOX_FLAG_READONLY); + ret = mailbox_attribute_get(inbox, + MAIL_ATTRIBUTE_TYPE_SHARED, + MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER + MAILBOX_ATTRIBUTE_IMAPSIEVE_SCRIPT, &value); + + if (ret <= 0) { + if (ret < 0) { + imap_sieve_mailbox_error(box, + "Failed to read /shared/" + MAIL_SERVER_ATTRIBUTE_IMAPSIEVE_SCRIPT" " + "server attribute: %s", + mailbox_get_last_internal_error(inbox, NULL)); + } else if (ret == 0) { + imap_sieve_mailbox_debug(box, + "Server attribute /shared/" + MAIL_SERVER_ATTRIBUTE_IMAPSIEVE_SCRIPT" " + "not found"); + } + mailbox_free(&inbox); + return ret; + } + mailbox_free(&inbox); + + imap_sieve_mailbox_debug(box, + "Server attribute /shared/" + MAIL_SERVER_ATTRIBUTE_IMAPSIEVE_SCRIPT" " + "points to Sieve script `%s'", value.value); + } + + *script_name_r = value.value; + return 1; +} + +static int imap_sieve_mailbox_get_script +(struct mailbox *box, const char **script_name_r) +{ + int ret; + + ret = imap_sieve_mailbox_get_script_real + (box, script_name_r); + return ret; +} + +static struct imap_sieve_mailbox_event * +imap_sieve_create_mailbox_event +(struct mailbox_transaction_context *t, struct mail *dest_mail) +{ + struct imap_sieve_mailbox_transaction *ismt = IMAP_SIEVE_CONTEXT_REQUIRE(t); + struct imap_sieve_mailbox_event *event; + + if (!array_is_created(&ismt->events)) + i_array_init(&ismt->events, 64); + + event = array_append_space(&ismt->events); + event->save_seq = t->save_count; + event->dest_mail_uid = dest_mail->uid; + return event; +} + +static void imap_sieve_add_mailbox_event +(struct mailbox_transaction_context *t, + struct mail *dest_mail, struct mailbox *src_box, + const char *changed_flags) +{ + struct imap_sieve_mailbox_transaction *ismt = IMAP_SIEVE_CONTEXT_REQUIRE(t); + struct imap_sieve_mailbox_event *event; + + i_assert(ismt->src_box == NULL || ismt->src_box == src_box); + ismt->src_box = src_box; + + event = imap_sieve_create_mailbox_event(t, dest_mail); + event->changed_flags = p_strdup(ismt->pool, changed_flags); +} + +static void imap_sieve_add_mailbox_copy_event +(struct mailbox_transaction_context *t, + struct mail *dest_mail, struct mail *src_mail) +{ + struct imap_sieve_mailbox_transaction *ismt = IMAP_SIEVE_CONTEXT_REQUIRE(t); + struct imap_sieve_mailbox_event *event; + + i_assert(ismt->src_box == NULL || ismt->src_box == src_mail->box); + i_assert(ismt->src_mail_trans == NULL || + ismt->src_mail_trans == src_mail->transaction); + + ismt->src_box = src_mail->box; + ismt->src_mail_trans = src_mail->transaction; + + event = imap_sieve_create_mailbox_event(t, dest_mail); + event->src_mail_uid = src_mail->uid; +} + +/* + * Mail + */ + +static void +imap_sieve_mail_update_flags(struct mail *_mail, + enum modify_type modify_type, enum mail_flags flags) +{ + struct mail_private *mail = (struct mail_private *)_mail; + struct imap_sieve_mail *ismail = IMAP_SIEVE_MAIL_CONTEXT(mail); + enum mail_flags old_flags, new_flags, changed_flags; + + old_flags = mail_get_flags(_mail); + ismail->module_ctx.super.update_flags(_mail, modify_type, flags); + new_flags = mail_get_flags(_mail); + + changed_flags = old_flags ^ new_flags; + if (changed_flags == 0) + return; + + if (ismail->flags == NULL) + ismail->flags = str_new(default_pool, 64); + imap_write_flags(ismail->flags, changed_flags, NULL); +} + +static void +imap_sieve_mail_update_keywords(struct mail *_mail, + enum modify_type modify_type, struct mail_keywords *keywords) +{ + struct mail_private *mail = (struct mail_private *)_mail; + struct imap_sieve_mail *ismail = IMAP_SIEVE_MAIL_CONTEXT(mail); + const char *const *old_keywords, *const *new_keywords; + unsigned int i, j; + + old_keywords = mail_get_keywords(_mail); + ismail->module_ctx.super.update_keywords(_mail, modify_type, keywords); + new_keywords = mail_get_keywords(_mail); + + if (ismail->flags == NULL) + ismail->flags = str_new(default_pool, 64); + + /* Removed flags */ + for (i = 0; old_keywords[i] != NULL; i++) { + for (j = 0; new_keywords[j] != NULL; j++) { + if (strcmp(old_keywords[i], new_keywords[j]) == 0) + break; + } + if (new_keywords[j] == NULL) { + if (str_len(ismail->flags) > 0) + str_append_c(ismail->flags, ' '); + str_append(ismail->flags, old_keywords[i]); + } + } + + /* Added flags */ + for (i = 0; new_keywords[i] != NULL; i++) { + for (j = 0; old_keywords[j] != NULL; j++) { + if (strcmp(new_keywords[i], old_keywords[j]) == 0) + break; + } + if (old_keywords[j] == NULL) { + if (str_len(ismail->flags) > 0) + str_append_c(ismail->flags, ' '); + str_append(ismail->flags, new_keywords[i]); + } + } +} + +static void imap_sieve_mail_close(struct mail *_mail) +{ + struct mail_private *mail = (struct mail_private *)_mail; + struct mailbox_transaction_context *t = _mail->transaction; + struct imap_sieve_mail *ismail = IMAP_SIEVE_MAIL_CONTEXT(mail); + + if (ismail->flags != NULL && str_len(ismail->flags) > 0) { + if (!_mail->expunged) { + imap_sieve_mailbox_debug(_mail->box, + "FLAG event (changed flags: %s)", + str_c(ismail->flags)); + + imap_sieve_add_mailbox_event(t, + _mail, _mail->box, str_c(ismail->flags)); + } + str_truncate(ismail->flags, 0); + } + + ismail->module_ctx.super.close(_mail); +} + +static void imap_sieve_mail_free(struct mail *_mail) +{ + struct mail_private *mail = (struct mail_private *)_mail; + struct imap_sieve_mail *ismail = IMAP_SIEVE_MAIL_CONTEXT(mail); + string_t *flags = ismail->flags; + + ismail->module_ctx.super.free(_mail); + + if (flags != NULL) + str_free(&flags); +} + +static void imap_sieve_mail_allocated(struct mail *_mail) +{ + struct mail_private *mail = (struct mail_private *)_mail; + struct imap_sieve_mailbox_transaction *ismt = + IMAP_SIEVE_CONTEXT(_mail->transaction); + struct mail_user *user = _mail->box->storage->user; + struct imap_sieve_user *isuser = + IMAP_SIEVE_USER_CONTEXT_REQUIRE(user); + struct mail_vfuncs *v = mail->vlast; + struct imap_sieve_mail *ismail; + + if (ismt == NULL || isuser->sieve_active) + return; + + ismail = p_new(mail->pool, struct imap_sieve_mail, 1); + ismail->module_ctx.super = *v; + mail->vlast = &ismail->module_ctx.super; + + v->close = imap_sieve_mail_close; + v->free = imap_sieve_mail_free; + v->update_flags = imap_sieve_mail_update_flags; + v->update_keywords = imap_sieve_mail_update_keywords; + MODULE_CONTEXT_SET(mail, imap_sieve_mail_module, ismail); +} + +/* + * Save/copy + */ + +static int +imap_sieve_mailbox_copy(struct mail_save_context *ctx, struct mail *mail) +{ + struct mailbox_transaction_context *t = ctx->transaction; + struct mail_storage *storage = t->box->storage; + struct mail_user *user = storage->user; + struct imap_sieve_user *isuser = + IMAP_SIEVE_USER_CONTEXT_REQUIRE(user); + union mailbox_module_context *lbox = + IMAP_SIEVE_CONTEXT_REQUIRE(t->box); + struct imap_sieve_mailbox_transaction *ismt = + IMAP_SIEVE_CONTEXT(t); + + if (lbox->super.copy(ctx, mail) < 0) + return -1; + + if (ismt != NULL && !isuser->sieve_active && + !ctx->dest_mail->expunged && + (isuser->cur_cmd == IMAP_SIEVE_CMD_COPY || + isuser->cur_cmd == IMAP_SIEVE_CMD_MOVE)) { + imap_sieve_mailbox_debug(t->box, "%s event", + (isuser->cur_cmd == IMAP_SIEVE_CMD_COPY ? + "COPY" : "MOVE")); + imap_sieve_add_mailbox_copy_event(t, ctx->dest_mail, + ctx->copy_src_mail); + } + + return 0; +} + +static int +imap_sieve_mailbox_save_finish(struct mail_save_context *ctx) +{ + struct mailbox_transaction_context *t = ctx->transaction; + struct mailbox *box = t->box; + struct imap_sieve_mailbox_transaction *ismt = IMAP_SIEVE_CONTEXT(t); + union mailbox_module_context *lbox = IMAP_SIEVE_CONTEXT_REQUIRE(box); + struct mail_user *user = box->storage->user; + struct imap_sieve_user *isuser = IMAP_SIEVE_USER_CONTEXT_REQUIRE(user); + struct mail *dest_mail = ctx->copying_via_save ? NULL : ctx->dest_mail; + + if (lbox->super.save_finish(ctx) < 0) + return -1; + + if (ismt != NULL && !isuser->sieve_active && + dest_mail != NULL && !dest_mail->expunged && + isuser->cur_cmd == IMAP_SIEVE_CMD_APPEND) { + + imap_sieve_mailbox_debug(t->box, "APPEND event"); + imap_sieve_add_mailbox_event(t, dest_mail, box, NULL); + } + return 0; +} + +/* + * Mailbox + */ + +static struct mailbox_transaction_context * +imap_sieve_mailbox_transaction_begin(struct mailbox *box, + enum mailbox_transaction_flags flags, + const char *reason) +{ + union mailbox_module_context *lbox = IMAP_SIEVE_CONTEXT_REQUIRE(box); + struct mail_user *user = box->storage->user; + struct imap_sieve_user *isuser = IMAP_SIEVE_USER_CONTEXT(user); + struct mailbox_transaction_context *t; + struct imap_sieve_mailbox_transaction *ismt; + pool_t pool; + + /* commence parent transaction */ + t = lbox->super.transaction_begin(box, flags, reason); + + if (isuser == NULL || isuser->sieve_active || + isuser->cur_cmd == IMAP_SIEVE_CMD_NONE) + return t; + + i_assert(isuser->client != NULL); + + pool = pool_alloconly_create("imap_sieve_mailbox_transaction", 1024); + ismt = p_new(pool, struct imap_sieve_mailbox_transaction, 1); + ismt->pool = pool; + MODULE_CONTEXT_SET(t, imap_sieve_storage_module, ismt); + + return t; +} + +static void +imap_sieve_mailbox_transaction_free +(struct imap_sieve_mailbox_transaction *ismt) +{ + if (array_is_created(&ismt->events)) + array_free(&ismt->events); + pool_unref(&ismt->pool); +} + +static void +imap_sieve_mailbox_run_copy_source( + struct imap_sieve_mailbox_transaction *ismt, + struct imap_sieve_run *isrun, + const struct imap_sieve_mailbox_event *mevent, + struct mail **src_mail, bool *fatal_r) +{ + struct mailbox *src_box = ismt->src_box; + int ret; + + *fatal_r = FALSE; + + if (isrun == NULL) + return; + + i_assert(ismt->src_mail_trans->box == src_box); + i_assert(mevent->src_mail_uid > 0); + + if (*src_mail == NULL) + *src_mail = mail_alloc(ismt->src_mail_trans, 0, NULL); + + /* Select source message */ + if (!mail_set_uid(*src_mail, mevent->src_mail_uid)) { + imap_sieve_mailbox_warning(src_box, + "Failed to find source message for Sieve event " + "(UID=%llu)", (unsigned long long)mevent->src_mail_uid); + return; + } + + imap_sieve_mailbox_debug(src_box, + "Running copy_source_after scripts."); + + /* Run scripts for source mail */ + ret = imap_sieve_run_mail(isrun, *src_mail, NULL, fatal_r); + if (ret > 0) { + /* Discard */ + mail_update_flags(*src_mail, MODIFY_ADD, MAIL_DELETED); + } +} + +static int +imap_sieve_mailbox_transaction_run( + struct imap_sieve_mailbox_transaction *ismt, + struct mailbox *dest_box, + struct mail_transaction_commit_changes *changes) +{ + static const char *wanted_headers[] = { + "From", "To", "Message-ID", "Subject", "Return-Path", + NULL + }; + struct mailbox *src_box = ismt->src_box; + struct mail_user *user = dest_box->storage->user; + struct imap_sieve_user *isuser = IMAP_SIEVE_USER_CONTEXT_REQUIRE(user); + const struct imap_sieve_mailbox_event *mevent; + struct mailbox_header_lookup_ctx *headers_ctx; + struct mailbox_transaction_context *st; + struct mailbox *sbox; + struct imap_sieve_run *isrun, *isrun_src; + struct seq_range_iter siter; + const char *cause, *script_name = NULL; + bool can_discard; + struct mail *mail, *src_mail = NULL; + int ret; + + if (ismt == NULL || !array_is_created(&ismt->events)) { + /* Nothing to do */ + return 0; + } + + i_assert(isuser->client != NULL); + + /* Get user script for this mailbox */ + if (isuser->user_script && imap_sieve_mailbox_get_script + (dest_box, &script_name) < 0) { + return 0; // FIXME: some errors may warrant -1 + } + + /* Make sure IMAPSIEVE is initialized for this user */ + if (isuser->isieve == NULL) + isuser->isieve = imap_sieve_init(isuser->client); + + can_discard = FALSE; + switch (isuser->cur_cmd) { + case IMAP_SIEVE_CMD_APPEND: + cause = "APPEND"; + can_discard = TRUE; + break; + case IMAP_SIEVE_CMD_COPY: + case IMAP_SIEVE_CMD_MOVE: + cause = "COPY"; + can_discard = TRUE; + break; + case IMAP_SIEVE_CMD_STORE: + case IMAP_SIEVE_CMD_OTHER: + cause = "FLAG"; + break; + default: + i_unreached(); + } + + /* Initialize execution */ + T_BEGIN { + ARRAY_TYPE(imap_sieve_mailbox_rule) mbrules; + ARRAY_TYPE(const_string) scripts_before, scripts_after; + ARRAY_TYPE(const_string) scripts_copy_source; + struct imap_sieve_mailbox_rule *rule; + + /* Find matching rules */ + t_array_init(&mbrules, 16); + imap_sieve_mailbox_rules_get + (user, dest_box, src_box, cause, &mbrules); + + /* Apply all matched rules */ + t_array_init(&scripts_before, 8); + t_array_init(&scripts_after, 8); + t_array_init(&scripts_copy_source, 4); + array_foreach_elem(&mbrules, rule) { + if (rule->before != NULL) + array_append(&scripts_before, &rule->before, 1); + if (rule->after != NULL) + array_append(&scripts_after, &rule->after, 1); + if (rule->copy_source_after != NULL) + array_append(&scripts_copy_source, &rule->copy_source_after, 1); + } + (void)array_append_space(&scripts_before); + (void)array_append_space(&scripts_after); + + /* Initialize */ + ret = imap_sieve_run_init + (isuser->isieve, dest_box, src_box, cause, script_name, + array_idx(&scripts_before, 0), + array_idx(&scripts_after, 0), &isrun); + + /* Initialize source script execution */ + isrun_src = NULL; + if (ret > 0 && ismt->src_mail_trans != NULL && + isuser->cur_cmd == IMAP_SIEVE_CMD_COPY && + array_count(&scripts_copy_source) > 0) { + const char *no_scripts = NULL; + + (void)array_append_space(&scripts_copy_source); + if (imap_sieve_run_init(isuser->isieve, + dest_box, src_box, cause, NULL, + &no_scripts, array_idx(&scripts_copy_source, 0), + &isrun_src) <= 0) + isrun_src = NULL; + } + } T_END; + + if (ret <= 0) { + // FIXME: temp fail should be handled properly + return 0; + } + + /* Get synchronized view on the destination mailbox */ + sbox = mailbox_alloc(dest_box->list, dest_box->vname, 0); + if (mailbox_sync(sbox, 0) < 0) { + mailbox_free(&sbox); + imap_sieve_run_deinit(&isrun); + if (isrun_src != NULL) + imap_sieve_run_deinit(&isrun_src); + return -1; + } + + /* Create transaction for event messages */ + st = mailbox_transaction_begin(sbox, 0, __func__); + headers_ctx = mailbox_header_lookup_init(sbox, wanted_headers); + mail = mail_alloc(st, 0, headers_ctx); + mailbox_header_lookup_unref(&headers_ctx); + + /* Iterate through all events */ + seq_range_array_iter_init(&siter, &changes->saved_uids); + array_foreach(&ismt->events, mevent) { + uint32_t uid; + bool fatal; + + /* Determine UID for saved message */ + if (mevent->dest_mail_uid > 0) + uid = mevent->dest_mail_uid; + else if (!seq_range_array_iter_nth(&siter, mevent->save_seq, + &uid)) { + /* already gone for some reason */ + imap_sieve_mailbox_debug( + sbox, "Message for Sieve event gone"); + continue; + } + + /* Select event message */ + i_assert(uid > 0); + if (!mail_set_uid(mail, uid) || mail->expunged) { + /* already gone for some reason */ + imap_sieve_mailbox_debug(sbox, + "Message for Sieve event gone (UID=%llu)", + (unsigned long long)uid); + continue; + } + + /* Run scripts for this mail */ + ret = imap_sieve_run_mail(isrun, mail, mevent->changed_flags, + &fatal); + if (fatal) + break; + + /* Handle the result */ + if (ret < 0) { + /* Sieve error; keep */ + } else { + if (ret <= 0 || !can_discard) { + /* Keep */ + } else if (!isuser->expunge_discarded) { + /* Mark as \Deleted */ + mail_update_flags(mail, + MODIFY_ADD, MAIL_DELETED); + } else { + /* Expunge */ + mail_expunge(mail); + } + + imap_sieve_mailbox_run_copy_source( + ismt, isrun_src, mevent, &src_mail, &fatal); + if (fatal) + break; + } + } + + /* Cleanup */ + mail_free(&mail); + ret = mailbox_transaction_commit(&st); + if (src_mail != NULL) + mail_free(&src_mail); + imap_sieve_run_deinit(&isrun); + if (isrun_src != NULL) + imap_sieve_run_deinit(&isrun_src); + mailbox_free(&sbox); + return ret; +} + +static int +imap_sieve_mailbox_transaction_commit( + struct mailbox_transaction_context *t, + struct mail_transaction_commit_changes *changes_r) +{ + struct mailbox *box = t->box; + struct mail_user *user = box->storage->user; + struct imap_sieve_mailbox_transaction *ismt = IMAP_SIEVE_CONTEXT(t); + union mailbox_module_context *lbox = IMAP_SIEVE_CONTEXT_REQUIRE(t->box); + struct imap_sieve_user *isuser = IMAP_SIEVE_USER_CONTEXT_REQUIRE(user); + int ret = 0; + + if ((lbox->super.transaction_commit(t, changes_r)) < 0) + ret = -1; + else if (ismt != NULL) { + isuser->sieve_active = TRUE; + if (imap_sieve_mailbox_transaction_run + (ismt, box, changes_r) < 0) + ret = -1; + isuser->sieve_active = FALSE; + } + + if (ismt != NULL) + imap_sieve_mailbox_transaction_free(ismt); + return ret; +} + +static void +imap_sieve_mailbox_transaction_rollback( + struct mailbox_transaction_context *t) +{ + struct imap_sieve_mailbox_transaction *ismt = IMAP_SIEVE_CONTEXT(t); + union mailbox_module_context *lbox = IMAP_SIEVE_CONTEXT_REQUIRE(t->box); + + lbox->super.transaction_rollback(t); + + if (ismt != NULL) + imap_sieve_mailbox_transaction_free(ismt); +} + +static void imap_sieve_mailbox_allocated(struct mailbox *box) +{ + struct mail_user *user = box->storage->user; + struct imap_sieve_user *isuser = IMAP_SIEVE_USER_CONTEXT_REQUIRE(user); + struct mailbox_vfuncs *v = box->vlast; + union mailbox_module_context *lbox; + + if (isuser->client == NULL || isuser->sieve_active || + (box->flags & MAILBOX_FLAG_READONLY) != 0) + return; + + lbox = p_new(box->pool, union mailbox_module_context, 1); + lbox->super = *v; + box->vlast = &lbox->super; + + v->copy = imap_sieve_mailbox_copy; + v->save_finish = imap_sieve_mailbox_save_finish; + v->transaction_begin = imap_sieve_mailbox_transaction_begin; + v->transaction_commit = imap_sieve_mailbox_transaction_commit; + v->transaction_rollback = imap_sieve_mailbox_transaction_rollback; + MODULE_CONTEXT_SET_SELF(box, imap_sieve_storage_module, lbox); +} + +/* + * Mailbox rules + */ + +static unsigned int imap_sieve_mailbox_rule_hash +(const struct imap_sieve_mailbox_rule *rule) +{ + unsigned int hash = str_hash(rule->mailbox); + + if (rule->from != NULL) + hash += str_hash(rule->from); + return hash; +} + +static int imap_sieve_mailbox_rule_cmp +(const struct imap_sieve_mailbox_rule *rule1, + const struct imap_sieve_mailbox_rule *rule2) +{ + int ret; + + if ((ret=strcmp(rule1->mailbox, rule2->mailbox)) != 0) + return ret; + return null_strcmp(rule1->from, rule2->from); +} + +static bool rule_pattern_has_wildcards(const char *pattern) +{ + for (; *pattern != '\0'; pattern++) { + if (*pattern == '%' || *pattern == '*') + return TRUE; + } + return FALSE; +} + +static void +imap_sieve_mailbox_rules_init(struct mail_user *user) +{ + struct imap_sieve_user *isuser = IMAP_SIEVE_USER_CONTEXT_REQUIRE(user); + string_t *identifier; + unsigned int i = 0; + size_t prefix_len; + + if (hash_table_is_created(isuser->mbox_rules)) + return; + + hash_table_create(&isuser->mbox_rules, default_pool, 0, + imap_sieve_mailbox_rule_hash, imap_sieve_mailbox_rule_cmp); + i_array_init(&isuser->mbox_patterns, 8); + + identifier = t_str_new(256); + str_append(identifier, "imapsieve_mailbox"); + prefix_len = str_len(identifier); + + for (i = 1; ; i++) { + struct imap_sieve_mailbox_rule *mbrule; + const char *setval; + size_t id_len; + + str_truncate(identifier, prefix_len); + str_printfa(identifier, "%u", i); + id_len = str_len(identifier); + + str_append(identifier, "_name"); + setval = mail_user_plugin_getenv + (user, str_c(identifier)); + if (setval == NULL || *setval == '\0') + break; + setval = t_str_trim(setval, "\t "); + if (strcasecmp(setval, "INBOX") == 0) + setval = t_str_ucase(setval); + + mbrule = p_new(user->pool, + struct imap_sieve_mailbox_rule, 1); + mbrule->index = i; + mbrule->mailbox = p_strdup(user->pool, setval); + + str_truncate(identifier, id_len); + str_append(identifier, "_from"); + setval = mail_user_plugin_getenv(user, str_c(identifier)); + if (setval != NULL && *setval != '\0') { + setval = t_str_trim(setval, "\t "); + if (strcasecmp(setval, "INBOX") == 0) + setval = t_str_ucase(setval); + mbrule->from = p_strdup(user->pool, setval); + if (strcmp(mbrule->from, "*") == 0) + mbrule->from = NULL; + } + + if ((strcmp(mbrule->mailbox, "*") == 0 || + !rule_pattern_has_wildcards(mbrule->mailbox)) && + (mbrule->from == NULL || + !rule_pattern_has_wildcards(mbrule->from)) && + hash_table_lookup(isuser->mbox_rules, mbrule) != NULL) { + imap_sieve_warning(user, + "Duplicate static mailbox rule [%u] for mailbox `%s' " + "(skipped)", i, mbrule->mailbox); + continue; + } + + str_truncate(identifier, id_len); + str_append(identifier, "_causes"); + setval = mail_user_plugin_getenv(user, str_c(identifier)); + if (setval != NULL && *setval != '\0') { + const char *const *cause; + + mbrule->causes = (const char *const *) + p_strsplit_spaces(user->pool, setval, " \t,"); + + for (cause = mbrule->causes; *cause != NULL; cause++) { + if (!imap_sieve_event_cause_valid(*cause)) + break; + } + if (*cause != NULL) { + imap_sieve_warning(user, + "Static mailbox rule [%u] has invalid event cause `%s' " + "(skipped)", i, *cause); + continue; + } + } + + str_truncate(identifier, id_len); + str_append(identifier, "_before"); + setval = mail_user_plugin_getenv(user, str_c(identifier)); + mbrule->before = p_strdup_empty(user->pool, setval); + + str_truncate(identifier, id_len); + str_append(identifier, "_after"); + setval = mail_user_plugin_getenv(user, str_c(identifier)); + mbrule->after = p_strdup_empty(user->pool, setval); + + str_truncate(identifier, id_len); + str_append(identifier, "_copy_source_after"); + setval = mail_user_plugin_getenv(user, str_c(identifier)); + mbrule->copy_source_after = p_strdup_empty(user->pool, setval); + + if (user->mail_debug) { + imap_sieve_debug(user, "Static mailbox rule [%u]: " + "mailbox=`%s' from=`%s' causes=(%s) => " + "before=%s after=%s%s", + mbrule->index, mbrule->mailbox, + (mbrule->from == NULL ? "*" : mbrule->from), + t_strarray_join(mbrule->causes, " "), + (mbrule->before == NULL ? "(none)" : + t_strconcat("`", mbrule->before, "'", NULL)), + (mbrule->after == NULL ? "(none)" : + t_strconcat("`", mbrule->after, "'", NULL)), + (mbrule->copy_source_after == NULL ? "": + t_strconcat(" copy_source_after=`", + mbrule->copy_source_after, "'", NULL))); + } + + if ((strcmp(mbrule->mailbox, "*") == 0 || + !rule_pattern_has_wildcards(mbrule->mailbox)) && + (mbrule->from == NULL || + !rule_pattern_has_wildcards(mbrule->from))) { + hash_table_insert(isuser->mbox_rules, mbrule, mbrule); + } else { + array_append(&isuser->mbox_patterns, &mbrule, 1); + } + } + + if (i == 0) + imap_sieve_debug(user, "No static mailbox rules"); +} + +static bool +imap_sieve_mailbox_rule_match_cause +(struct imap_sieve_mailbox_rule *rule, const char *cause) +{ + const char *const *cp; + + if (rule->causes == NULL || *rule->causes == NULL) + return TRUE; + + for (cp = rule->causes; *cp != NULL; cp++) { + if (strcasecmp(cause, *cp) == 0) + return TRUE; + } + return FALSE; +} + +static void +imap_sieve_mailbox_rules_match_patterns(struct mail_user *user, + struct mailbox *dst_box, struct mailbox *src_box, + const char *cause, + ARRAY_TYPE(imap_sieve_mailbox_rule) *rules) +{ + struct imap_sieve_user *isuser = IMAP_SIEVE_USER_CONTEXT_REQUIRE(user); + struct imap_sieve_mailbox_rule *rule; + struct mail_namespace *dst_ns, *src_ns; + + if (array_count(&isuser->mbox_patterns) == 0) + return; + + dst_ns = mailbox_get_namespace(dst_box); + src_ns = (src_box == NULL ? NULL : + mailbox_get_namespace(src_box)); + + array_foreach_elem(&isuser->mbox_patterns, rule) { + struct imap_match_glob *glob; + + if (src_ns == NULL && rule->from != NULL) + continue; + if (!imap_sieve_mailbox_rule_match_cause(rule, cause)) + continue; + + if (strcmp(rule->mailbox, "*") != 0) { + glob = imap_match_init(pool_datastack_create(), + rule->mailbox, TRUE, mail_namespace_get_sep(dst_ns)); + if (imap_match(glob, mailbox_get_vname(dst_box)) + != IMAP_MATCH_YES) + continue; + } + if (rule->from != NULL) { + glob = imap_match_init(pool_datastack_create(), + rule->from, TRUE, mail_namespace_get_sep(src_ns)); + if (imap_match(glob, mailbox_get_vname(src_box)) + != IMAP_MATCH_YES) + continue; + } + + imap_sieve_debug(user, + "Matched static mailbox rule [%u]", + rule->index); + array_append(rules, &rule, 1); + } +} + +static void +imap_sieve_mailbox_rules_match(struct mail_user *user, + const char *dst_box, const char *src_box, + const char *cause, + ARRAY_TYPE(imap_sieve_mailbox_rule) *rules) +{ + struct imap_sieve_user *isuser = IMAP_SIEVE_USER_CONTEXT_REQUIRE(user); + struct imap_sieve_mailbox_rule lookup_rule; + struct imap_sieve_mailbox_rule *rule; + + i_zero(&lookup_rule); + lookup_rule.mailbox = dst_box; + lookup_rule.from = src_box; + rule = hash_table_lookup(isuser->mbox_rules, &lookup_rule); + + if (rule != NULL && + imap_sieve_mailbox_rule_match_cause(rule, cause)) { + struct imap_sieve_mailbox_rule *const *rule_idx; + unsigned int insert_idx = array_count(rules); + + /* Insert sorted by rule index */ + array_foreach(rules, rule_idx) { + if (rule->index < (*rule_idx)->index) { + insert_idx = array_foreach_idx(rules, rule_idx); + break; + } + } + array_insert(rules, insert_idx, &rule, 1); + + imap_sieve_debug(user, + "Matched static mailbox rule [%u]", + rule->index); + } +} + +static void +imap_sieve_mailbox_rules_get(struct mail_user *user, + struct mailbox *dst_box, struct mailbox *src_box, + const char *cause, + ARRAY_TYPE(imap_sieve_mailbox_rule) *rules) +{ + const char *dst_name, *src_name; + + imap_sieve_mailbox_rules_init(user); + + imap_sieve_mailbox_rules_match_patterns + (user, dst_box, src_box, cause, rules); + + dst_name = mailbox_get_vname(dst_box); + src_name = (src_box == NULL ? NULL : + mailbox_get_vname(src_box)); + + imap_sieve_mailbox_rules_match + (user, dst_name, src_name, cause, rules); + imap_sieve_mailbox_rules_match + (user, "*", src_name, cause, rules); + if (src_name != NULL) { + imap_sieve_mailbox_rules_match + (user, dst_name, NULL, cause, rules); + imap_sieve_mailbox_rules_match + (user, "*", NULL, cause, rules); + } +} + +/* + * User + */ + +static void imap_sieve_user_deinit(struct mail_user *user) +{ + struct imap_sieve_user *isuser = IMAP_SIEVE_USER_CONTEXT_REQUIRE(user); + + if (isuser->isieve != NULL) + imap_sieve_deinit(&isuser->isieve); + + hash_table_destroy(&isuser->mbox_rules); + if (array_is_created(&isuser->mbox_patterns)) + array_free(&isuser->mbox_patterns); + + isuser->module_ctx.super.deinit(user); +} + +static void imap_sieve_user_created(struct mail_user *user) +{ + struct imap_sieve_user *isuser; + struct mail_user_vfuncs *v = user->vlast; + + isuser = p_new(user->pool, struct imap_sieve_user, 1); + isuser->module_ctx.super = *v; + user->vlast = &isuser->module_ctx.super; + v->deinit = imap_sieve_user_deinit; + MODULE_CONTEXT_SET(user, imap_sieve_user_module, isuser); +} + +/* + * Hooks + */ + +static struct mail_storage_hooks imap_sieve_mail_storage_hooks = { + .mail_user_created = imap_sieve_user_created, + .mailbox_allocated = imap_sieve_mailbox_allocated, + .mail_allocated = imap_sieve_mail_allocated +}; + +/* + * Commands + */ + +static void imap_sieve_command_pre(struct client_command_context *cmd) +{ + struct client *client = cmd->client; + struct mail_user *user = client->user; + struct imap_sieve_user *isuser = IMAP_SIEVE_USER_CONTEXT(user); + + if (isuser == NULL) + return; + + if (strcasecmp(cmd->name, "APPEND") == 0) { + isuser->cur_cmd = IMAP_SIEVE_CMD_APPEND; + } else if (strcasecmp(cmd->name, "COPY") == 0 || + strcasecmp(cmd->name, "UID COPY") == 0) { + isuser->cur_cmd = IMAP_SIEVE_CMD_COPY; + } else if (strcasecmp(cmd->name, "MOVE") == 0 || + strcasecmp(cmd->name, "UID MOVE") == 0) { + isuser->cur_cmd = IMAP_SIEVE_CMD_MOVE; + } else if (strcasecmp(cmd->name, "STORE") == 0 || + strcasecmp(cmd->name, "UID STORE") == 0) { + isuser->cur_cmd = IMAP_SIEVE_CMD_STORE; + } else { + isuser->cur_cmd = IMAP_SIEVE_CMD_OTHER; + } +} + +static void imap_sieve_command_post(struct client_command_context *cmd) +{ + struct client *client = cmd->client; + struct mail_user *user = client->user; + struct imap_sieve_user *isuser = IMAP_SIEVE_USER_CONTEXT(user); + + if (isuser == NULL) + return; + isuser->cur_cmd = IMAP_SIEVE_CMD_NONE; +} + +/* + * Client + */ + +void imap_sieve_storage_client_created(struct client *client, + bool user_script) +{ + struct mail_user *user = client->user; + struct imap_sieve_user *isuser = IMAP_SIEVE_USER_CONTEXT_REQUIRE(user); + const char *set; + + isuser->client = client; + isuser->user_script = user_script; + + set = mail_user_plugin_getenv(user, "imapsieve_expunge_discarded"); + isuser->expunge_discarded = + (set != NULL && strcasecmp(set, "yes") == 0); +} + +/* + * + */ + +void imap_sieve_storage_init(struct module *module) +{ + command_hook_register(imap_sieve_command_pre, imap_sieve_command_post); + mail_storage_hooks_add(module, &imap_sieve_mail_storage_hooks); +} + +void imap_sieve_storage_deinit(void) +{ + mail_storage_hooks_remove(&imap_sieve_mail_storage_hooks); + command_hook_unregister(imap_sieve_command_pre, imap_sieve_command_post); +} diff --git a/pigeonhole/src/plugins/imapsieve/imap-sieve-storage.h b/pigeonhole/src/plugins/imapsieve/imap-sieve-storage.h new file mode 100644 index 0000000..f96860f --- /dev/null +++ b/pigeonhole/src/plugins/imapsieve/imap-sieve-storage.h @@ -0,0 +1,10 @@ +#ifndef IMAP_SIEVE_STORAGE_H +#define IMAP_SIEVE_STORAGE_H + +void imap_sieve_storage_init(struct module *module); +void imap_sieve_storage_deinit(void); + +void imap_sieve_storage_client_created(struct client *client, + bool user_script); + +#endif diff --git a/pigeonhole/src/plugins/imapsieve/imap-sieve.c b/pigeonhole/src/plugins/imapsieve/imap-sieve.c new file mode 100644 index 0000000..e6cc24a --- /dev/null +++ b/pigeonhole/src/plugins/imapsieve/imap-sieve.c @@ -0,0 +1,940 @@ +/* Copyright (c) 2016-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "home-expand.h" +#include "smtp-address.h" +#include "smtp-submit.h" +#include "mail-storage.h" +#include "mail-user.h" +#include "mail-duplicate.h" +#include "iostream-ssl.h" +#include "imap-client.h" +#include "imap-settings.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "ext-imapsieve-common.h" + +#include "imap-sieve.h" + +/* + * Configuration + */ + +#define DUPLICATE_DB_NAME "lda-dupes" +#define IMAP_SIEVE_MAX_USER_ERRORS 30 + +/* + * IMAP Sieve + */ + +struct imap_sieve { + pool_t pool; + struct client *client; + const char *home_dir; + + struct sieve_instance *svinst; + struct sieve_storage *storage; + + const struct sieve_extension *ext_imapsieve; + const struct sieve_extension *ext_vnd_imapsieve; + + struct mail_duplicate_db *dup_db; + + struct sieve_error_handler *master_ehandler; +}; + +static const char * +mail_sieve_get_setting(void *context, const char *identifier) +{ + struct imap_sieve *isieve = context; + struct mail_user *user = isieve->client->user; + + return mail_user_plugin_getenv(user, identifier); +} + +static const struct sieve_callbacks mail_sieve_callbacks = { + NULL, + mail_sieve_get_setting +}; + +struct imap_sieve *imap_sieve_init(struct client *client) +{ + struct sieve_environment svenv; + struct imap_sieve *isieve; + struct mail_user *user = client->user; + const struct mail_storage_settings *mail_set = + mail_user_set_get_storage_set(user); + bool debug = user->mail_debug; + pool_t pool; + + pool = pool_alloconly_create("imap_sieve", 256); + isieve = p_new(pool, struct imap_sieve, 1); + isieve->pool = pool; + isieve->client = client; + + isieve->dup_db = mail_duplicate_db_init(user, DUPLICATE_DB_NAME); + + i_zero(&svenv); + svenv.username = user->username; + (void)mail_user_get_home(user, &svenv.home_dir); + svenv.hostname = mail_set->hostname; + svenv.base_dir = user->set->base_dir; + svenv.event_parent = client->event; + svenv.flags = SIEVE_FLAG_HOME_RELATIVE; + svenv.location = SIEVE_ENV_LOCATION_MS; + svenv.delivery_phase = SIEVE_DELIVERY_PHASE_POST; + + isieve->home_dir = p_strdup(pool, svenv.home_dir); + + isieve->svinst = sieve_init(&svenv, &mail_sieve_callbacks, isieve, + debug); + + isieve->ext_imapsieve = sieve_extension_replace( + isieve->svinst, &imapsieve_extension, TRUE); + isieve->ext_vnd_imapsieve = sieve_extension_replace( + isieve->svinst, &vnd_imapsieve_extension, TRUE); + + isieve->master_ehandler = + sieve_master_ehandler_create(isieve->svinst, 0); + sieve_error_handler_accept_infolog(isieve->master_ehandler, TRUE); + sieve_error_handler_accept_debuglog(isieve->master_ehandler, debug); + + return isieve; +} + +void imap_sieve_deinit(struct imap_sieve **_isieve) +{ + struct imap_sieve *isieve = *_isieve; + + *_isieve = NULL; + + sieve_error_handler_unref(&isieve->master_ehandler); + + if (isieve->storage != NULL) + sieve_storage_unref(&isieve->storage); + sieve_extension_unregister(isieve->ext_imapsieve); + sieve_extension_unregister(isieve->ext_vnd_imapsieve); + sieve_deinit(&isieve->svinst); + + mail_duplicate_db_deinit(&isieve->dup_db); + + pool_unref(&isieve->pool); +} + +static int +imap_sieve_get_storage(struct imap_sieve *isieve, + struct sieve_storage **storage_r) +{ + enum sieve_storage_flags storage_flags = 0; + struct mail_user *user = isieve->client->user; + enum sieve_error error; + + if (isieve->storage != NULL) { + *storage_r = isieve->storage; + return 1; + } + + // FIXME: limit interval between retries + + isieve->storage = sieve_storage_create_main(isieve->svinst, user, + storage_flags, &error); + if (isieve->storage == NULL) { + if (error == SIEVE_ERROR_TEMP_FAILURE) + return -1; + return 0; + } + *storage_r = isieve->storage; + return 1; +} + +/* + * Mail transmission + */ + +static void * +imap_sieve_smtp_start(const struct sieve_script_env *senv, + const struct smtp_address *mail_from) +{ + struct imap_sieve_context *isctx = senv->script_context; + struct imap_sieve *isieve = isctx->isieve; + struct mail_user *user = isieve->client->user; + const struct smtp_submit_settings *smtp_set = isieve->client->smtp_set; + struct ssl_iostream_settings ssl_set; + struct smtp_submit_input submit_input; + + i_zero(&ssl_set); + mail_user_init_ssl_client_settings(user, &ssl_set); + + i_zero(&submit_input); + submit_input.ssl = &ssl_set; + + return smtp_submit_init_simple(&submit_input, smtp_set, mail_from); +} + +static void +imap_sieve_smtp_add_rcpt(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle, const struct smtp_address *rcpt_to) +{ + struct smtp_submit *smtp_submit = handle; + + smtp_submit_add_rcpt(smtp_submit, rcpt_to); +} + +static struct ostream * +imap_sieve_smtp_send(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle) +{ + struct smtp_submit *smtp_submit = handle; + + return smtp_submit_send(smtp_submit); +} + +static void +imap_sieve_smtp_abort(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle) +{ + struct smtp_submit *smtp_submit = handle; + + smtp_submit_deinit(&smtp_submit); +} + +static int +imap_sieve_smtp_finish(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle, const char **error_r) +{ + struct smtp_submit *smtp_submit = handle; + int ret; + + ret = smtp_submit_run(smtp_submit, error_r); + smtp_submit_deinit(&smtp_submit); + return ret; +} + +/* + * Duplicate checking + */ + +static void * +imap_sieve_duplicate_transaction_begin(const struct sieve_script_env *senv) +{ + struct imap_sieve_context *isctx = senv->script_context; + + return mail_duplicate_transaction_begin(isctx->isieve->dup_db); +} + +static void imap_sieve_duplicate_transaction_commit(void **_dup_trans) +{ + struct mail_duplicate_transaction *dup_trans = *_dup_trans; + + *_dup_trans = NULL; + mail_duplicate_transaction_commit(&dup_trans); +} + +static void imap_sieve_duplicate_transaction_rollback(void **_dup_trans) +{ + struct mail_duplicate_transaction *dup_trans = *_dup_trans; + + *_dup_trans = NULL; + mail_duplicate_transaction_rollback(&dup_trans); +} + +static enum sieve_duplicate_check_result +imap_sieve_duplicate_check(void *_dup_trans, + const struct sieve_script_env *senv, + const void *id, size_t id_size) +{ + struct mail_duplicate_transaction *dup_trans = _dup_trans; + + switch (mail_duplicate_check(dup_trans, id, id_size, + senv->user->username)) { + case MAIL_DUPLICATE_CHECK_RESULT_EXISTS: + return SIEVE_DUPLICATE_CHECK_RESULT_EXISTS; + case MAIL_DUPLICATE_CHECK_RESULT_NOT_FOUND: + return SIEVE_DUPLICATE_CHECK_RESULT_NOT_FOUND; + case MAIL_DUPLICATE_CHECK_RESULT_DEADLOCK: + case MAIL_DUPLICATE_CHECK_RESULT_LOCK_TIMEOUT: + return SIEVE_DUPLICATE_CHECK_RESULT_TEMP_FAILURE; + case MAIL_DUPLICATE_CHECK_RESULT_IO_ERROR: + case MAIL_DUPLICATE_CHECK_RESULT_TOO_MANY_LOCKS: + break; + } + return SIEVE_DUPLICATE_CHECK_RESULT_FAILURE; +} + +static void +imap_sieve_duplicate_mark(void *_dup_trans, const struct sieve_script_env *senv, + const void *id, size_t id_size, time_t time) +{ + struct mail_duplicate_transaction *dup_trans = _dup_trans; + + mail_duplicate_mark(dup_trans, id, id_size, senv->user->username, time); +} + +/* + * Result logging + */ + +static const char * +imap_sieve_result_amend_log_message(const struct sieve_script_env *senv, + enum log_type log_type ATTR_UNUSED, + const char *message) +{ + struct imap_sieve_context *isctx = senv->script_context; + string_t *str; + + if (isctx->mail == NULL) + return message; + + str = t_str_new(256); + str_printfa(str, "uid=%u: ", isctx->mail->uid); + str_append(str, message); + return str_c(str); +} + +/* + * IMAP Sieve run + */ + +struct imap_sieve_run_script { + struct sieve_script *script; + struct sieve_binary *binary; + + /* Compile failed once with this error; + don't try again for this transaction */ + enum sieve_error compile_error; + + /* Binary corrupt after recompile; don't recompile again */ + bool binary_corrupt:1; + /* Resource usage exceeded */ + bool rusage_exceeded:1; +}; + +struct imap_sieve_run { + pool_t pool; + struct imap_sieve *isieve; + struct mailbox *dest_mailbox, *src_mailbox; + char *cause; + + struct sieve_error_handler *user_ehandler; + char *userlog; + + struct sieve_trace_config trace_config; + struct sieve_trace_log *trace_log; + + struct sieve_script *user_script; + struct imap_sieve_run_script *scripts; + unsigned int scripts_count; + + bool trace_log_initialized:1; +}; + +static void +imap_sieve_run_init_user_log(struct imap_sieve_run *isrun) +{ + struct imap_sieve *isieve = isrun->isieve; + struct sieve_instance *svinst = isieve->svinst; + const char *log_path; + + log_path = sieve_user_get_log_path(svinst, isrun->user_script); + if (log_path != NULL) { + isrun->userlog = p_strdup(isrun->pool, log_path); + isrun->user_ehandler = sieve_logfile_ehandler_create( + svinst, log_path, IMAP_SIEVE_MAX_USER_ERRORS); + } +} + +static void +imap_sieve_run_init_trace_log(struct imap_sieve_run *isrun, + struct sieve_trace_config *trace_config_r, + struct sieve_trace_log **trace_log_r) +{ + struct imap_sieve *isieve = isrun->isieve; + struct sieve_instance *svinst = isieve->svinst; + struct mail_user *user = isieve->client->user; + + if (isrun->trace_log_initialized) { + *trace_config_r = isrun->trace_config; + *trace_log_r = isrun->trace_log; + return; + } + isrun->trace_log_initialized = TRUE; + + if (sieve_trace_config_get(svinst, &isrun->trace_config) < 0 || + sieve_trace_log_open(svinst, &isrun->trace_log) < 0) { + i_zero(&isrun->trace_config); + isrun->trace_log = NULL; + + i_zero(trace_config_r); + *trace_log_r = NULL; + return; + } + + /* Write header for trace file */ + sieve_trace_log_printf(isrun->trace_log, + "Sieve trace log for IMAPSIEVE:\n" + "\n" + " Username: %s\n", user->username); + if (user->session_id != NULL) { + sieve_trace_log_printf(isrun->trace_log, + " Session ID: %s\n", user->session_id); + } + if (isrun->src_mailbox != NULL) { + sieve_trace_log_printf(isrun->trace_log, + " Source mailbox: %s\n", + mailbox_get_vname(isrun->src_mailbox)); + } + + sieve_trace_log_printf(isrun->trace_log, + " Destination mailbox: %s\n" + " Cause: %s\n\n", + mailbox_get_vname(isrun->dest_mailbox), + isrun->cause); + + *trace_config_r = isrun->trace_config; + *trace_log_r = isrun->trace_log; +} + +int imap_sieve_run_init(struct imap_sieve *isieve, + struct mailbox *dest_mailbox, + struct mailbox *src_mailbox, + const char *cause, const char *script_name, + const char *const *scripts_before, + const char *const *scripts_after, + struct imap_sieve_run **isrun_r) +{ + struct sieve_instance *svinst = isieve->svinst; + struct imap_sieve_run *isrun; + struct sieve_storage *storage; + struct imap_sieve_run_script *scripts; + struct sieve_script *user_script; + const char *const *sp; + enum sieve_error error; + pool_t pool; + unsigned int max_len, count; + int ret; + + /* Determine how many scripts we may run for this event */ + max_len = 0; + if (scripts_before != NULL) + max_len += str_array_length(scripts_before); + if (script_name != NULL) + max_len++; + if (scripts_after != NULL) + max_len += str_array_length(scripts_after); + if (max_len == 0) + return 0; + + /* Get storage for user script */ + storage = NULL; + if (script_name != NULL && *script_name != '\0' && + (ret = imap_sieve_get_storage(isieve, &storage)) < 0) + return ret; + + /* Open all scripts */ + count = 0; + pool = pool_alloconly_create("imap_sieve_run", 256); + scripts = p_new(pool, struct imap_sieve_run_script, max_len); + + /* Admin scripts before user script */ + if (scripts_before != NULL) { + for (sp = scripts_before; *sp != NULL; sp++) { + i_assert(count < max_len); + scripts[count].script = + sieve_script_create_open(svinst, *sp, NULL, + &error); + if (scripts[count].script != NULL) + count++; + else if (error == SIEVE_ERROR_TEMP_FAILURE) + return -1; + } + } + + /* The user script */ + user_script = NULL; + if (storage != NULL) { + i_assert(count < max_len); + scripts[count].script = + sieve_storage_open_script(storage, script_name, &error); + if (scripts[count].script != NULL) { + user_script = scripts[count].script; + count++; + } else if (error == SIEVE_ERROR_TEMP_FAILURE) { + return -1; + } + } + + /* Admin scripts after user script */ + if (scripts_after != NULL) { + for (sp = scripts_after; *sp != NULL; sp++) { + i_assert(count < max_len); + scripts[count].script = + sieve_script_create_open(svinst, *sp, NULL, + &error); + if (scripts[count].script != NULL) + count++; + else if (error == SIEVE_ERROR_TEMP_FAILURE) + return -1; + } + } + + if (count == 0) { + /* None of the scripts could be opened */ + pool_unref(&pool); + return 0; + } + + /* Initialize */ + isrun = p_new(pool, struct imap_sieve_run, 1); + isrun->pool = pool; + isrun->isieve = isieve; + isrun->dest_mailbox = dest_mailbox; + isrun->src_mailbox = src_mailbox; + isrun->cause = p_strdup(pool, cause); + isrun->user_script = user_script; + isrun->scripts = scripts; + isrun->scripts_count = count; + + imap_sieve_run_init_user_log(isrun); + + *isrun_r = isrun; + return 1; +} + +void imap_sieve_run_deinit(struct imap_sieve_run **_isrun) +{ + struct imap_sieve_run *isrun = *_isrun; + unsigned int i; + + *_isrun = NULL; + + for (i = 0; i < isrun->scripts_count; i++) { + if (isrun->scripts[i].binary != NULL) + sieve_close(&isrun->scripts[i].binary); + if (isrun->scripts[i].script != NULL) + sieve_script_unref(&isrun->scripts[i].script); + } + if (isrun->user_ehandler != NULL) + sieve_error_handler_unref(&isrun->user_ehandler); + if (isrun->trace_log != NULL) + sieve_trace_log_free(&isrun->trace_log); + + pool_unref(&isrun->pool); +} + +static struct sieve_binary * +imap_sieve_run_open_script(struct imap_sieve_run *isrun, + struct sieve_script *script, + enum sieve_compile_flags cpflags, + bool recompile, enum sieve_error *error_r) +{ + struct imap_sieve *isieve = isrun->isieve; + struct sieve_instance *svinst = isieve->svinst; + struct sieve_error_handler *ehandler; + struct sieve_binary *sbin; + const char *compile_name = "compile"; + + if (recompile) { + /* Warn */ + e_warning(sieve_get_event(svinst), + "Encountered corrupt binary: re-compiling script %s", + sieve_script_location(script)); + compile_name = "re-compile"; + } else { + e_debug(sieve_get_event(svinst), + "Loading script %s", sieve_script_location(script)); + } + + if (script == isrun->user_script) + ehandler = isrun->user_ehandler; + else + ehandler = isieve->master_ehandler; + sieve_error_handler_reset(ehandler); + + /* Load or compile the sieve script */ + if (recompile) { + sbin = sieve_compile_script(script, ehandler, cpflags, error_r); + } else { + sbin = sieve_open_script(script, ehandler, cpflags, error_r); + } + + /* Handle error */ + if (sbin == NULL) { + switch (*error_r) { + /* Script not found */ + case SIEVE_ERROR_NOT_FOUND: + e_debug(sieve_get_event(svinst), + "Script `%s' is missing for %s", + sieve_script_location(script), compile_name); + break; + /* Temporary failure */ + case SIEVE_ERROR_TEMP_FAILURE: + e_error(sieve_get_event(svinst), + "Failed to open script `%s' for %s " + "(temporary failure)", + sieve_script_location(script), compile_name); + break; + /* Compile failed */ + case SIEVE_ERROR_NOT_VALID: + if (script == isrun->user_script && + isrun->userlog != NULL ) { + e_info(sieve_get_event(svinst), + "Failed to %s script `%s' " + "(view user logfile `%s' for more information)", + compile_name, sieve_script_location(script), + isrun->userlog); + break; + } + e_error(sieve_get_event(svinst), + "Failed to %s script `%s'", + compile_name, sieve_script_location(script)); + break; + /* Cumulative resource limit exceeded */ + case SIEVE_ERROR_RESOURCE_LIMIT: + e_error(sieve_get_event(svinst), + "Failed to open script `%s' for %s " + "(cumulative resource limit exceeded)", + sieve_script_location(script), compile_name); + break; + /* Something else */ + default: + e_error(sieve_get_event(svinst), + "Failed to open script `%s' for %s", + sieve_script_location(script), compile_name); + break; + } + + return NULL; + } + + if (!recompile) + (void)sieve_save(sbin, FALSE, NULL); + return sbin; +} + +static int +imap_sieve_handle_exec_status(struct imap_sieve_run *isrun, + struct sieve_script *script, int status, + struct sieve_exec_status *estatus, bool *fatal_r) + ATTR_NULL(2) +{ + struct imap_sieve *isieve = isrun->isieve; + struct sieve_instance *svinst = isieve->svinst; + const char *userlog_notice = ""; + enum log_type log_level, user_log_level; + enum mail_error mail_error = MAIL_ERROR_NONE; + int ret = -1; + + *fatal_r = FALSE; + + log_level = user_log_level = LOG_TYPE_ERROR; + + if (estatus->last_storage != NULL && estatus->store_failed) { + mail_storage_get_last_error(estatus->last_storage, &mail_error); + + /* Don't bother administrator too much with benign errors */ + if (mail_error == MAIL_ERROR_NOQUOTA) { + log_level = LOG_TYPE_INFO; + user_log_level = LOG_TYPE_INFO; + } + } + + if (script == isrun->user_script && isrun->userlog != NULL) { + userlog_notice = t_strdup_printf( + " (user logfile %s may reveal additional details)", + isrun->userlog); + user_log_level = LOG_TYPE_INFO; + } + + switch (status) { + case SIEVE_EXEC_FAILURE: + e_log(sieve_get_event(svinst), user_log_level, + "Execution of script %s failed%s", + sieve_script_location(script), userlog_notice); + ret = 0; + break; + case SIEVE_EXEC_TEMP_FAILURE: + e_log(sieve_get_event(svinst), log_level, + "Execution of script %s was aborted " + "due to temporary failure%s", + sieve_script_location(script), userlog_notice); + *fatal_r = TRUE; + ret = -1; + break; + case SIEVE_EXEC_BIN_CORRUPT: + e_error(sieve_get_event(svinst), + "!!BUG!!: Binary compiled from %s is still corrupt; " + "bailing out and reverting to default action", + sieve_script_location(script)); + *fatal_r = TRUE; + ret = -1; + break; + case SIEVE_EXEC_RESOURCE_LIMIT: + e_error(sieve_get_event(svinst), + "Execution of script %s was aborted " + "due to excessive resource usage", + sieve_script_location(script)); + *fatal_r = TRUE; + ret = -1; + break; + case SIEVE_EXEC_KEEP_FAILED: + e_log(sieve_get_event(svinst), log_level, + "Execution of script %s failed " + "with unsuccessful implicit keep%s", + sieve_script_location(script), userlog_notice); + ret = 0; + break; + case SIEVE_EXEC_OK: + ret = (estatus->keep_original ? 0 : 1); + break; + } + + return ret; +} + +static int +imap_sieve_run_scripts(struct imap_sieve_run *isrun, + const struct sieve_message_data *msgdata, + const struct sieve_script_env *scriptenv, bool *fatal_r) +{ + struct imap_sieve *isieve = isrun->isieve; + struct sieve_instance *svinst = isieve->svinst; + struct imap_sieve_run_script *scripts = isrun->scripts; + unsigned int count = isrun->scripts_count; + struct sieve_resource_usage *rusage = + &scriptenv->exec_status->resource_usage; + struct sieve_multiscript *mscript; + struct sieve_error_handler *ehandler; + struct sieve_script *last_script = NULL; + bool user_script = FALSE, more = TRUE, rusage_exceeded = FALSE; + enum sieve_compile_flags cpflags; + enum sieve_execute_flags exflags; + enum sieve_error compile_error = SIEVE_ERROR_NONE; + unsigned int i; + int ret; + + *fatal_r = FALSE; + + /* Start execution */ + mscript = sieve_multiscript_start_execute(svinst, msgdata, scriptenv); + + /* Execute scripts */ + for (i = 0; i < count && more; i++) { + struct sieve_script *script = scripts[i].script; + struct sieve_binary *sbin = scripts[i].binary; + int mstatus; + + cpflags = 0; + exflags = SIEVE_EXECUTE_FLAG_NO_ENVELOPE | + SIEVE_EXECUTE_FLAG_SKIP_RESPONSES; + + user_script = (script == isrun->user_script); + last_script = script; + + if (scripts[i].rusage_exceeded) { + rusage_exceeded = TRUE; + break; + } + + sieve_resource_usage_init(rusage); + if (user_script) { + cpflags |= SIEVE_COMPILE_FLAG_NOGLOBAL; + exflags |= SIEVE_EXECUTE_FLAG_NOGLOBAL; + ehandler = isrun->user_ehandler; + } else { + cpflags |= SIEVE_COMPILE_FLAG_NO_ENVELOPE; + ehandler = isieve->master_ehandler; + } + + /* Open */ + if (sbin == NULL) { + e_debug(sieve_get_event(svinst), + "Opening script %d of %d from `%s'", + i+1, count, sieve_script_location(script)); + + /* Already known to fail */ + if (scripts[i].compile_error != SIEVE_ERROR_NONE) { + compile_error = scripts[i].compile_error; + break; + } + + /* Try to open/compile binary */ + scripts[i].binary = sbin = imap_sieve_run_open_script( + isrun, script, cpflags, FALSE, &compile_error); + if (sbin == NULL) { + scripts[i].compile_error = compile_error; + break; + } + } + + /* Execute */ + e_debug(sieve_get_event(svinst), + "Executing script from `%s'", + sieve_get_source(sbin)); + more = sieve_multiscript_run(mscript, sbin, ehandler, ehandler, + exflags); + + mstatus = sieve_multiscript_status(mscript); + if (!more && mstatus == SIEVE_EXEC_BIN_CORRUPT && + !scripts[i].binary_corrupt && sieve_is_loaded(sbin)) { + /* Close corrupt script */ + sieve_close(&sbin); + + /* Recompile */ + scripts[i].binary = sbin = + imap_sieve_run_open_script( + isrun, script, cpflags, FALSE, + &compile_error); + if (sbin == NULL) { + scripts[i].compile_error = compile_error; + break; + } + + /* Execute again */ + more = sieve_multiscript_run(mscript, sbin, + ehandler, ehandler, + exflags); + + /* Save new version */ + + mstatus = sieve_multiscript_status(mscript); + if (mstatus == SIEVE_EXEC_BIN_CORRUPT) + scripts[i].binary_corrupt = TRUE; + else if (more) + (void)sieve_save(sbin, FALSE, NULL); + } + + if (user_script && !sieve_record_resource_usage(sbin, rusage)) { + rusage_exceeded = ((i + 1) < count && more); + scripts[i].rusage_exceeded = TRUE; + break; + } + } + + /* Finish execution */ + exflags = SIEVE_EXECUTE_FLAG_NO_ENVELOPE | + SIEVE_EXECUTE_FLAG_SKIP_RESPONSES; + ehandler = (isrun->user_ehandler != NULL ? + isrun->user_ehandler : isieve->master_ehandler); + if (compile_error == SIEVE_ERROR_TEMP_FAILURE) { + ret = sieve_multiscript_finish(&mscript, ehandler, exflags, + SIEVE_EXEC_TEMP_FAILURE); + } else if (rusage_exceeded) { + i_assert(last_script != NULL); + (void)sieve_multiscript_finish(&mscript, ehandler, exflags, + SIEVE_EXEC_TEMP_FAILURE); + sieve_error(ehandler, sieve_script_name(last_script), + "cumulative resource usage limit exceeded"); + ret = SIEVE_EXEC_RESOURCE_LIMIT; + } else { + ret = sieve_multiscript_finish(&mscript, ehandler, exflags, + SIEVE_EXEC_OK); + } + + /* Don't log additional messages about compile failure */ + if (compile_error != SIEVE_ERROR_NONE && ret == SIEVE_EXEC_FAILURE) { + e_info(sieve_get_event(svinst), + "Aborted script execution sequence " + "with successful implicit keep"); + return 1; + } + + if (last_script == NULL && ret == SIEVE_EXEC_OK) + return 0; + return imap_sieve_handle_exec_status(isrun, last_script, ret, + scriptenv->exec_status, fatal_r); +} + +int imap_sieve_run_mail(struct imap_sieve_run *isrun, struct mail *mail, + const char *changed_flags, bool *fatal_r) +{ + struct imap_sieve *isieve = isrun->isieve; + struct sieve_instance *svinst = isieve->svinst; + struct mail_user *user = isieve->client->user; + struct sieve_message_data msgdata; + struct sieve_script_env scriptenv; + struct sieve_exec_status estatus; + struct imap_sieve_context context; + struct sieve_trace_config trace_config; + struct sieve_trace_log *trace_log; + const char *error; + int ret; + + *fatal_r = FALSE; + + i_zero(&context); + context.event.dest_mailbox = isrun->dest_mailbox; + context.event.src_mailbox = isrun->src_mailbox; + context.event.cause = isrun->cause; + context.event.changed_flags = changed_flags; + context.mail = mail; + context.isieve = isieve; + + /* Initialize trace logging */ + imap_sieve_run_init_trace_log(isrun, &trace_config, &trace_log); + + T_BEGIN { + if (trace_log != NULL) { + /* Write trace header for message */ + sieve_trace_log_printf(trace_log, + "Filtering message:\n" + "\n" + " UID: %u\n", mail->uid); + if (changed_flags != NULL && *changed_flags != '\0') { + sieve_trace_log_printf(trace_log, + " Changed flags: %s\n", changed_flags); + } + } + + /* Collect necessary message data */ + + i_zero(&msgdata); + msgdata.mail = mail; + msgdata.auth_user = user->username; + (void)mail_get_message_id(msgdata.mail, &msgdata.id); + + /* Compose script execution environment */ + + if (sieve_script_env_init(&scriptenv, user, &error) < 0) { + e_error(sieve_get_event(svinst), + "Failed to initialize script execution: %s", + error); + ret = -1; + } else { + scriptenv.default_mailbox = + mailbox_get_vname(mail->box); + scriptenv.smtp_start = imap_sieve_smtp_start; + scriptenv.smtp_add_rcpt = imap_sieve_smtp_add_rcpt; + scriptenv.smtp_send = imap_sieve_smtp_send; + scriptenv.smtp_abort = imap_sieve_smtp_abort; + scriptenv.smtp_finish = imap_sieve_smtp_finish; + scriptenv.duplicate_transaction_begin = + imap_sieve_duplicate_transaction_begin; + scriptenv.duplicate_transaction_commit = + imap_sieve_duplicate_transaction_commit; + scriptenv.duplicate_transaction_rollback = + imap_sieve_duplicate_transaction_rollback; + scriptenv.duplicate_mark = imap_sieve_duplicate_mark; + scriptenv.duplicate_check = imap_sieve_duplicate_check; + scriptenv.result_amend_log_message = + imap_sieve_result_amend_log_message; + scriptenv.trace_log = trace_log; + scriptenv.trace_config = trace_config; + scriptenv.script_context = &context; + + i_zero(&estatus); + scriptenv.exec_status = &estatus; + + /* Execute script(s) */ + + ret = imap_sieve_run_scripts(isrun, &msgdata, + &scriptenv, fatal_r); + } + } T_END; + + return ret; +} diff --git a/pigeonhole/src/plugins/imapsieve/imap-sieve.h b/pigeonhole/src/plugins/imapsieve/imap-sieve.h new file mode 100644 index 0000000..12d0ac7 --- /dev/null +++ b/pigeonhole/src/plugins/imapsieve/imap-sieve.h @@ -0,0 +1,59 @@ +#ifndef IMAP_SIEVE_H +#define IMAP_SIEVE_H + +struct client; + +/* + * IMAP event + */ + +struct imap_sieve_event { + struct mailbox *dest_mailbox, *src_mailbox; + const char *cause; + const char *changed_flags; +}; + +struct imap_sieve_context { + struct imap_sieve_event event; + struct mail *mail; + + struct imap_sieve *isieve; +}; + +static inline bool +imap_sieve_event_cause_valid(const char *cause) +{ + return (strcasecmp(cause, "APPEND") == 0 || + strcasecmp(cause, "COPY") == 0 || + strcasecmp(cause, "FLAG") == 0); +} + +/* + * IMAP Sieve + */ + +struct imap_sieve; + +struct imap_sieve *imap_sieve_init(struct client *client); +void imap_sieve_deinit(struct imap_sieve **_isieve); + +/* + * IMAP Sieve run + */ + +struct imap_sieve_run; + +int imap_sieve_run_init(struct imap_sieve *isieve, struct mailbox *dest_mailbox, + struct mailbox *src_mailbox, const char *cause, + const char *script_name, + const char *const *scripts_before, + const char *const *scripts_after, + struct imap_sieve_run **isrun_r) + ATTR_NULL(4, 5, 6); + +int imap_sieve_run_mail(struct imap_sieve_run *isrun, struct mail *mail, + const char *changed_flags, bool *fatal_r); + +void imap_sieve_run_deinit(struct imap_sieve_run **_isrun); + +#endif diff --git a/pigeonhole/src/plugins/imapsieve/sieve-imapsieve-plugin.c b/pigeonhole/src/plugins/imapsieve/sieve-imapsieve-plugin.c new file mode 100644 index 0000000..12611b3 --- /dev/null +++ b/pigeonhole/src/plugins/imapsieve/sieve-imapsieve-plugin.c @@ -0,0 +1,62 @@ +/* Copyright (c) 2016-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve.h" +#include "sieve-error.h" +#include "sieve-extensions.h" + +#include "ext-imapsieve-common.h" + +#include "sieve-imapsieve-plugin.h" + +/* + * Sieve plugin interface + */ + +struct _plugin_context { + const struct sieve_extension *ext_imapsieve; + const struct sieve_extension *ext_vnd_imapsieve; +}; + +const char *sieve_imapsieve_plugin_version = PIGEONHOLE_ABI_VERSION; + +void sieve_imapsieve_plugin_load +(struct sieve_instance *svinst, void **context) +{ + struct _plugin_context *pctx = i_new(struct _plugin_context, 1); + + pctx->ext_imapsieve = sieve_extension_register + (svinst, &imapsieve_extension_dummy, TRUE); + pctx->ext_vnd_imapsieve = sieve_extension_register + (svinst, &vnd_imapsieve_extension_dummy, TRUE); + + e_debug(sieve_get_event(svinst), + "Sieve imapsieve plugin for %s version %s loaded", + PIGEONHOLE_NAME, PIGEONHOLE_VERSION_FULL); + + *context = (void *)pctx; +} + +void sieve_imapsieve_plugin_unload +(struct sieve_instance *svinst ATTR_UNUSED, void *context) +{ + struct _plugin_context *pctx = (struct _plugin_context *)context; + + sieve_extension_unregister(pctx->ext_imapsieve); + sieve_extension_unregister(pctx->ext_vnd_imapsieve); + + i_free(pctx);} + +/* + * Module interface + */ + +void sieve_imapsieve_plugin_init(void) +{ + /* Nothing */ +} + +void sieve_imapsieve_plugin_deinit(void) +{ + /* Nothing */ +} diff --git a/pigeonhole/src/plugins/imapsieve/sieve-imapsieve-plugin.h b/pigeonhole/src/plugins/imapsieve/sieve-imapsieve-plugin.h new file mode 100644 index 0000000..fcf9777 --- /dev/null +++ b/pigeonhole/src/plugins/imapsieve/sieve-imapsieve-plugin.h @@ -0,0 +1,20 @@ +#ifndef SIEVE_IMAPSIEVE_PLUGIN_H +#define SIEVE_IMAPSIEVE_PLUGIN_H + +/* + * Plugin interface + */ + +void sieve_imapsieve_plugin_load + (struct sieve_instance *svinst, void **context); +void sieve_imapsieve_plugin_unload + (struct sieve_instance *svinst, void *context); + +/* + * Module interface + */ + +void sieve_imapsieve_plugin_init(void); +void sieve_imapsieve_plugin_deinit(void); + +#endif diff --git a/pigeonhole/src/plugins/lda-sieve/Makefile.am b/pigeonhole/src/plugins/lda-sieve/Makefile.am new file mode 100644 index 0000000..7c2797a --- /dev/null +++ b/pigeonhole/src/plugins/lda-sieve/Makefile.am @@ -0,0 +1,19 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_DICT_INCLUDE) \ + $(LIBDOVECOT_SMTP_INCLUDE) \ + $(LIBDOVECOT_LDA_INCLUDE) + +lib90_sieve_plugin_la_LDFLAGS = -module -avoid-version + +dovecot_module_LTLIBRARIES = lib90_sieve_plugin.la + +lib90_sieve_plugin_la_LIBADD = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la + +lib90_sieve_plugin_la_SOURCES = \ + lda-sieve-plugin.c + +noinst_HEADERS = \ + lda-sieve-plugin.h diff --git a/pigeonhole/src/plugins/lda-sieve/Makefile.in b/pigeonhole/src/plugins/lda-sieve/Makefile.in new file mode 100644 index 0000000..6f0fba0 --- /dev/null +++ b/pigeonhole/src/plugins/lda-sieve/Makefile.in @@ -0,0 +1,746 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/plugins/lda-sieve +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(dovecot_moduledir)" +LTLIBRARIES = $(dovecot_module_LTLIBRARIES) +lib90_sieve_plugin_la_DEPENDENCIES = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la +am_lib90_sieve_plugin_la_OBJECTS = lda-sieve-plugin.lo +lib90_sieve_plugin_la_OBJECTS = $(am_lib90_sieve_plugin_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +lib90_sieve_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib90_sieve_plugin_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/lda-sieve-plugin.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(lib90_sieve_plugin_la_SOURCES) +DIST_SOURCES = $(lib90_sieve_plugin_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_DICT_INCLUDE) \ + $(LIBDOVECOT_SMTP_INCLUDE) \ + $(LIBDOVECOT_LDA_INCLUDE) + +lib90_sieve_plugin_la_LDFLAGS = -module -avoid-version +dovecot_module_LTLIBRARIES = lib90_sieve_plugin.la +lib90_sieve_plugin_la_LIBADD = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la + +lib90_sieve_plugin_la_SOURCES = \ + lda-sieve-plugin.c + +noinst_HEADERS = \ + lda-sieve-plugin.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/lda-sieve/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/plugins/lda-sieve/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-dovecot_moduleLTLIBRARIES: $(dovecot_module_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(dovecot_module_LTLIBRARIES)'; test -n "$(dovecot_moduledir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(dovecot_moduledir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(dovecot_moduledir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(dovecot_moduledir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(dovecot_moduledir)"; \ + } + +uninstall-dovecot_moduleLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(dovecot_module_LTLIBRARIES)'; test -n "$(dovecot_moduledir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(dovecot_moduledir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(dovecot_moduledir)/$$f"; \ + done + +clean-dovecot_moduleLTLIBRARIES: + -test -z "$(dovecot_module_LTLIBRARIES)" || rm -f $(dovecot_module_LTLIBRARIES) + @list='$(dovecot_module_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +lib90_sieve_plugin.la: $(lib90_sieve_plugin_la_OBJECTS) $(lib90_sieve_plugin_la_DEPENDENCIES) $(EXTRA_lib90_sieve_plugin_la_DEPENDENCIES) + $(AM_V_CCLD)$(lib90_sieve_plugin_la_LINK) -rpath $(dovecot_moduledir) $(lib90_sieve_plugin_la_OBJECTS) $(lib90_sieve_plugin_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lda-sieve-plugin.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(dovecot_moduledir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-dovecot_moduleLTLIBRARIES clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/lda-sieve-plugin.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dovecot_moduleLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/lda-sieve-plugin.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dovecot_moduleLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-dovecot_moduleLTLIBRARIES clean-generic clean-libtool \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dovecot_moduleLTLIBRARIES \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-dovecot_moduleLTLIBRARIES + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/plugins/lda-sieve/lda-sieve-plugin.c b/pigeonhole/src/plugins/lda-sieve/lda-sieve-plugin.c new file mode 100644 index 0000000..4e79c1f --- /dev/null +++ b/pigeonhole/src/plugins/lda-sieve/lda-sieve-plugin.c @@ -0,0 +1,1128 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "array.h" +#include "home-expand.h" +#include "var-expand.h" +#include "eacces-error.h" +#include "smtp-address.h" +#include "smtp-submit.h" +#include "mail-storage.h" +#include "mail-deliver.h" +#include "mail-user.h" +#include "mail-duplicate.h" +#include "smtp-submit.h" +#include "mail-send.h" +#include "iostream-ssl.h" +#include "lda-settings.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "lda-sieve-plugin.h" + +#include <sys/stat.h> +#include <dirent.h> + +/* + * Configuration + */ + +#define LDA_SIEVE_DEFAULT_LOCATION "~/.dovecot.sieve" + +#define LDA_SIEVE_MAX_USER_ERRORS 30 + +/* + * Global variables + */ + +static deliver_mail_func_t *next_deliver_mail; + +/* + * Settings handling + */ + +static const char * +lda_sieve_get_setting(void *context, const char *identifier) +{ + struct mail_deliver_context *mdctx = + (struct mail_deliver_context *)context; + const char *value = NULL; + + if (mdctx == NULL) + return NULL; + + if (mdctx->rcpt_user == NULL || + (value = mail_user_plugin_getenv( + mdctx->rcpt_user, identifier)) == NULL) { + if (strcmp(identifier, "recipient_delimiter") == 0) + value = mdctx->set->recipient_delimiter; + } + + return value; +} + +static const struct sieve_callbacks lda_sieve_callbacks = { + NULL, + lda_sieve_get_setting +}; + +/* + * Mail transmission + */ + +static void * +lda_sieve_smtp_start(const struct sieve_script_env *senv, + const struct smtp_address *mail_from) +{ + struct mail_deliver_context *dctx = + (struct mail_deliver_context *)senv->script_context; + struct mail_user *user = dctx->rcpt_user; + struct ssl_iostream_settings ssl_set; + struct smtp_submit_input submit_input; + + i_zero(&ssl_set); + mail_user_init_ssl_client_settings(user, &ssl_set); + + i_zero(&submit_input); + submit_input.ssl = &ssl_set; + + return (void *)smtp_submit_init_simple(&submit_input, dctx->smtp_set, + mail_from); +} + +static void +lda_sieve_smtp_add_rcpt(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle, const struct smtp_address *rcpt_to) +{ + struct smtp_submit *smtp_submit = (struct smtp_submit *) handle; + + smtp_submit_add_rcpt(smtp_submit, rcpt_to); +} + +static struct ostream * +lda_sieve_smtp_send(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle) +{ + struct smtp_submit *smtp_submit = (struct smtp_submit *) handle; + + return smtp_submit_send(smtp_submit); +} + +static void +lda_sieve_smtp_abort(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle) +{ + struct smtp_submit *smtp_submit = (struct smtp_submit *) handle; + + smtp_submit_deinit(&smtp_submit); +} + +static int +lda_sieve_smtp_finish(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle, const char **error_r) +{ + struct smtp_submit *smtp_submit = (struct smtp_submit *) handle; + int ret; + + ret = smtp_submit_run(smtp_submit, error_r); + smtp_submit_deinit(&smtp_submit); + return ret; +} + +static int +lda_sieve_reject_mail(const struct sieve_script_env *senv, + const struct smtp_address *recipient, + const char *reason) +{ + struct mail_deliver_context *dctx = + (struct mail_deliver_context *)senv->script_context; + + return mail_send_rejection(dctx, recipient, reason); +} + +/* + * Duplicate checking + */ + +static void * +lda_sieve_duplicate_transaction_begin(const struct sieve_script_env *senv) +{ + struct mail_deliver_context *dctx = + (struct mail_deliver_context *)senv->script_context; + + return mail_duplicate_transaction_begin(dctx->dup_db); +} + +static void lda_sieve_duplicate_transaction_commit(void **_dup_trans) +{ + struct mail_duplicate_transaction *dup_trans = *_dup_trans; + + *_dup_trans = NULL; + mail_duplicate_transaction_commit(&dup_trans); +} + +static void lda_sieve_duplicate_transaction_rollback(void **_dup_trans) +{ + struct mail_duplicate_transaction *dup_trans = *_dup_trans; + + *_dup_trans = NULL; + mail_duplicate_transaction_rollback(&dup_trans); +} + +static enum sieve_duplicate_check_result +lda_sieve_duplicate_check(void *_dup_trans, const struct sieve_script_env *senv, + const void *id, size_t id_size) +{ + struct mail_duplicate_transaction *dup_trans = _dup_trans; + + switch (mail_duplicate_check(dup_trans, id, id_size, + senv->user->username)) { + case MAIL_DUPLICATE_CHECK_RESULT_EXISTS: + return SIEVE_DUPLICATE_CHECK_RESULT_EXISTS; + case MAIL_DUPLICATE_CHECK_RESULT_NOT_FOUND: + return SIEVE_DUPLICATE_CHECK_RESULT_NOT_FOUND; + case MAIL_DUPLICATE_CHECK_RESULT_DEADLOCK: + case MAIL_DUPLICATE_CHECK_RESULT_LOCK_TIMEOUT: + return SIEVE_DUPLICATE_CHECK_RESULT_TEMP_FAILURE; + case MAIL_DUPLICATE_CHECK_RESULT_IO_ERROR: + case MAIL_DUPLICATE_CHECK_RESULT_TOO_MANY_LOCKS: + break; + } + return SIEVE_DUPLICATE_CHECK_RESULT_FAILURE; +} + +static void +lda_sieve_duplicate_mark(void *_dup_trans, const struct sieve_script_env *senv, + const void *id, size_t id_size, time_t time) +{ + struct mail_duplicate_transaction *dup_trans = _dup_trans; + + mail_duplicate_mark(dup_trans, id, id_size, senv->user->username, time); +} + +/* + * Result logging + */ + +static const char * +lda_sieve_result_amend_log_message(const struct sieve_script_env *senv, + enum log_type log_type ATTR_UNUSED, + const char *message) +{ + struct mail_deliver_context *mdctx = senv->script_context; + const struct var_expand_table *table; + string_t *str; + const char *error; + + table = mail_deliver_ctx_get_log_var_expand_table(mdctx, message); + + str = t_str_new(256); + if (var_expand(str, mdctx->set->deliver_log_format, + table, &error) <= 0) { + e_error(mdctx->event, + "Failed to expand deliver_log_format=%s: %s", + mdctx->set->deliver_log_format, error); + } + return str_c(str); +} + +/* + * Plugin implementation + */ + +struct lda_sieve_run_context { + struct sieve_instance *svinst; + + struct mail_deliver_context *mdctx; + const char *home_dir; + + struct sieve_script **scripts; + unsigned int script_count; + + struct sieve_script *user_script; + struct sieve_script *main_script; + struct sieve_script *discard_script; + + const struct sieve_message_data *msgdata; + const struct sieve_script_env *scriptenv; + + struct sieve_error_handler *user_ehandler; + struct sieve_error_handler *master_ehandler; + struct sieve_error_handler *action_ehandler; + const char *userlog; +}; + +static int +lda_sieve_get_personal_storage(struct sieve_instance *svinst, + struct mail_user *user, + struct sieve_storage **storage_r, + enum sieve_error *error_r) +{ + *storage_r = sieve_storage_create_main(svinst, user, 0, error_r); + if (*storage_r == NULL) { + switch (*error_r) { + case SIEVE_ERROR_NOT_POSSIBLE: + case SIEVE_ERROR_NOT_FOUND: + break; + case SIEVE_ERROR_TEMP_FAILURE: + e_error(sieve_get_event(svinst), + "Failed to access user's personal storage " + "(temporary failure)"); + return -1; + default: + e_error(sieve_get_event(svinst), + "Failed to access user's personal storage"); + break; + } + return 0; + } + return 1; +} + +static int +lda_sieve_multiscript_get_scripts(struct sieve_instance *svinst, + const char *label, const char *location, + ARRAY_TYPE(sieve_script) *scripts, + enum sieve_error *error_r) +{ + struct sieve_script_sequence *seq; + struct sieve_script *script; + bool finished = FALSE; + int ret = 1; + + seq = sieve_script_sequence_create(svinst, location, error_r); + if (seq == NULL) + return (*error_r == SIEVE_ERROR_NOT_FOUND ? 0 : -1); + + while (ret > 0 && !finished) { + script = sieve_script_sequence_next(seq, error_r); + if (script == NULL) { + switch (*error_r) { + case SIEVE_ERROR_NONE: + finished = TRUE; + break; + case SIEVE_ERROR_TEMP_FAILURE: + e_error(sieve_get_event(svinst), + "Failed to access %s script from `%s' " + "(temporary failure)", + label, location); + ret = -1; + default: + break; + } + continue; + } + + array_append(scripts, &script, 1); + } + + sieve_script_sequence_free(&seq); + return ret; +} + +static void +lda_sieve_binary_save(struct lda_sieve_run_context *srctx, + struct sieve_binary *sbin, struct sieve_script *script) +{ + enum sieve_error error; + + /* Save binary when compiled */ + if (sieve_save(sbin, FALSE, &error) < 0 && + error == SIEVE_ERROR_NO_PERMISSION && + script != srctx->user_script) { + /* Cannot save binary for global script */ + e_error(sieve_get_event(srctx->svinst), + "The LDA Sieve plugin does not have permission " + "to save global Sieve script binaries; " + "global Sieve scripts like `%s' need to be " + "pre-compiled using the sievec tool", + sieve_script_location(script)); + } +} + +static struct +sieve_binary *lda_sieve_open(struct lda_sieve_run_context *srctx, + struct sieve_script *script, + enum sieve_compile_flags cpflags, bool recompile, + enum sieve_error *error_r) +{ + struct sieve_instance *svinst = srctx->svinst; + struct sieve_error_handler *ehandler; + struct sieve_binary *sbin; + const char *compile_name = "compile"; + + if (recompile) { + /* Warn */ + e_warning(sieve_get_event(svinst), + "Encountered corrupt binary: re-compiling script %s", + sieve_script_location(script)); + compile_name = "re-compile"; + } else { + e_debug(sieve_get_event(svinst), + "Loading script %s", sieve_script_location(script)); + } + + if (script == srctx->user_script) + ehandler = srctx->user_ehandler; + else + ehandler = srctx->master_ehandler; + + sieve_error_handler_reset(ehandler); + + if (recompile) + sbin = sieve_compile_script(script, ehandler, cpflags, error_r); + else + sbin = sieve_open_script(script, ehandler, cpflags, error_r); + + /* Load or compile the sieve script */ + if (sbin == NULL) { + switch (*error_r) { + /* Script not found */ + case SIEVE_ERROR_NOT_FOUND: + e_debug(sieve_get_event(svinst), + "Script `%s' is missing for %s", + sieve_script_location(script), + compile_name); + break; + /* Temporary failure */ + case SIEVE_ERROR_TEMP_FAILURE: + e_error(sieve_get_event(svinst), + "Failed to open script `%s' for %s " + "(temporary failure)", + sieve_script_location(script), compile_name); + break; + /* Compile failed */ + case SIEVE_ERROR_NOT_VALID: + if (script == srctx->user_script && + srctx->userlog != NULL ) { + e_info(sieve_get_event(svinst), + "Failed to %s script `%s' " + "(view user logfile `%s' for more information)", + compile_name, + sieve_script_location(script), + srctx->userlog); + break; + } + e_error(sieve_get_event(svinst), + "Failed to %s script `%s'", + compile_name, sieve_script_location(script)); + break; + /* Cumulative resource limit exceeded */ + case SIEVE_ERROR_RESOURCE_LIMIT: + e_error(sieve_get_event(svinst), + "Failed to open script `%s' for %s " + "(cumulative resource limit exceeded)", + sieve_script_location(script), compile_name); + break; + /* Something else */ + default: + e_error(sieve_get_event(svinst), + "Failed to open script `%s' for %s", + sieve_script_location(script), compile_name); + break; + } + + return NULL; + } + + if (!recompile) + lda_sieve_binary_save(srctx, sbin, script); + return sbin; +} + +static int +lda_sieve_handle_exec_status(struct lda_sieve_run_context *srctx, + struct sieve_script *script, int status) +{ + struct sieve_instance *svinst = srctx->svinst; + struct mail_deliver_context *mdctx = srctx->mdctx; + struct sieve_exec_status *estatus = srctx->scriptenv->exec_status; + const char *userlog_notice = ""; + enum log_type log_level, user_log_level; + enum mail_error mail_error = MAIL_ERROR_NONE; + int ret; + + log_level = user_log_level = LOG_TYPE_ERROR; + + if (estatus != NULL && estatus->last_storage != NULL && + estatus->store_failed) { + mail_storage_get_last_error(estatus->last_storage, &mail_error); + + /* Don't bother administrator too much with benign errors */ + if (mail_error == MAIL_ERROR_NOQUOTA) { + log_level = LOG_TYPE_INFO; + user_log_level = LOG_TYPE_INFO; + } + } + + if (script == srctx->user_script && srctx->userlog != NULL) { + userlog_notice = t_strdup_printf( + " (user logfile %s may reveal additional details)", + srctx->userlog); + user_log_level = LOG_TYPE_INFO; + } + + switch (status) { + case SIEVE_EXEC_FAILURE: + e_log(sieve_get_event(svinst), user_log_level, + "Execution of script %s failed, " + "but implicit keep was successful%s", + sieve_script_location(script), userlog_notice); + ret = 1; + break; + case SIEVE_EXEC_TEMP_FAILURE: + e_log(sieve_get_event(svinst), log_level, + "Execution of script %s was aborted due to temporary failure%s", + sieve_script_location(script), userlog_notice); + if (mail_error != MAIL_ERROR_TEMP && + mdctx->tempfail_error == NULL) { + mdctx->tempfail_error = + "Execution of Sieve filters was aborted due to temporary failure"; + } + ret = -1; + break; + case SIEVE_EXEC_BIN_CORRUPT: + e_error(sieve_get_event(svinst), + "!!BUG!!: Binary compiled from %s is still corrupt; " + "bailing out and reverting to default delivery", + sieve_script_location(script)); + ret = -1; + break; + case SIEVE_EXEC_RESOURCE_LIMIT: + e_error(sieve_get_event(svinst), + "Execution of script %s was aborted " + "due to excessive resource usage", + sieve_script_location(script)); + ret = -1; + break; + case SIEVE_EXEC_KEEP_FAILED: + e_log(sieve_get_event(svinst), log_level, + "Execution of script %s failed with unsuccessful implicit keep%s", + sieve_script_location(script), userlog_notice); + ret = -1; + break; + default: + ret = status > 0 ? 1 : -1; + break; + } + + return ret; +} + +static int +lda_sieve_execute_script(struct lda_sieve_run_context *srctx, + struct sieve_multiscript *mscript, + struct sieve_script *script, + unsigned int index, bool discard_script, + enum sieve_error *error_r) +{ + struct sieve_instance *svinst = srctx->svinst; + struct sieve_error_handler *exec_ehandler; + struct sieve_binary *sbin = NULL; + enum sieve_compile_flags cpflags = 0; + enum sieve_execute_flags exflags = SIEVE_EXECUTE_FLAG_LOG_RESULT; + struct sieve_resource_usage *rusage = + &srctx->scriptenv->exec_status->resource_usage; + bool user_script; + int mstatus, ret; + + *error_r = SIEVE_ERROR_NONE; + + user_script = (script == srctx->user_script); + + sieve_resource_usage_init(rusage); + if (user_script) { + cpflags |= SIEVE_COMPILE_FLAG_NOGLOBAL; + exflags |= SIEVE_EXECUTE_FLAG_NOGLOBAL; + exec_ehandler = srctx->user_ehandler; + } else { + exec_ehandler = srctx->master_ehandler; + } + + /* Open */ + + if (!discard_script) { + e_debug(sieve_get_event(svinst), + "Opening script %d of %d from `%s'", + index, srctx->script_count, + sieve_script_location(script)); + } else { + e_debug(sieve_get_event(svinst), + "Opening discard script from `%s'", + sieve_script_location(script)); + } + + sbin = lda_sieve_open(srctx, script, cpflags, FALSE, error_r); + if (sbin == NULL) + return 0; + + /* Execute */ + + e_debug(sieve_get_event(svinst), + "Executing script from `%s'", + sieve_get_source(sbin)); + + if (!discard_script) { + ret = (sieve_multiscript_run(mscript, sbin, exec_ehandler, + exec_ehandler, exflags) ? 1 : 0); + } else { + sieve_multiscript_run_discard(mscript, sbin, exec_ehandler, + exec_ehandler, exflags); + ret = 0; + } + + mstatus = sieve_multiscript_status(mscript); + if (ret == 0 && mstatus == SIEVE_EXEC_BIN_CORRUPT && + sieve_is_loaded(sbin)) { + /* Close corrupt script */ + + sieve_close(&sbin); + + /* Recompile */ + + sbin = lda_sieve_open(srctx, script, cpflags, TRUE, + error_r); + if (sbin == NULL) + return 0; + + /* Execute again */ + + if (!discard_script) { + ret = (sieve_multiscript_run( + mscript, sbin, exec_ehandler, + exec_ehandler, exflags) ? 1 : 0); + } else { + sieve_multiscript_run_discard( + mscript, sbin, exec_ehandler, + exec_ehandler, exflags); + } + + /* Save new version */ + + mstatus = sieve_multiscript_status(mscript); + if (mstatus != SIEVE_EXEC_BIN_CORRUPT) + lda_sieve_binary_save(srctx, sbin, script); + } + if (ret == 0 && mstatus == SIEVE_EXEC_RESOURCE_LIMIT) + ret = -1; + + if (user_script) + (void)sieve_record_resource_usage(sbin, rusage); + + sieve_close(&sbin); + + return ret; +} + +static int lda_sieve_execute_scripts(struct lda_sieve_run_context *srctx) +{ + struct sieve_instance *svinst = srctx->svinst; + struct sieve_multiscript *mscript; + struct sieve_error_handler *exec_ehandler; + struct sieve_script *script, *last_script = NULL; + enum sieve_execute_flags exflags = SIEVE_EXECUTE_FLAG_LOG_RESULT; + bool discard_script; + enum sieve_error error; + unsigned int i; + int ret; + + i_assert(srctx->script_count > 0); + + /* Start execution */ + + mscript = sieve_multiscript_start_execute(svinst, srctx->msgdata, + srctx->scriptenv); + + /* Execute scripts */ + + i = 0; + discard_script = FALSE; + error = SIEVE_ERROR_NONE; + for (;;) { + if (!discard_script) { + /* normal script sequence */ + i_assert(i < srctx->script_count); + script = srctx->scripts[i]; + i++; + } else { + /* discard script */ + script = srctx->discard_script; + } + + i_assert(script != NULL); + last_script = script; + + ret = lda_sieve_execute_script(srctx, mscript, script, i, + discard_script, &error); + if (ret < 0) + break; + if (error == SIEVE_ERROR_NOT_FOUND) { + /* skip scripts which finally turn out not to exist */ + ret = 1; + } + + if (discard_script) { + /* Executed discard script, which is always final */ + break; + } else if (ret > 0) { + /* The "keep" action is applied; execute next script */ + i_assert(i <= srctx->script_count); + if (i == srctx->script_count) { + /* End of normal script sequence */ + break; + } + } else if (error != SIEVE_ERROR_NONE) { + break; + } else if (sieve_multiscript_will_discard(mscript) && + srctx->discard_script != NULL) { + /* Mail is set to be discarded, but we have a discard script. */ + discard_script = TRUE; + } else { + break; + } + } + + /* Finish execution */ + exec_ehandler = (srctx->user_ehandler != NULL ? + srctx->user_ehandler : srctx->master_ehandler); + ret = sieve_multiscript_finish(&mscript, exec_ehandler, exflags, + (error == SIEVE_ERROR_TEMP_FAILURE ? + SIEVE_EXEC_TEMP_FAILURE : + SIEVE_EXEC_OK)); + + /* Don't log additional messages about compile failure */ + if (error != SIEVE_ERROR_NONE && ret == SIEVE_EXEC_FAILURE) { + e_info(sieve_get_event(svinst), + "Aborted script execution sequence with successful implicit keep"); + return 1; + } + + return lda_sieve_handle_exec_status(srctx, last_script, ret); +} + +static int lda_sieve_find_scripts(struct lda_sieve_run_context *srctx) +{ + struct mail_deliver_context *mdctx = srctx->mdctx; + struct sieve_instance *svinst = srctx->svinst; + struct sieve_storage *main_storage; + const char *sieve_before, *sieve_after, *sieve_discard; + const char *setting_name; + enum sieve_error error; + ARRAY_TYPE(sieve_script) script_sequence; + struct sieve_script *const *scripts; + unsigned int after_index, count, i; + int ret = 1; + + /* Find the personal script to execute */ + + ret = lda_sieve_get_personal_storage(svinst, mdctx->rcpt_user, + &main_storage, &error); + if (ret == 0 && error == SIEVE_ERROR_NOT_POSSIBLE) + return 0; + if (ret > 0) { + srctx->main_script = + sieve_storage_active_script_open(main_storage, &error); + + if (srctx->main_script == NULL) { + switch (error) { + case SIEVE_ERROR_NOT_FOUND: + e_debug(sieve_get_event(svinst), + "User has no active script in storage `%s'", + sieve_storage_location(main_storage)); + break; + case SIEVE_ERROR_TEMP_FAILURE: + e_error(sieve_get_event(svinst), + "Failed to access active Sieve script in user storage `%s' " + "(temporary failure)", + sieve_storage_location(main_storage)); + ret = -1; + break; + default: + e_error(sieve_get_event(svinst), + "Failed to access active Sieve script in user storage `%s'", + sieve_storage_location(main_storage)); + break; + } + } else if (!sieve_script_is_default(srctx->main_script)) { + srctx->user_script = srctx->main_script; + } + sieve_storage_unref(&main_storage); + } + + if (ret >= 0 && srctx->main_script == NULL) { + e_debug(sieve_get_event(svinst), + "User has no personal script"); + } + + /* Compose script array */ + + t_array_init(&script_sequence, 16); + + /* before */ + if (ret >= 0) { + i = 2; + setting_name = "sieve_before"; + sieve_before = mail_user_plugin_getenv( + mdctx->rcpt_user, setting_name); + while (ret >= 0 && + sieve_before != NULL && *sieve_before != '\0') { + ret = lda_sieve_multiscript_get_scripts( + svinst, setting_name, sieve_before, + &script_sequence, &error); + if (ret < 0 && error == SIEVE_ERROR_TEMP_FAILURE) { + ret = -1; + break; + } else if (ret == 0) { + e_debug(sieve_get_event(svinst), + "Location for %s not found: %s", + setting_name, sieve_before); + } + ret = 0; + setting_name = t_strdup_printf("sieve_before%u", i++); + sieve_before = mail_user_plugin_getenv( + mdctx->rcpt_user, setting_name); + } + + if (ret >= 0) { + scripts = array_get(&script_sequence, &count); + for (i = 0; i < count; i ++) { + e_debug(sieve_get_event(svinst), + "Executed before user's personal Sieve script(%d): %s", + i+1, sieve_script_location(scripts[i])); + } + } + } + + /* main */ + if (srctx->main_script != NULL) { + array_append(&script_sequence, &srctx->main_script, 1); + + if (ret >= 0) { + e_debug(sieve_get_event(svinst), + "Using the following location for user's Sieve script: %s", + sieve_script_location(srctx->main_script)); + } + } + + after_index = array_count(&script_sequence); + + /* after */ + if (ret >= 0) { + i = 2; + setting_name = "sieve_after"; + sieve_after = mail_user_plugin_getenv(mdctx->rcpt_user, setting_name); + while (sieve_after != NULL && *sieve_after != '\0') { + ret = lda_sieve_multiscript_get_scripts( + svinst, setting_name, sieve_after, + &script_sequence, &error); + if (ret < 0 && error == SIEVE_ERROR_TEMP_FAILURE) { + ret = -1; + break; + } else if (ret == 0) { + e_debug(sieve_get_event(svinst), + "Location for %s not found: %s", + setting_name, sieve_after); + } + ret = 0; + setting_name = t_strdup_printf("sieve_after%u", i++); + sieve_after = mail_user_plugin_getenv( + mdctx->rcpt_user, setting_name); + } + + if (ret >= 0) { + scripts = array_get(&script_sequence, &count); + for ( i = after_index; i < count; i ++ ) { + e_debug(sieve_get_event(svinst), + "executed after user's Sieve script(%d): %s", + i+1, sieve_script_location(scripts[i])); + } + } + } + + /* discard */ + sieve_discard = mail_user_plugin_getenv( + mdctx->rcpt_user, "sieve_discard"); + if (sieve_discard != NULL && *sieve_discard != '\0') { + srctx->discard_script = sieve_script_create_open( + svinst, sieve_discard, NULL, &error); + if (srctx->discard_script == NULL) { + switch (error) { + case SIEVE_ERROR_NOT_FOUND: + e_debug(sieve_get_event(svinst), + "Location for sieve_discard not found: %s", + sieve_discard); + break; + case SIEVE_ERROR_TEMP_FAILURE: + ret = -1; + break; + default: + break; + } + } + } + + if (ret < 0) { + mdctx->tempfail_error = + "Temporarily unable to access necessary Sieve scripts"; + } + srctx->scripts = + array_get_modifiable(&script_sequence, &srctx->script_count); + return ret; +} + +static void +lda_sieve_free_scripts(struct lda_sieve_run_context *srctx) +{ + unsigned int i; + + for (i = 0; i < srctx->script_count; i++) + sieve_script_unref(&srctx->scripts[i]); + if (srctx->discard_script != NULL) + sieve_script_unref(&srctx->discard_script); +} + +static void +lda_sieve_init_trace_log(struct lda_sieve_run_context *srctx, + const struct smtp_address *mail_from, + struct sieve_trace_config *trace_config_r, + struct sieve_trace_log **trace_log_r) +{ + struct mail_deliver_context *mdctx = srctx->mdctx; + struct sieve_instance *svinst = srctx->svinst; + struct sieve_trace_log *trace_log = NULL; + + if (sieve_trace_config_get(svinst, trace_config_r) < 0 || + sieve_trace_log_open(svinst, &trace_log) < 0) { + i_zero(trace_config_r); + *trace_log_r = NULL; + return; + } + + /* Write header for trace file */ + sieve_trace_log_printf(trace_log, + "Sieve trace log for message delivery:\n" + "\n" + " Username: %s\n", mdctx->rcpt_user->username); + if (mdctx->rcpt_user->session_id != NULL) { + sieve_trace_log_printf(trace_log, + " Session ID: %s\n", + mdctx->rcpt_user->session_id); + } + sieve_trace_log_printf(trace_log, + " Sender: %s\n" + " Final recipient: %s\n" + " Default mailbox: %s\n\n", + smtp_address_encode_path(mail_from), + smtp_address_encode_path(mdctx->rcpt_to), + (mdctx->rcpt_default_mailbox != NULL ? + mdctx->rcpt_default_mailbox : "INBOX")); + + *trace_log_r = trace_log; +} + +static int +lda_sieve_execute(struct lda_sieve_run_context *srctx, + struct mail_storage **storage_r) +{ + struct mail_deliver_context *mdctx = srctx->mdctx; + struct sieve_instance *svinst = srctx->svinst; + struct sieve_message_data msgdata; + struct sieve_script_env scriptenv; + struct sieve_exec_status estatus; + struct sieve_trace_config trace_config; + const struct smtp_address *mail_from; + struct sieve_trace_log *trace_log; + const char *error; + int ret; + + /* Check whether there are any scripts to execute at all */ + + if (srctx->script_count == 0) { + e_debug(sieve_get_event(svinst), + "No scripts to execute: " + "reverting to default delivery."); + + /* No error, but no delivery by this plugin either. A return + value of <= 0 for a deliver plugin is is considered a + failure. In deliver itself, saved_mail and tried_default_save + remain unset, meaning that deliver will then attempt the + default delivery. We return 0 to signify the lack of a real + error. + */ + return 0; + } + + /* Initialize user error handler */ + + if (srctx->user_script != NULL) { + const char *log_path = + sieve_user_get_log_path(svinst, srctx->user_script); + + if (log_path != NULL) { + srctx->userlog = log_path; + srctx->user_ehandler = sieve_logfile_ehandler_create( + svinst, srctx->userlog, + LDA_SIEVE_MAX_USER_ERRORS); + } + } + + /* Determine return address */ + + mail_from = mail_deliver_get_return_address(mdctx); + + /* Initialize trace logging */ + + lda_sieve_init_trace_log(srctx, mail_from, &trace_config, &trace_log); + + /* Collect necessary message data */ + + i_zero(&msgdata); + + msgdata.mail = mdctx->src_mail; + msgdata.auth_user = mdctx->rcpt_user->username; + msgdata.envelope.mail_from = mail_from; + msgdata.envelope.mail_params = &mdctx->mail_params; + msgdata.envelope.rcpt_to = mdctx->rcpt_to; + msgdata.envelope.rcpt_params = &mdctx->rcpt_params; + (void)mail_get_message_id(msgdata.mail, &msgdata.id); + + srctx->msgdata = &msgdata; + + /* Compose script execution environment */ + + if (sieve_script_env_init(&scriptenv, mdctx->rcpt_user, &error) < 0) { + e_error(sieve_get_event(svinst), + "Failed to initialize script execution: %s", error); + if (trace_log != NULL) + sieve_trace_log_free(&trace_log); + return -1; + } + + scriptenv.default_mailbox = mdctx->rcpt_default_mailbox; + scriptenv.mailbox_autocreate = mdctx->set->lda_mailbox_autocreate; + scriptenv.mailbox_autosubscribe = mdctx->set->lda_mailbox_autosubscribe; + scriptenv.smtp_start = lda_sieve_smtp_start; + scriptenv.smtp_add_rcpt = lda_sieve_smtp_add_rcpt; + scriptenv.smtp_send = lda_sieve_smtp_send; + scriptenv.smtp_abort = lda_sieve_smtp_abort; + scriptenv.smtp_finish = lda_sieve_smtp_finish; + scriptenv.duplicate_transaction_begin = + lda_sieve_duplicate_transaction_begin; + scriptenv.duplicate_transaction_commit = + lda_sieve_duplicate_transaction_commit; + scriptenv.duplicate_transaction_rollback = + lda_sieve_duplicate_transaction_rollback; + scriptenv.duplicate_mark = lda_sieve_duplicate_mark; + scriptenv.duplicate_check = lda_sieve_duplicate_check; + scriptenv.reject_mail = lda_sieve_reject_mail; + scriptenv.result_amend_log_message = lda_sieve_result_amend_log_message; + scriptenv.script_context = (void *) mdctx; + scriptenv.trace_log = trace_log; + scriptenv.trace_config = trace_config; + + i_zero(&estatus); + scriptenv.exec_status = &estatus; + + srctx->scriptenv = &scriptenv; + + /* Execute script(s) */ + + ret = lda_sieve_execute_scripts(srctx); + + /* Record status */ + + mdctx->tried_default_save = estatus.tried_default_save; + *storage_r = estatus.last_storage; + + if (trace_log != NULL) + sieve_trace_log_free(&trace_log); + + return ret; +} + +static int +lda_sieve_deliver_mail(struct mail_deliver_context *mdctx, + struct mail_storage **storage_r) +{ + struct lda_sieve_run_context srctx; + const struct mail_storage_settings *mail_set = + mail_user_set_get_storage_set(mdctx->rcpt_user); + bool debug = mdctx->rcpt_user->mail_debug; + struct sieve_environment svenv; + int ret = 0; + + /* Initialize run context */ + + i_zero(&srctx); + srctx.mdctx = mdctx; + (void)mail_user_get_home(mdctx->rcpt_user, &srctx.home_dir); + + /* Initialize Sieve engine */ + + memset((void*)&svenv, 0, sizeof(svenv)); + svenv.username = mdctx->rcpt_user->username; + svenv.home_dir = srctx.home_dir; + svenv.hostname = mail_set->hostname; + svenv.base_dir = mdctx->rcpt_user->set->base_dir; + svenv.temp_dir = mdctx->rcpt_user->set->mail_temp_dir; + svenv.event_parent = mdctx->event; + svenv.flags = SIEVE_FLAG_HOME_RELATIVE; + svenv.location = SIEVE_ENV_LOCATION_MDA; + svenv.delivery_phase = SIEVE_DELIVERY_PHASE_DURING; + + srctx.svinst = sieve_init(&svenv, &lda_sieve_callbacks, mdctx, debug); + + /* Initialize master error handler */ + + srctx.master_ehandler = sieve_master_ehandler_create(srctx.svinst, 0); + + sieve_error_handler_accept_infolog(srctx.master_ehandler, TRUE); + sieve_error_handler_accept_debuglog(srctx.master_ehandler, debug); + + *storage_r = NULL; + + /* Find Sieve scripts and run them */ + + T_BEGIN { + if (lda_sieve_find_scripts(&srctx) < 0) + ret = -1; + else if (srctx.scripts == NULL) + ret = 0; + else + ret = lda_sieve_execute(&srctx, storage_r); + + lda_sieve_free_scripts(&srctx); + } T_END; + + /* Clean up */ + + if (srctx.user_ehandler != NULL) + sieve_error_handler_unref(&srctx.user_ehandler); + sieve_error_handler_unref(&srctx.master_ehandler); + sieve_deinit(&srctx.svinst); + + return ret; +} + +/* + * Plugin interface + */ + +const char *sieve_plugin_version = DOVECOT_ABI_VERSION; +const char sieve_plugin_binary_dependency[] = "lda lmtp"; + +void sieve_plugin_init(void) +{ + /* Hook into the delivery process */ + next_deliver_mail = mail_deliver_hook_set(lda_sieve_deliver_mail); +} + +void sieve_plugin_deinit(void) +{ + /* Remove hook */ + mail_deliver_hook_set(next_deliver_mail); +} diff --git a/pigeonhole/src/plugins/lda-sieve/lda-sieve-plugin.h b/pigeonhole/src/plugins/lda-sieve/lda-sieve-plugin.h new file mode 100644 index 0000000..2357097 --- /dev/null +++ b/pigeonhole/src/plugins/lda-sieve/lda-sieve-plugin.h @@ -0,0 +1,11 @@ +#ifndef LDA_SIEVE_PLUGIN_H +#define LDA_SIEVE_PLUGIN_H + +/* + * Plugin interface + */ + +void sieve_plugin_init(void); +void sieve_plugin_deinit(void); + +#endif diff --git a/pigeonhole/src/plugins/settings/Makefile.am b/pigeonhole/src/plugins/settings/Makefile.am new file mode 100644 index 0000000..49537e1 --- /dev/null +++ b/pigeonhole/src/plugins/settings/Makefile.am @@ -0,0 +1,12 @@ +settingsdir = $(dovecot_moduledir)/settings + +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) + +libpigeonhole_settings_la_LDFLAGS = -module -avoid-version + +settings_LTLIBRARIES = \ + libpigeonhole_settings.la + +libpigeonhole_settings_la_SOURCES = \ + pigeonhole-settings.c diff --git a/pigeonhole/src/plugins/settings/Makefile.in b/pigeonhole/src/plugins/settings/Makefile.in new file mode 100644 index 0000000..ee34c03 --- /dev/null +++ b/pigeonhole/src/plugins/settings/Makefile.in @@ -0,0 +1,737 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/plugins/settings +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(settingsdir)" +LTLIBRARIES = $(settings_LTLIBRARIES) +libpigeonhole_settings_la_LIBADD = +am_libpigeonhole_settings_la_OBJECTS = pigeonhole-settings.lo +libpigeonhole_settings_la_OBJECTS = \ + $(am_libpigeonhole_settings_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libpigeonhole_settings_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libpigeonhole_settings_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/pigeonhole-settings.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libpigeonhole_settings_la_SOURCES) +DIST_SOURCES = $(libpigeonhole_settings_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +settingsdir = $(dovecot_moduledir)/settings +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) + +libpigeonhole_settings_la_LDFLAGS = -module -avoid-version +settings_LTLIBRARIES = \ + libpigeonhole_settings.la + +libpigeonhole_settings_la_SOURCES = \ + pigeonhole-settings.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/settings/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/plugins/settings/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-settingsLTLIBRARIES: $(settings_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(settings_LTLIBRARIES)'; test -n "$(settingsdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(settingsdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(settingsdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(settingsdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(settingsdir)"; \ + } + +uninstall-settingsLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(settings_LTLIBRARIES)'; test -n "$(settingsdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(settingsdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(settingsdir)/$$f"; \ + done + +clean-settingsLTLIBRARIES: + -test -z "$(settings_LTLIBRARIES)" || rm -f $(settings_LTLIBRARIES) + @list='$(settings_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libpigeonhole_settings.la: $(libpigeonhole_settings_la_OBJECTS) $(libpigeonhole_settings_la_DEPENDENCIES) $(EXTRA_libpigeonhole_settings_la_DEPENDENCIES) + $(AM_V_CCLD)$(libpigeonhole_settings_la_LINK) -rpath $(settingsdir) $(libpigeonhole_settings_la_OBJECTS) $(libpigeonhole_settings_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pigeonhole-settings.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(settingsdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-settingsLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/pigeonhole-settings.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-settingsLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/pigeonhole-settings.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-settingsLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-settingsLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am \ + install-settingsLTLIBRARIES install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am \ + uninstall-settingsLTLIBRARIES + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/plugins/settings/pigeonhole-settings.c b/pigeonhole/src/plugins/settings/pigeonhole-settings.c new file mode 100644 index 0000000..21f8e85 --- /dev/null +++ b/pigeonhole/src/plugins/settings/pigeonhole-settings.c @@ -0,0 +1,13 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "pigeonhole-config.h" +#include "pigeonhole-version.h" + +/* This is currently just a dummy plugin that adds a Pigeonhole + * version banner the doveconf output. + */ + +const char *pigeonhole_settings_version = DOVECOT_ABI_VERSION; +const char *pigeonhole_settings_doveconf_banner = "Pigeonhole version "PIGEONHOLE_VERSION_FULL; diff --git a/pigeonhole/src/plugins/sieve-extprograms/Makefile.am b/pigeonhole/src/plugins/sieve-extprograms/Makefile.am new file mode 100644 index 0000000..ab7844f --- /dev/null +++ b/pigeonhole/src/plugins/sieve-extprograms/Makefile.am @@ -0,0 +1,34 @@ +sieve_plugindir = $(dovecot_moduledir)/sieve + +sieve_plugin_LTLIBRARIES = lib90_sieve_extprograms_plugin.la + +lib90_sieve_extprograms_plugin_la_LDFLAGS = -module -avoid-version + +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + -I$(top_srcdir)/src/lib-sieve/util \ + -I$(top_srcdir)/src/lib-sieve/plugins/copy \ + -I$(top_srcdir)/src/lib-sieve/plugins/variables \ + $(LIBDOVECOT_INCLUDE) \ + -DPKG_RUNDIR=\""$(rundir)"\" + +commands = \ + cmd-pipe.c \ + cmd-filter.c \ + cmd-execute.c + +extensions = \ + ext-pipe.c \ + ext-filter.c \ + ext-execute.c + +lib90_sieve_extprograms_plugin_la_SOURCES = \ + $(commands) \ + $(extensions) \ + sieve-extprograms-common.c \ + sieve-extprograms-plugin.c + +noinst_HEADERS = \ + sieve-extprograms-common.h \ + sieve-extprograms-plugin.h + diff --git a/pigeonhole/src/plugins/sieve-extprograms/Makefile.in b/pigeonhole/src/plugins/sieve-extprograms/Makefile.in new file mode 100644 index 0000000..e35da7b --- /dev/null +++ b/pigeonhole/src/plugins/sieve-extprograms/Makefile.in @@ -0,0 +1,790 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/plugins/sieve-extprograms +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(sieve_plugindir)" +LTLIBRARIES = $(sieve_plugin_LTLIBRARIES) +lib90_sieve_extprograms_plugin_la_LIBADD = +am__objects_1 = cmd-pipe.lo cmd-filter.lo cmd-execute.lo +am__objects_2 = ext-pipe.lo ext-filter.lo ext-execute.lo +am_lib90_sieve_extprograms_plugin_la_OBJECTS = $(am__objects_1) \ + $(am__objects_2) sieve-extprograms-common.lo \ + sieve-extprograms-plugin.lo +lib90_sieve_extprograms_plugin_la_OBJECTS = \ + $(am_lib90_sieve_extprograms_plugin_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +lib90_sieve_extprograms_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) \ + --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ + $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(lib90_sieve_extprograms_plugin_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/cmd-execute.Plo \ + ./$(DEPDIR)/cmd-filter.Plo ./$(DEPDIR)/cmd-pipe.Plo \ + ./$(DEPDIR)/ext-execute.Plo ./$(DEPDIR)/ext-filter.Plo \ + ./$(DEPDIR)/ext-pipe.Plo \ + ./$(DEPDIR)/sieve-extprograms-common.Plo \ + ./$(DEPDIR)/sieve-extprograms-plugin.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(lib90_sieve_extprograms_plugin_la_SOURCES) +DIST_SOURCES = $(lib90_sieve_extprograms_plugin_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +sieve_plugindir = $(dovecot_moduledir)/sieve +sieve_plugin_LTLIBRARIES = lib90_sieve_extprograms_plugin.la +lib90_sieve_extprograms_plugin_la_LDFLAGS = -module -avoid-version +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + -I$(top_srcdir)/src/lib-sieve/util \ + -I$(top_srcdir)/src/lib-sieve/plugins/copy \ + -I$(top_srcdir)/src/lib-sieve/plugins/variables \ + $(LIBDOVECOT_INCLUDE) \ + -DPKG_RUNDIR=\""$(rundir)"\" + +commands = \ + cmd-pipe.c \ + cmd-filter.c \ + cmd-execute.c + +extensions = \ + ext-pipe.c \ + ext-filter.c \ + ext-execute.c + +lib90_sieve_extprograms_plugin_la_SOURCES = \ + $(commands) \ + $(extensions) \ + sieve-extprograms-common.c \ + sieve-extprograms-plugin.c + +noinst_HEADERS = \ + sieve-extprograms-common.h \ + sieve-extprograms-plugin.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/sieve-extprograms/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/plugins/sieve-extprograms/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-sieve_pluginLTLIBRARIES: $(sieve_plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(sieve_plugin_LTLIBRARIES)'; test -n "$(sieve_plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(sieve_plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sieve_plugindir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(sieve_plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(sieve_plugindir)"; \ + } + +uninstall-sieve_pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(sieve_plugin_LTLIBRARIES)'; test -n "$(sieve_plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(sieve_plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(sieve_plugindir)/$$f"; \ + done + +clean-sieve_pluginLTLIBRARIES: + -test -z "$(sieve_plugin_LTLIBRARIES)" || rm -f $(sieve_plugin_LTLIBRARIES) + @list='$(sieve_plugin_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +lib90_sieve_extprograms_plugin.la: $(lib90_sieve_extprograms_plugin_la_OBJECTS) $(lib90_sieve_extprograms_plugin_la_DEPENDENCIES) $(EXTRA_lib90_sieve_extprograms_plugin_la_DEPENDENCIES) + $(AM_V_CCLD)$(lib90_sieve_extprograms_plugin_la_LINK) -rpath $(sieve_plugindir) $(lib90_sieve_extprograms_plugin_la_OBJECTS) $(lib90_sieve_extprograms_plugin_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-execute.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-filter.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-pipe.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-execute.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-filter.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-pipe.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-extprograms-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-extprograms-plugin.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(sieve_plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-sieve_pluginLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-execute.Plo + -rm -f ./$(DEPDIR)/cmd-filter.Plo + -rm -f ./$(DEPDIR)/cmd-pipe.Plo + -rm -f ./$(DEPDIR)/ext-execute.Plo + -rm -f ./$(DEPDIR)/ext-filter.Plo + -rm -f ./$(DEPDIR)/ext-pipe.Plo + -rm -f ./$(DEPDIR)/sieve-extprograms-common.Plo + -rm -f ./$(DEPDIR)/sieve-extprograms-plugin.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-sieve_pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/cmd-execute.Plo + -rm -f ./$(DEPDIR)/cmd-filter.Plo + -rm -f ./$(DEPDIR)/cmd-pipe.Plo + -rm -f ./$(DEPDIR)/ext-execute.Plo + -rm -f ./$(DEPDIR)/ext-filter.Plo + -rm -f ./$(DEPDIR)/ext-pipe.Plo + -rm -f ./$(DEPDIR)/sieve-extprograms-common.Plo + -rm -f ./$(DEPDIR)/sieve-extprograms-plugin.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-sieve_pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-sieve_pluginLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am \ + install-sieve_pluginLTLIBRARIES install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am \ + uninstall-sieve_pluginLTLIBRARIES + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/plugins/sieve-extprograms/cmd-execute.c b/pigeonhole/src/plugins/sieve-extprograms/cmd-execute.c new file mode 100644 index 0000000..79f6663 --- /dev/null +++ b/pigeonhole/src/plugins/sieve-extprograms/cmd-execute.c @@ -0,0 +1,488 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "buffer.h" +#include "str.h" +#include "str-sanitize.h" +#include "istream.h" +#include "ostream.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-result.h" + +#include "sieve-ext-variables.h" + +#include "sieve-extprograms-common.h" + +/* Execute command + * + * Syntax: + * "execute" [":input" <input-data: string> / ":pipe"] + * [":output" <varname: string>] + * <program-name: string> [<arguments: string-list>] + * + */ + +static bool +cmd_execute_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool +cmd_execute_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def sieve_cmd_execute = { + .identifier = "execute", + .type = SCT_HYBRID, + .positional_args = -1, /* We check positional arguments ourselves */ + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_execute_registered, + .validate = sieve_extprogram_command_validate, + .generate = cmd_execute_generate, +}; + +/* + * Tagged arguments + */ + +static bool +cmd_execute_validate_input_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +cmd_execute_generate_input_tag(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, + struct sieve_command *cmd); + +static bool +cmd_execute_validate_output_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +static const struct sieve_argument_def execute_input_tag = { + .identifier = "input", + .validate = cmd_execute_validate_input_tag, + .generate = cmd_execute_generate_input_tag +}; + +static const struct sieve_argument_def execute_pipe_tag = { + .identifier = "pipe", + .validate = cmd_execute_validate_input_tag, + .generate = cmd_execute_generate_input_tag +}; + +static const struct sieve_argument_def execute_output_tag = { + .identifier = "output", + .validate = cmd_execute_validate_output_tag, +}; + + +/* + * Execute operation + */ + +static bool +cmd_execute_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_execute_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def sieve_opr_execute = { + .mnemonic = "EXECUTE", + .ext_def = &sieve_ext_vnd_execute, + .dump = cmd_execute_operation_dump, + .execute = cmd_execute_operation_execute +}; + +/* Codes for optional operands */ + +enum cmd_execute_optional { + OPT_END, + OPT_INPUT, + OPT_OUTPUT +}; + +/* + * Tag validation + */ + +static bool +cmd_execute_validate_input_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + + if ((bool)cmd->data) { + sieve_argument_validate_error( + valdtr, *arg, + "multiple :input or :pipe arguments specified for the %s %s", + sieve_command_identifier(cmd), + sieve_command_type_name(cmd)); + return FALSE; + } + + cmd->data = (void *)TRUE; + + /* Skip tag */ + *arg = sieve_ast_argument_next(*arg); + + if (sieve_argument_is(tag, execute_input_tag)) { + /* Check syntax: + * :input <input-data: string> + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, + 0, SAAT_STRING, FALSE)) + return FALSE; + + /* Assign tag parameters */ + tag->parameters = *arg; + *arg = sieve_ast_arguments_detach(*arg,1); + } + + return TRUE; +} + +static bool +cmd_execute_validate_output_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct sieve_extprograms_config *ext_config = + (struct sieve_extprograms_config *)cmd->ext->context; + + if (ext_config == NULL || ext_config->var_ext == NULL || + !sieve_ext_variables_is_active(ext_config->var_ext, valdtr)) { + sieve_argument_validate_error( + valdtr,*arg, + "the %s %s only allows for the specification of an " + ":output argument when the variables extension is active", + sieve_command_identifier(cmd), + sieve_command_type_name(cmd)); + return FALSE; + } + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + if (!sieve_variable_argument_activate(ext_config->var_ext, + ext_config->var_ext, valdtr, + cmd, *arg, TRUE)) + return FALSE; + + (*arg)->argument->id_code = tag->argument->id_code; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Command registration + */ + +static bool +cmd_execute_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &execute_input_tag, OPT_INPUT); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &execute_pipe_tag, OPT_INPUT); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &execute_output_tag, OPT_OUTPUT); + return TRUE; +} + +/* + * Code generation + */ + +static bool +cmd_execute_generate_input_tag(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, + struct sieve_command *cmd) +{ + if (arg->parameters == NULL) { + sieve_opr_omitted_emit(cgenv->sblock); + return TRUE; + } + + return sieve_generate_argument_parameters(cgenv, cmd, arg); +} + +static bool +cmd_execute_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &sieve_opr_execute); + + /* Emit is_test flag */ + sieve_binary_emit_byte(cgenv->sblock, + (uint8_t)(cmd->ast_node->type == SAT_TEST ? + 1 : 0)); + + /* Generate arguments */ + if (!sieve_generate_arguments(cgenv, cmd, NULL)) + return FALSE; + + /* Emit a placeholder when the <arguments> argument is missing */ + if (sieve_ast_argument_next(cmd->first_positional) == NULL) + sieve_opr_omitted_emit(cgenv->sblock); + + return TRUE; +} + +/* + * Code dump + */ + +static bool +cmd_execute_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + int opt_code = 0; + unsigned int is_test = 0; + + /* Read is_test flag */ + if (!sieve_binary_read_byte(denv->sblock, address, &is_test)) + return FALSE; + + sieve_code_dumpf(denv, "EXECUTE (%s)", + (is_test > 0 ? "test" : "command")); + sieve_code_descend(denv); + + /* Dump optional operands */ + for (;;) { + int opt; + bool opok = TRUE; + + if ((opt = sieve_action_opr_optional_dump(denv, address, + &opt_code)) < 0) + return FALSE; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_INPUT: + opok = sieve_opr_string_dump_ex(denv, address, + "input", "PIPE"); + break; + case OPT_OUTPUT: + opok = sieve_opr_string_dump(denv, address, "output"); + break; + default: + return FALSE; + } + + if (!opok) + return FALSE; + } + + if (!sieve_opr_string_dump(denv, address, "program-name")) + return FALSE; + + return sieve_opr_stringlist_dump_ex(denv, address, "arguments", ""); +} + +/* + * Code execution + */ + +static int +cmd_execute_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct sieve_side_effects_list *slist = NULL; + int opt_code = 0; + unsigned int is_test = 0; + struct sieve_stringlist *args_list = NULL; + string_t *pname = NULL, *input = NULL; + struct sieve_variable_storage *var_storage = NULL; + unsigned int var_index; + bool have_input = FALSE; + const char *program_name = NULL; + const char *const *args = NULL; + enum sieve_error error = SIEVE_ERROR_NONE; + buffer_t *outbuf = NULL; + struct sieve_extprogram *sprog = NULL; + int ret; + + /* + * Read operands + */ + + /* The is_test flag */ + if (!sieve_binary_read_byte(renv->sblock, address, &is_test)) { + sieve_runtime_trace_error(renv, "invalid is_test flag"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + /* Optional operands */ + + for (;;) { + int opt; + + if ((opt = sieve_action_opr_optional_read( + renv, address, &opt_code, &ret, &slist)) < 0) + return ret; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_INPUT: + ret = sieve_opr_string_read_ex(renv, address, "input", + TRUE, &input, NULL); + have_input = TRUE; + break; + case OPT_OUTPUT: + ret = sieve_variable_operand_read( + renv, address, "output", &var_storage, + &var_index); + break; + default: + sieve_runtime_trace_error( + renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if (ret <= 0) + return ret; + } + + /* Fixed operands */ + + if ((ret = sieve_extprogram_command_read_operands( + renv, address, &pname, &args_list)) <= 0) + return ret; + + program_name = str_c(pname); + if (args_list != NULL && + sieve_stringlist_read_all(args_list, pool_datastack_create(), + &args) < 0) { + sieve_runtime_trace_error(renv, "failed to read args operand"); + return args_list->exec_status; + } + + /* + * Perform operation + */ + + /* Trace */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "execute action"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, + "execute program `%s'", + str_sanitize(program_name, 128)); + + sprog = sieve_extprogram_create(this_ext, eenv->scriptenv, + eenv->msgdata, "execute", + program_name, args, &error); + if (sprog != NULL) { + if (var_storage != NULL) { + // FIXME: limit output size + struct ostream *outdata; + + outbuf = buffer_create_dynamic(default_pool, 1024); + outdata = o_stream_create_buffer(outbuf); + sieve_extprogram_set_output(sprog, outdata); + o_stream_unref(&outdata); + } + + if (input == NULL && have_input) { + struct mail *mail = sieve_message_get_mail(renv->msgctx); + + if (sieve_extprogram_set_input_mail(sprog, mail) < 0) { + sieve_extprogram_destroy(&sprog); + if (outbuf != NULL) + buffer_free(&outbuf); + return sieve_runtime_mail_error( + renv, mail, "execute action: " + "failed to read input message"); + } + ret = 1; + } else if (input != NULL) { + struct istream *indata = + i_stream_create_from_data(str_data(input), + str_len(input)); + sieve_extprogram_set_input(sprog, indata); + i_stream_unref(&indata); + ret = 1; + } + + if (ret >= 0) + ret = sieve_extprogram_run(sprog); + sieve_extprogram_destroy(&sprog); + } else { + ret = -1; + } + + if (ret > 0) { + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, + "executed program successfully"); + + if (var_storage != NULL) { + string_t *var; + + if (sieve_variable_get_modifiable(var_storage, + var_index, &var)) { + str_truncate(var, 0); + str_append_str(var, outbuf); + + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, + "assigned output variable"); + } // FIXME: handle failure + } + + } else if (ret < 0) { + if (error == SIEVE_ERROR_NOT_FOUND) { + sieve_runtime_error( + renv, NULL, + "execute action: program `%s' not found", + str_sanitize(program_name, 80)); + } else { + sieve_extprogram_exec_error( + renv->ehandler, + sieve_runtime_get_full_command_location(renv), + "execute action: failed to execute to program `%s'", + str_sanitize(program_name, 80)); + } + } else { + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, + "execute action: " + "program indicated false result"); + } + + if (outbuf != NULL) + buffer_free(&outbuf); + + if (is_test > 0) { + sieve_interpreter_set_test_result(renv->interp, (ret > 0)); + return SIEVE_EXEC_OK; + } + return (ret >= 0 ? SIEVE_EXEC_OK : SIEVE_EXEC_FAILURE); +} diff --git a/pigeonhole/src/plugins/sieve-extprograms/cmd-filter.c b/pigeonhole/src/plugins/sieve-extprograms/cmd-filter.c new file mode 100644 index 0000000..7118ff1 --- /dev/null +++ b/pigeonhole/src/plugins/sieve-extprograms/cmd-filter.c @@ -0,0 +1,254 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "buffer.h" +#include "str.h" +#include "str-sanitize.h" +#include "istream.h" +#include "ostream.h" +#include "safe-mkstemp.h" +#include "mail-user.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-result.h" + +#include "sieve-ext-variables.h" + +#include "sieve-extprograms-common.h" + +/* Filter command + * + * Syntax: + * "filter" <program-name: string> [<arguments: string-list>] + * + */ + +static bool +cmd_filter_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def sieve_cmd_filter = { + .identifier = "filter", + .type = SCT_HYBRID, + .positional_args = -1, /* We check positional arguments ourselves */ + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = sieve_extprogram_command_validate, + .generate = cmd_filter_generate +}; + +/* + * Filter operation + */ + +static bool +cmd_filter_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_filter_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def sieve_opr_filter = { + .mnemonic = "FILTER", + .ext_def = &sieve_ext_vnd_filter, + .dump = cmd_filter_operation_dump, + .execute = cmd_filter_operation_execute +}; + +/* + * Code generation + */ + +static bool +cmd_filter_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &sieve_opr_filter); + + /* Emit is_test flag */ + sieve_binary_emit_byte(cgenv->sblock, + (uint8_t)(cmd->ast_node->type == SAT_TEST ? + 1 : 0)); + + /* Generate arguments */ + if (!sieve_generate_arguments(cgenv, cmd, NULL)) + return FALSE; + + /* Emit a placeholder when the <arguments> argument is missing */ + if (sieve_ast_argument_next(cmd->first_positional) == NULL) + sieve_opr_omitted_emit(cgenv->sblock); + return TRUE; +} + +/* + * Code dump + */ + +static bool +cmd_filter_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + unsigned int is_test = 0; + + /* Read is_test flag */ + if (!sieve_binary_read_byte(denv->sblock, address, &is_test)) + return FALSE; + + sieve_code_dumpf(denv, "FILTER (%s)", + (is_test > 0 ? "test" : "command")); + sieve_code_descend(denv); + + /* Dump optional operands */ + if (sieve_action_opr_optional_dump(denv, address, NULL) != 0) + return FALSE; + + if (!sieve_opr_string_dump(denv, address, "program-name")) + return FALSE; + + return sieve_opr_stringlist_dump_ex(denv, address, "arguments", ""); +} + +/* + * Code execution + */ + +static int +cmd_filter_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_extension *this_ext = renv->oprtn->ext; + unsigned int is_test = 0; + struct sieve_stringlist *args_list = NULL; + enum sieve_error error = SIEVE_ERROR_NONE; + string_t *pname = NULL; + const char *program_name = NULL; + const char *const *args = NULL; + struct istream *newmsg = NULL; + struct sieve_extprogram *sprog; + int ret; + + /* + * Read operands + */ + + /* The is_test flag */ + + if (!sieve_binary_read_byte(renv->sblock, address, &is_test)) { + sieve_runtime_trace_error(renv, "invalid is_test flag"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + /* Optional operands */ + + if (sieve_action_opr_optional_read(renv, address, NULL, + &ret, NULL) != 0) + return ret; + + /* Fixed operands */ + + if ((ret = sieve_extprogram_command_read_operands(renv, address, &pname, + &args_list)) <= 0) + return ret; + + program_name = str_c(pname); + if (args_list != NULL && + sieve_stringlist_read_all(args_list, pool_datastack_create(), + &args) < 0) { + sieve_runtime_trace_error(renv, "failed to read args operand"); + return args_list->exec_status; + } + + /* + * Perform operation + */ + + /* Trace */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "filter action"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, + "execute program `%s'", str_sanitize(program_name, 128)); + + sprog = sieve_extprogram_create(this_ext, eenv->scriptenv, + eenv->msgdata, "filter", + program_name, args, &error); + if (sprog != NULL) { + struct mail *mail = sieve_message_get_mail(renv->msgctx); + + if (sieve_extprogram_set_input_mail(sprog, mail) < 0) { + sieve_extprogram_destroy(&sprog); + return sieve_runtime_mail_error( + renv, mail, + "filter action: failed to read input message"); + } + sieve_extprogram_set_output_seekable(sprog); + ret = sieve_extprogram_run(sprog); + } else { + ret = -1; + } + + if (ret > 0) + newmsg = sieve_extprogram_get_output_seekable(sprog); + if (sprog != NULL) + sieve_extprogram_destroy(&sprog); + + if (ret > 0 && newmsg != NULL) { + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, + "executed program successfully"); + + i_stream_set_name(newmsg, t_strdup_printf("filter %s output", + program_name)); + newmsg->blocking = TRUE; + if ((ret = sieve_message_substitute(renv->msgctx, + newmsg)) >= 0) { + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, + "changed message"); + } else { + sieve_runtime_critical(renv, NULL, "filter action", + "filter action: " + "failed to substitute message"); + } + + i_stream_unref(&newmsg); + } else if (ret < 0) { + if (error == SIEVE_ERROR_NOT_FOUND) { + sieve_runtime_error(renv, NULL, "filter action: " + "program `%s' not found", + str_sanitize(program_name, 80)); + } else { + sieve_extprogram_exec_error( + renv->ehandler, + sieve_runtime_get_full_command_location(renv), + "filter action: " + "failed to execute to program `%s'", + str_sanitize(program_name, 80)); + } + + } else { + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "filter action: " + "program indicated false result"); + } + + if (is_test > 0) { + sieve_interpreter_set_test_result(renv->interp, (ret > 0)); + + return SIEVE_EXEC_OK; + } + + return (ret >= 0 ? SIEVE_EXEC_OK : SIEVE_EXEC_FAILURE); +} diff --git a/pigeonhole/src/plugins/sieve-extprograms/cmd-pipe.c b/pigeonhole/src/plugins/sieve-extprograms/cmd-pipe.c new file mode 100644 index 0000000..f5a5c34 --- /dev/null +++ b/pigeonhole/src/plugins/sieve-extprograms/cmd-pipe.c @@ -0,0 +1,457 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "str.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-result.h" + +#include "sieve-extprograms-common.h" + +/* Pipe command + * + * Syntax: + * pipe [":copy"] [":try"] <program-name: string> [<arguments: string-list>] + * + */ + +static bool +cmd_pipe_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool +cmd_pipe_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def sieve_cmd_pipe = { + .identifier = "pipe", + .type = SCT_COMMAND, + .positional_args = -1, /* We check positional arguments ourselves */ + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_pipe_registered, + .validate = sieve_extprogram_command_validate, + .generate = cmd_pipe_generate, +}; + +/* + * Tagged arguments + */ + +static const struct sieve_argument_def pipe_try_tag = { + .identifier = "try", +}; + +/* + * Pipe operation + */ + +static bool +cmd_pipe_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_pipe_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def sieve_opr_pipe = { + .mnemonic = "PIPE", + .ext_def = &sieve_ext_vnd_pipe, + .dump = cmd_pipe_operation_dump, + .execute = cmd_pipe_operation_execute, +}; + +/* Codes for optional operands */ + +enum cmd_pipe_optional { + OPT_END, + OPT_TRY, +}; + +/* + * Pipe action + */ + +/* Forward declarations */ + +static int +act_pipe_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other); +static void +act_pipe_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, + bool *keep); +static int +act_pipe_start(const struct sieve_action_exec_env *aenv, void **tr_context); +static int +act_pipe_execute(const struct sieve_action_exec_env *aenv, + void *tr_context, bool *keep); +static int +act_pipe_commit(const struct sieve_action_exec_env *aenv, + void *tr_context); +static void +act_pipe_rollback(const struct sieve_action_exec_env *aenv, + void *tr_context, bool success); + +/* Action object */ + +const struct sieve_action_def act_pipe = { + .name = "pipe", + .flags = SIEVE_ACTFLAG_TRIES_DELIVER, + .check_duplicate = act_pipe_check_duplicate, + .print = act_pipe_print, + .start = act_pipe_start, + .execute = act_pipe_execute, + .commit = act_pipe_commit, + .rollback = act_pipe_rollback, +}; + +/* Action context information */ + +struct ext_pipe_action { + const char *program_name; + const char * const *args; + bool try; +}; + +/* + * Command registration + */ + +static bool +cmd_pipe_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &pipe_try_tag, OPT_TRY); + return TRUE; +} + +/* + * Code generation + */ + +static bool +cmd_pipe_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &sieve_opr_pipe); + + /* Generate arguments */ + if (!sieve_generate_arguments(cgenv, cmd, NULL)) + return FALSE; + + /* Emit a placeholder when the <arguments> argument is missing */ + if (sieve_ast_argument_next(cmd->first_positional) == NULL) + sieve_opr_omitted_emit(cgenv->sblock); + return TRUE; +} + +/* + * Code dump + */ + +static bool +cmd_pipe_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "PIPE"); + sieve_code_descend(denv); + + /* Dump optional operands */ + for (;;) { + int opt; + + if ((opt = sieve_action_opr_optional_dump(denv, address, + &opt_code)) < 0) + return FALSE; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_TRY: + sieve_code_dumpf(denv, "try"); + break; + default: + return FALSE; + } + } + + if (!sieve_opr_string_dump(denv, address, "program-name")) + return FALSE; + + return sieve_opr_stringlist_dump_ex(denv, address, "arguments", ""); +} + +/* + * Code execution + */ + +static int +cmd_pipe_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct sieve_side_effects_list *slist = NULL; + struct ext_pipe_action *act; + pool_t pool; + int opt_code = 0; + struct sieve_stringlist *args_list = NULL; + string_t *pname = NULL; + bool try = FALSE; + int ret; + + /* + * Read operands + */ + + /* Optional operands */ + + for (;;) { + int opt; + + if ((opt = sieve_action_opr_optional_read(renv, address, + &opt_code, &ret, + &slist)) < 0) + return ret; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_TRY: + try = TRUE; + break; + default: + sieve_runtime_trace_error( + renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + } + + /* Fixed operands */ + + if ((ret = sieve_extprogram_command_read_operands(renv, address, &pname, + &args_list)) <= 0) + return ret; + + /* + * Perform operation + */ + + /* Trace */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "pipe action"); + + /* Compose action */ + + pool = sieve_result_pool(renv->result); + act = p_new(pool, struct ext_pipe_action, 1); + + if (args_list != NULL && + sieve_stringlist_read_all(args_list, pool, &act->args) < 0) { + sieve_runtime_trace_error(renv, "failed to read args operand"); + return args_list->exec_status; + } + + act->program_name = p_strdup(pool, str_c(pname)); + act->try = try; + + if (sieve_result_add_action(renv, this_ext, "pipe", &act_pipe, slist, + (void *)act, 0, TRUE) < 0) + return SIEVE_EXEC_FAILURE; + return SIEVE_EXEC_OK; +} + +/* + * Action + */ + +/* Runtime verification */ + +static int +act_pipe_check_duplicate(const struct sieve_runtime_env *renv ATTR_UNUSED, + const struct sieve_action *act, + const struct sieve_action *act_other) +{ + struct ext_pipe_action *new_act, *old_act; + + if (act->context == NULL || act_other->context == NULL) + return 0; + + new_act = (struct ext_pipe_action *) act->context; + old_act = (struct ext_pipe_action *) act_other->context; + + if (strcmp(new_act->program_name, old_act->program_name) == 0) { + sieve_runtime_error(renv, act->location, + "duplicate pipe \"%s\" action not allowed " + "(previously triggered one was here: %s)", + new_act->program_name, act_other->location); + return -1; + } + + return 0; +} + +/* Result printing */ + +static void +act_pipe_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, + bool *keep ATTR_UNUSED) +{ + const struct ext_pipe_action *act = + (const struct ext_pipe_action *)action->context; + + sieve_result_action_printf( + rpenv, "pipe message to external program '%s':", + act->program_name); + + /* Print main method parameters */ + + sieve_result_printf( + rpenv, " => try : %s\n", + (act->try ? "yes" : "no")); + + /* FIXME: print args */ + + /* Finish output with an empty line */ + sieve_result_printf(rpenv, "\n"); +} + +/* Result execution */ + +struct act_pipe_transaction { + struct sieve_extprogram *sprog; +}; + +static int +act_pipe_start(const struct sieve_action_exec_env *aenv, void **tr_context) +{ + struct act_pipe_transaction *trans; + pool_t pool = sieve_result_pool(aenv->result); + + /* Create transaction context */ + trans = p_new(pool, struct act_pipe_transaction, 1); + *tr_context = (void *)trans; + + return SIEVE_EXEC_OK; +} + +static int +act_pipe_execute(const struct sieve_action_exec_env *aenv, + void *tr_context, bool *keep) +{ + const struct sieve_action *action = aenv->action; + const struct sieve_execute_env *eenv = aenv->exec_env; + const struct ext_pipe_action *act = + (const struct ext_pipe_action *)action->context; + struct act_pipe_transaction *trans = tr_context; + struct mail *mail = (action->mail != NULL ? + action->mail : + sieve_message_get_mail(aenv->msgctx)); + enum sieve_error error = SIEVE_ERROR_NONE; + + trans->sprog = sieve_extprogram_create(action->ext, eenv->scriptenv, + eenv->msgdata, "pipe", + act->program_name, act->args, + &error); + if (trans->sprog != NULL) { + if (sieve_extprogram_set_input_mail(trans->sprog, mail) < 0) { + sieve_extprogram_destroy(&trans->sprog); + return sieve_result_mail_error( + aenv, mail, "failed to read input message"); + } + } + + *keep = FALSE; + return SIEVE_EXEC_OK; +} + +static int +act_pipe_commit(const struct sieve_action_exec_env *aenv, + void *tr_context ATTR_UNUSED) +{ + const struct sieve_action *action = aenv->action; + const struct sieve_execute_env *eenv = aenv->exec_env; + const struct ext_pipe_action *act = + (const struct ext_pipe_action *)action->context; + struct act_pipe_transaction *trans = tr_context; + enum sieve_error error = SIEVE_ERROR_NONE; + int ret; + + if (trans->sprog != NULL) { + ret = sieve_extprogram_run(trans->sprog); + sieve_extprogram_destroy(&trans->sprog); + } else { + ret = -1; + } + + if (ret > 0) { + struct event_passthrough *e = + sieve_action_create_finish_event(aenv)-> + add_str("pipe_program", + str_sanitize(act->program_name, 256)); + + sieve_result_event_log(aenv, e->event(), + "piped message to program `%s'", + str_sanitize(act->program_name, 128)); + + /* Indicate that message was successfully 'forwarded' */ + eenv->exec_status->message_forwarded = TRUE; + } else { + if (ret < 0) { + if (error == SIEVE_ERROR_NOT_FOUND) { + sieve_result_error( + aenv, + "failed to pipe message to program: " + "program `%s' not found", + str_sanitize(act->program_name, 80)); + } else { + sieve_extprogram_exec_error( + aenv->ehandler, NULL, + "failed to pipe message to program `%s'", + str_sanitize(act->program_name, 80)); + } + } else { + sieve_extprogram_exec_error( + aenv->ehandler, NULL, + "failed to execute to program `%s'", + str_sanitize(act->program_name, 80)); + } + + if (act->try) + return SIEVE_EXEC_OK; + return SIEVE_EXEC_FAILURE; + } + + return SIEVE_EXEC_OK; +} + +static void +act_pipe_rollback(const struct sieve_action_exec_env *aenv ATTR_UNUSED, + void *tr_context, bool success ATTR_UNUSED) +{ + struct act_pipe_transaction *trans = tr_context; + + if (trans->sprog != NULL) + sieve_extprogram_destroy(&trans->sprog); +} diff --git a/pigeonhole/src/plugins/sieve-extprograms/ext-execute.c b/pigeonhole/src/plugins/sieve-extprograms/ext-execute.c new file mode 100644 index 0000000..055ee88 --- /dev/null +++ b/pigeonhole/src/plugins/sieve-extprograms/ext-execute.c @@ -0,0 +1,80 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension vnd.dovecot.execute + * ----------------------------- + * + * Authors: Stephan Bosch + * Specification: vendor-defined; spec-bosch-sieve-extprograms + * Implementation: full + * Status: experimental + * + */ + +#include "lib.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-binary.h" + +#include "sieve-validator.h" +#include "sieve-interpreter.h" + +#include "sieve-ext-copy.h" + +#include "sieve-extprograms-common.h" + +/* + * Extension + */ + +static bool ext_execute_load(const struct sieve_extension *ext, void **context); +static void ext_execute_unload(const struct sieve_extension *ext); +static bool ext_execute_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def sieve_ext_vnd_execute = { + .name = "vnd.dovecot.execute", + .load = ext_execute_load, + .unload = ext_execute_unload, + .validator_load = ext_execute_validator_load, + SIEVE_EXT_DEFINE_OPERATION(sieve_opr_execute) +}; + +/* + * Context + */ + +static bool ext_execute_load(const struct sieve_extension *ext, void **context) +{ + if ( *context != NULL ) { + ext_execute_unload(ext); + *context = NULL; + } + + *context = (void *)sieve_extprograms_config_init(ext); + return TRUE; +} + +static void ext_execute_unload(const struct sieve_extension *ext) +{ + struct sieve_extprograms_config *ext_config = + (struct sieve_extprograms_config *)ext->context; + + if ( ext_config == NULL ) return; + + sieve_extprograms_config_deinit(&ext_config); +} + +/* + * Validation + */ + +static bool ext_execute_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register commands */ + sieve_validator_register_command(valdtr, ext, &sieve_cmd_execute); + + return TRUE; +} diff --git a/pigeonhole/src/plugins/sieve-extprograms/ext-filter.c b/pigeonhole/src/plugins/sieve-extprograms/ext-filter.c new file mode 100644 index 0000000..af1f8f1 --- /dev/null +++ b/pigeonhole/src/plugins/sieve-extprograms/ext-filter.c @@ -0,0 +1,80 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension vnd.dovecot.filter + * ----------------------------- + * + * Authors: Stephan Bosch + * Specification: vendor-defined; spec-bosch-sieve-extprograms + * Implementation: full + * Status: experimental + * + */ + +#include "lib.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-binary.h" + +#include "sieve-validator.h" +#include "sieve-interpreter.h" + +#include "sieve-ext-copy.h" + +#include "sieve-extprograms-common.h" + +/* + * Extension + */ + +static bool ext_filter_load(const struct sieve_extension *ext, void **context); +static void ext_filter_unload(const struct sieve_extension *ext); +static bool ext_filter_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def sieve_ext_vnd_filter = { + .name = "vnd.dovecot.filter", + .load = ext_filter_load, + .unload = ext_filter_unload, + .validator_load = ext_filter_validator_load, + SIEVE_EXT_DEFINE_OPERATION(sieve_opr_filter), +}; + +/* + * Context + */ + +static bool ext_filter_load(const struct sieve_extension *ext, void **context) +{ + if ( *context != NULL ) { + ext_filter_unload(ext); + *context = NULL; + } + + *context = (void *)sieve_extprograms_config_init(ext); + return TRUE; +} + +static void ext_filter_unload(const struct sieve_extension *ext) +{ + struct sieve_extprograms_config *ext_config = + (struct sieve_extprograms_config *)ext->context; + + if ( ext_config == NULL ) return; + + sieve_extprograms_config_deinit(&ext_config); +} + +/* + * Validation + */ + +static bool ext_filter_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register commands */ + sieve_validator_register_command(valdtr, ext, &sieve_cmd_filter); + + return TRUE; +} diff --git a/pigeonhole/src/plugins/sieve-extprograms/ext-pipe.c b/pigeonhole/src/plugins/sieve-extprograms/ext-pipe.c new file mode 100644 index 0000000..5da7d36 --- /dev/null +++ b/pigeonhole/src/plugins/sieve-extprograms/ext-pipe.c @@ -0,0 +1,114 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension vnd.dovecot.pipe + * ----------------------------- + * + * Authors: Stephan Bosch + * Specification: vendor-define; spec-bosch-sieve-extprograms + * Implementation: full + * Status: experimental + * + */ + +#include "lib.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-binary.h" + +#include "sieve-validator.h" +#include "sieve-interpreter.h" + +#include "sieve-ext-copy.h" + +#include "sieve-extprograms-common.h" + +/* + * Extension + */ + +static bool ext_pipe_load(const struct sieve_extension *ext, void **context); +static void ext_pipe_unload(const struct sieve_extension *ext); +static bool ext_pipe_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def sieve_ext_vnd_pipe = { + .name = "vnd.dovecot.pipe", + .load = ext_pipe_load, + .unload = ext_pipe_unload, + .validator_load = ext_pipe_validator_load, + SIEVE_EXT_DEFINE_OPERATION(sieve_opr_pipe), +}; + +/* + * Context + */ + +static bool ext_pipe_load(const struct sieve_extension *ext, void **context) +{ + if ( *context != NULL ) { + ext_pipe_unload(ext); + *context = NULL; + } + + *context = (void *)sieve_extprograms_config_init(ext); + return TRUE; +} + +static void ext_pipe_unload(const struct sieve_extension *ext) +{ + struct sieve_extprograms_config *ext_config = + (struct sieve_extprograms_config *)ext->context; + + if ( ext_config == NULL ) return; + + sieve_extprograms_config_deinit(&ext_config); +} + +/* + * Validation + */ + +static bool ext_pipe_validator_validate + (const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + bool required); + +static const struct sieve_validator_extension pipe_validator_extension = { + .ext = &sieve_ext_vnd_pipe, + .validate = ext_pipe_validator_validate +}; + +static bool ext_pipe_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register commands */ + sieve_validator_register_command(valdtr, ext, &sieve_cmd_pipe); + + /* Register extension to validator */ + sieve_validator_extension_register + (valdtr, ext, &pipe_validator_extension, NULL); + + return TRUE; +} + +static bool ext_pipe_validator_validate +(const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg ATTR_UNUSED, + bool required ATTR_UNUSED) +{ + struct sieve_extprograms_config *ext_config = + (struct sieve_extprograms_config *) ext->context; + + if ( ext_config != NULL && ext_config->copy_ext != NULL ) { + /* Register :copy command tag */ + sieve_ext_copy_register_tag(valdtr, + ext_config->copy_ext, sieve_cmd_pipe.identifier); + } + return TRUE; +} + + diff --git a/pigeonhole/src/plugins/sieve-extprograms/sieve-extprograms-common.c b/pigeonhole/src/plugins/sieve-extprograms/sieve-extprograms-common.c new file mode 100644 index 0000000..3c9ff23 --- /dev/null +++ b/pigeonhole/src/plugins/sieve-extprograms/sieve-extprograms-common.c @@ -0,0 +1,648 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "lib-signals.h" +#include "str.h" +#include "strfuncs.h" +#include "str-sanitize.h" +#include "unichar.h" +#include "array.h" +#include "eacces-error.h" +#include "smtp-params.h" +#include "istream.h" +#include "istream-crlf.h" +#include "istream-header-filter.h" +#include "ostream.h" +#include "mail-user.h" +#include "mail-storage.h" + +#include "program-client.h" + +#include "sieve-common.h" +#include "sieve-settings.h" +#include "sieve-error.h" +#include "sieve-extensions.h" +#include "sieve-ast.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-runtime.h" +#include "sieve-interpreter.h" + +#include "sieve-ext-copy.h" +#include "sieve-ext-variables.h" + +#include "sieve-extprograms-common.h" + +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/socket.h> + +/* + * Limits + */ + +#define SIEVE_EXTPROGRAMS_MAX_PROGRAM_NAME_LEN 128 +#define SIEVE_EXTPROGRAMS_MAX_PROGRAM_ARG_LEN 1024 + +#define SIEVE_EXTPROGRAMS_DEFAULT_EXEC_TIMEOUT_SECS 10 +#define SIEVE_EXTPROGRAMS_CONNECT_TIMEOUT_MSECS 5 + +/* + * Pipe Extension Context + */ + +struct sieve_extprograms_config *sieve_extprograms_config_init +(const struct sieve_extension *ext) +{ + struct sieve_instance *svinst = ext->svinst; + struct sieve_extprograms_config *ext_config; + const char *extname = sieve_extension_name(ext); + const char *bin_dir, *socket_dir, *input_eol; + sieve_number_t execute_timeout; + + extname = strrchr(extname, '.'); + i_assert(extname != NULL); + extname++; + + bin_dir = sieve_setting_get + (svinst, t_strdup_printf("sieve_%s_bin_dir", extname)); + socket_dir = sieve_setting_get + (svinst, t_strdup_printf("sieve_%s_socket_dir", extname)); + input_eol = sieve_setting_get + (svinst, t_strdup_printf("sieve_%s_input_eol", extname)); + + ext_config = i_new(struct sieve_extprograms_config, 1); + ext_config->execute_timeout = + SIEVE_EXTPROGRAMS_DEFAULT_EXEC_TIMEOUT_SECS; + + if ( bin_dir == NULL && socket_dir == NULL ) { + e_debug(svinst->event, "%s extension: " + "no bin or socket directory specified; extension is unconfigured " + "(both sieve_%s_bin_dir and sieve_%s_socket_dir are not set)", + sieve_extension_name(ext), extname, extname); + } else { + ext_config->bin_dir = i_strdup(bin_dir); + ext_config->socket_dir = i_strdup(socket_dir); + + if (sieve_setting_get_duration_value + (svinst, t_strdup_printf("sieve_%s_exec_timeout", extname), + &execute_timeout)) { + ext_config->execute_timeout = execute_timeout; + } + + ext_config->default_input_eol = SIEVE_EXTPROGRAMS_EOL_CRLF; + if (input_eol != NULL && strcasecmp(input_eol, "lf") == 0) + ext_config->default_input_eol = SIEVE_EXTPROGRAMS_EOL_LF; + } + + if ( sieve_extension_is(ext, sieve_ext_vnd_pipe) ) + ext_config->copy_ext = sieve_ext_copy_get_extension(ext->svinst); + if ( sieve_extension_is(ext, sieve_ext_vnd_execute) ) + ext_config->var_ext = sieve_ext_variables_get_extension(ext->svinst); + return ext_config; +} + +void sieve_extprograms_config_deinit +(struct sieve_extprograms_config **ext_config) +{ + if ( *ext_config == NULL ) + return; + + i_free((*ext_config)->bin_dir); + i_free((*ext_config)->socket_dir); + i_free((*ext_config)); + + *ext_config = NULL; +} + +/* + * Program name and arguments + */ + +bool sieve_extprogram_name_is_valid(string_t *name) +{ + ARRAY_TYPE(unichars) uni_name; + unsigned int count, i; + const unichar_t *name_chars; + size_t namelen = str_len(name); + + /* Check minimum length */ + if ( namelen == 0 ) + return FALSE; + + /* Check worst-case maximum length */ + if ( namelen > SIEVE_EXTPROGRAMS_MAX_PROGRAM_NAME_LEN * 4 ) + return FALSE; + + /* Intialize array for unicode characters */ + t_array_init(&uni_name, namelen * 4); + + /* Convert UTF-8 to UCS4/UTF-32 */ + if ( uni_utf8_to_ucs4_n(str_data(name), namelen, &uni_name) < 0 ) + return FALSE; + name_chars = array_get(&uni_name, &count); + + /* Check true maximum length */ + if ( count > SIEVE_EXTPROGRAMS_MAX_PROGRAM_NAME_LEN ) + return FALSE; + + /* Scan name for invalid characters + * FIXME: compliance with Net-Unicode Definition (Section 2 of + * RFC 5198) is not checked fully and no normalization + * is performed. + */ + for ( i = 0; i < count; i++ ) { + + /* 0000-001F; [CONTROL CHARACTERS] */ + if ( name_chars[i] <= 0x001f ) + return FALSE; + + /* 002F; SLASH */ + if ( name_chars[i] == 0x002f ) + return FALSE; + + /* 007F; DELETE */ + if ( name_chars[i] == 0x007f ) + return FALSE; + + /* 0080-009F; [CONTROL CHARACTERS] */ + if ( name_chars[i] >= 0x0080 && name_chars[i] <= 0x009f ) + return FALSE; + + /* 00FF */ + if ( name_chars[i] == 0x00ff ) + return FALSE; + + /* 2028; LINE SEPARATOR */ + /* 2029; PARAGRAPH SEPARATOR */ + if ( name_chars[i] == 0x2028 || name_chars[i] == 0x2029 ) + return FALSE; + } + + return TRUE; +} + +bool sieve_extprogram_arg_is_valid(string_t *arg) +{ + const unsigned char *chars; + unsigned int i; + + /* Check maximum length */ + if ( str_len(arg) > SIEVE_EXTPROGRAMS_MAX_PROGRAM_ARG_LEN ) + return FALSE; + + /* Check invalid characters */ + chars = str_data(arg); + for ( i = 0; i < str_len(arg); i++ ) { + /* 0010; CR */ + if ( chars[i] == 0x0D ) + return FALSE; + + /* 0010; LF */ + if ( chars[i] == 0x0A ) + return FALSE; + } + + return TRUE; +} + +/* + * Command validation + */ + +struct _arg_validate_context { + struct sieve_validator *valdtr; + struct sieve_command *cmd; +}; + +static int _arg_validate +(void *context, struct sieve_ast_argument *item) +{ + struct _arg_validate_context *actx = (struct _arg_validate_context *) context; + + if ( sieve_argument_is_string_literal(item) ) { + string_t *arg = sieve_ast_argument_str(item); + + if ( !sieve_extprogram_arg_is_valid(arg) ) { + sieve_argument_validate_error(actx->valdtr, item, + "%s %s: specified external program argument `%s' is invalid", + sieve_command_identifier(actx->cmd), sieve_command_type_name(actx->cmd), + str_sanitize(str_c(arg), 128)); + + return -1; + } + } + + return 1; +} + +bool sieve_extprogram_command_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + struct sieve_ast_argument *stritem; + struct _arg_validate_context actx; + string_t *program_name; + + if ( arg == NULL ) { + sieve_command_validate_error(valdtr, cmd, + "the %s %s expects at least one positional argument, but none was found", + sieve_command_identifier(cmd), sieve_command_type_name(cmd)); + return FALSE; + } + + /* <program-name: string> argument */ + + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "program-name", 1, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) ) + return FALSE; + + /* Variables are not allowed */ + if ( !sieve_argument_is_string_literal(arg) ) { + sieve_argument_validate_error(valdtr, arg, + "the %s %s requires a constant string " + "for its program-name argument", + sieve_command_identifier(cmd), sieve_command_type_name(cmd)); + return FALSE; + } + + /* Check program name */ + program_name = sieve_ast_argument_str(arg); + if ( !sieve_extprogram_name_is_valid(program_name) ) { + sieve_argument_validate_error(valdtr, arg, + "%s %s: invalid program name '%s'", + sieve_command_identifier(cmd), sieve_command_type_name(cmd), + str_sanitize(str_c(program_name), 80)); + return FALSE; + } + + /* Optional <arguments: string-list> argument */ + + arg = sieve_ast_argument_next(arg); + if ( arg == NULL ) + return TRUE; + + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "arguments", 2, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) ) + return FALSE; + + /* Check arguments */ + actx.valdtr = valdtr; + actx.cmd = cmd; + stritem = arg; + if ( sieve_ast_stringlist_map + (&stritem, (void *)&actx, _arg_validate) <= 0 ) { + return FALSE; + } + + if ( sieve_ast_argument_next(arg) != NULL ) { + sieve_command_validate_error(valdtr, cmd, + "the %s %s expects at most two positional arguments, but more were found", + sieve_command_identifier(cmd), sieve_command_type_name(cmd)); + return FALSE; + } + + return TRUE; +} + +/* + * Common command operands + */ + +int sieve_extprogram_command_read_operands +(const struct sieve_runtime_env *renv, sieve_size_t *address, + string_t **pname_r, struct sieve_stringlist **args_list_r) +{ + string_t *arg; + int ret; + + /* + * Read fixed operands + */ + + if ( (ret=sieve_opr_string_read + (renv, address, "program-name", pname_r)) <= 0 ) + return ret; + + if ( (ret=sieve_opr_stringlist_read_ex + (renv, address, "arguments", TRUE, args_list_r)) <= 0 ) + return ret; + + /* + * Check operands + */ + + arg = NULL; + while ( *args_list_r != NULL && + (ret=sieve_stringlist_next_item(*args_list_r, &arg)) > 0 ) { + if ( !sieve_extprogram_arg_is_valid(arg) ) { + sieve_runtime_error(renv, NULL, + "specified :args item `%s' is invalid", + str_sanitize(str_c(arg), 128)); + return SIEVE_EXEC_FAILURE; + } + } + + if ( ret < 0 ) { + sieve_runtime_trace_error(renv, "invalid args-list item"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + return SIEVE_EXEC_OK; +} + +/* + * Running external programs + */ + +struct sieve_extprogram { + struct sieve_instance *svinst; + const struct sieve_extprograms_config *ext_config; + + const struct sieve_script_env *scriptenv; + struct program_client_settings set; + struct program_client *program_client; +}; + +void sieve_extprogram_exec_error +(struct sieve_error_handler *ehandler, const char *location, + const char *fmt, ...) +{ + char str[256]; + struct tm *tm; + const char *timestamp; + + tm = localtime(&ioloop_time); + + timestamp = + ( strftime(str, sizeof(str), " [%Y-%m-%d %H:%M:%S]", tm) > 0 ? str : "" ); + + va_list args; + va_start(args, fmt); + + T_BEGIN { + sieve_error(ehandler, location, + "%s: refer to server log for more information.%s", + t_strdup_vprintf(fmt, args), timestamp); + } T_END; + + va_end(args); +} + +/* API */ + +struct sieve_extprogram *sieve_extprogram_create +(const struct sieve_extension *ext, const struct sieve_script_env *senv, + const struct sieve_message_data *msgdata, const char *action, + const char *program_name, const char * const *args, + enum sieve_error *error_r) +{ + struct sieve_instance *svinst = ext->svinst; + struct sieve_extprograms_config *ext_config = + (struct sieve_extprograms_config *) ext->context; + const struct smtp_address *sender, *recipient, *orig_recipient; + struct sieve_extprogram *sprog; + const char *path = NULL; + struct stat st; + bool fork = FALSE; + + e_debug(svinst->event, "action %s: " + "running program: %s", action, program_name); + + if ( ext_config == NULL || + (ext_config->bin_dir == NULL && ext_config->socket_dir == NULL) ) { + e_error(svinst->event, "action %s: " + "failed to execute program `%s': " + "vnd.dovecot.%s extension is unconfigured", + action, program_name, action); + *error_r = SIEVE_ERROR_NOT_FOUND; + return NULL; + } + + /* Try socket first */ + if ( ext_config->socket_dir != NULL ) { + path = t_strconcat(senv->user->set->base_dir, "/", + ext_config->socket_dir, "/", program_name, NULL); + if ( stat(path, &st) < 0 ) { + switch ( errno ) { + case ENOENT: + e_debug(svinst->event, "action %s: " + "socket path `%s' for program `%s' not found", + action, path, program_name); + break; + case EACCES: + e_error(svinst->event, "action %s: " + "failed to stat socket: %s", + action, eacces_error_get("stat", path)); + *error_r = SIEVE_ERROR_NO_PERMISSION; + return NULL; + default: + e_error(svinst->event, "action %s: " + "failed to stat socket `%s': %m", + action, path); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return NULL; + } + path = NULL; + } else if ( !S_ISSOCK(st.st_mode) ) { + e_error(svinst->event, "action %s: " + "socket path `%s' for program `%s' is not a socket", + action, path, program_name); + *error_r = SIEVE_ERROR_NOT_POSSIBLE; + return NULL; + } + } + + /* Try executable next */ + if ( path == NULL && ext_config->bin_dir != NULL ) { + fork = TRUE; + path = t_strconcat(ext_config->bin_dir, "/", program_name, NULL); + if ( stat(path, &st) < 0 ) { + switch ( errno ) { + case ENOENT: + e_debug(svinst->event, "action %s: " + "executable path `%s' for program `%s' not found", + action, path, program_name); + *error_r = SIEVE_ERROR_NOT_FOUND; + break; + case EACCES: + e_error(svinst->event, "action %s: " + "failed to stat program: %s", + action, eacces_error_get("stat", path)); + *error_r = SIEVE_ERROR_NO_PERMISSION; + break; + default: + e_error(svinst->event, "action %s: " + "failed to stat program `%s': %m", + action, path); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + break; + } + + return NULL; + } else if ( !S_ISREG(st.st_mode) ) { + e_error(svinst->event, "action %s: " + "executable `%s' for program `%s' is not a regular file", + action, path, program_name); + *error_r = SIEVE_ERROR_NOT_POSSIBLE; + return NULL; + } else if ( (st.st_mode & S_IWOTH) != 0 ) { + e_error(svinst->event, "action %s: " + "executable `%s' for program `%s' is world-writable", + action, path, program_name); + *error_r = SIEVE_ERROR_NO_PERMISSION; + return NULL; + } + } + + /* None found ? */ + if ( path == NULL ) { + e_error(svinst->event, "action %s: " + "program `%s' not found", action, program_name); + *error_r = SIEVE_ERROR_NOT_FOUND; + return NULL; + } + + sprog = i_new(struct sieve_extprogram, 1); + sprog->svinst = ext->svinst; + sprog->ext_config = ext_config; + sprog->scriptenv = senv; + + sprog->set.client_connect_timeout_msecs = + SIEVE_EXTPROGRAMS_CONNECT_TIMEOUT_MSECS; + sprog->set.input_idle_timeout_msecs = + ext_config->execute_timeout * 1000; + restrict_access_init(&sprog->set.restrict_set); + if (senv->user->uid != 0) + sprog->set.restrict_set.uid = senv->user->uid; + if (senv->user->gid != 0) + sprog->set.restrict_set.gid = senv->user->gid; + sprog->set.debug = svinst->debug; + + if ( fork ) { + sprog->program_client = + program_client_local_create(path, args, &sprog->set); + } else { + sprog->program_client = + program_client_unix_create(path, args, &sprog->set, FALSE); + } + + if ( svinst->username != NULL ) + program_client_set_env(sprog->program_client, "USER", svinst->username); + if ( svinst->home_dir != NULL ) + program_client_set_env(sprog->program_client, "HOME", svinst->home_dir); + if ( svinst->hostname != NULL ) + program_client_set_env(sprog->program_client, "HOST", svinst->hostname); + + sender = msgdata->envelope.mail_from; + recipient = msgdata->envelope.rcpt_to; + orig_recipient = NULL; + if ( msgdata->envelope.rcpt_params != NULL ) + orig_recipient = msgdata->envelope.rcpt_params->orcpt.addr; + + if ( !smtp_address_isnull(sender) ) { + program_client_set_env(sprog->program_client, "SENDER", + smtp_address_encode(sender)); + } + if ( !smtp_address_isnull(recipient) ) { + program_client_set_env(sprog->program_client, "RECIPIENT", + smtp_address_encode(recipient)); + } + if ( !smtp_address_isnull(orig_recipient) ) { + program_client_set_env(sprog->program_client, "ORIG_RECIPIENT", + smtp_address_encode(orig_recipient)); + } + + return sprog; +} + +void sieve_extprogram_destroy(struct sieve_extprogram **_sprog) +{ + struct sieve_extprogram *sprog = *_sprog; + + program_client_destroy(&sprog->program_client); + i_free(sprog); + *_sprog = NULL; +} + +/* I/0 */ + +void sieve_extprogram_set_output +(struct sieve_extprogram *sprog, struct ostream *output) +{ + program_client_set_output(sprog->program_client, output); +} + +void sieve_extprogram_set_input +(struct sieve_extprogram *sprog, struct istream *input) +{ + switch (sprog->ext_config->default_input_eol) { + case SIEVE_EXTPROGRAMS_EOL_LF: + input = i_stream_create_lf(input); + break; + case SIEVE_EXTPROGRAMS_EOL_CRLF: + input = i_stream_create_crlf(input); + break; + default: + i_unreached(); + } + + program_client_set_input(sprog->program_client, input); + + i_stream_unref(&input); +} + +void sieve_extprogram_set_output_seekable +(struct sieve_extprogram *sprog) +{ + string_t *prefix; + prefix = t_str_new(128); + mail_user_set_get_temp_prefix(prefix, sprog->scriptenv->user->set); + + program_client_set_output_seekable(sprog->program_client, str_c(prefix)); +} + +struct istream *sieve_extprogram_get_output_seekable +(struct sieve_extprogram *sprog) +{ + return program_client_get_output_seekable(sprog->program_client); +} + +int sieve_extprogram_set_input_mail +(struct sieve_extprogram *sprog, struct mail *mail) +{ + struct istream *input; + + if (mail_get_stream(mail, NULL, NULL, &input) < 0) + return -1; + + sieve_extprogram_set_input(sprog, input); + return 1; +} + +int sieve_extprogram_run(struct sieve_extprogram *sprog) +{ + switch (program_client_run(sprog->program_client)) { + case PROGRAM_CLIENT_EXIT_STATUS_INTERNAL_FAILURE: + return -1; + case PROGRAM_CLIENT_EXIT_STATUS_FAILURE: + return 0; + case PROGRAM_CLIENT_EXIT_STATUS_SUCCESS: + return 1; + } + i_unreached(); +} + diff --git a/pigeonhole/src/plugins/sieve-extprograms/sieve-extprograms-common.h b/pigeonhole/src/plugins/sieve-extprograms/sieve-extprograms-common.h new file mode 100644 index 0000000..063c02b --- /dev/null +++ b/pigeonhole/src/plugins/sieve-extprograms/sieve-extprograms-common.h @@ -0,0 +1,107 @@ +#ifndef SIEVE_EXTPROGRAMS_COMMON_H +#define SIEVE_EXTPROGRAMS_COMMON_H + +#include "sieve-common.h" + +/* + * Extension configuration + */ + +enum sieve_extprograms_eol { + SIEVE_EXTPROGRAMS_EOL_CRLF = 0, + SIEVE_EXTPROGRAMS_EOL_LF +}; + +struct sieve_extprograms_config { + const struct sieve_extension *copy_ext; + const struct sieve_extension *var_ext; + + char *socket_dir; + char *bin_dir; + + enum sieve_extprograms_eol default_input_eol; + + unsigned int execute_timeout; +}; + +struct sieve_extprograms_config *sieve_extprograms_config_init + (const struct sieve_extension *ext); +void sieve_extprograms_config_deinit + (struct sieve_extprograms_config **ext_config); + +/* + * Extensions + */ + +extern const struct sieve_extension_def sieve_ext_vnd_pipe; +extern const struct sieve_extension_def sieve_ext_vnd_filter; +extern const struct sieve_extension_def sieve_ext_vnd_execute; + +/* + * Commands + */ + +extern const struct sieve_command_def sieve_cmd_pipe; +extern const struct sieve_command_def sieve_cmd_filter; +extern const struct sieve_command_def sieve_cmd_execute; + +/* + * Operations + */ + +extern const struct sieve_operation_def sieve_opr_pipe; +extern const struct sieve_operation_def sieve_opr_filter; +extern const struct sieve_operation_def sieve_opr_execute; + +/* + * Program name and arguments + */ + +bool sieve_extprogram_arg_is_valid(string_t *arg); +bool sieve_extprogram_name_is_valid(string_t *name); + +/* + * Command validation + */ + +bool sieve_extprogram_command_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); + +/* + * Common command operands + */ + +int sieve_extprogram_command_read_operands + (const struct sieve_runtime_env *renv, sieve_size_t *address, + string_t **pname_r, struct sieve_stringlist **args_list_r); + +/* + * Running external programs + */ + +void sieve_extprogram_exec_error + (struct sieve_error_handler *ehandler, const char *location, + const char *fmt, ...) ATTR_FORMAT(3, 4); + +struct sieve_extprogram *sieve_extprogram_create + (const struct sieve_extension *ext, const struct sieve_script_env *senv, + const struct sieve_message_data *msgdata, const char *action, + const char *program_name, const char * const *args, + enum sieve_error *error_r); +void sieve_extprogram_destroy(struct sieve_extprogram **_sprog); + +void sieve_extprogram_set_output + (struct sieve_extprogram *sprog, struct ostream *output); +void sieve_extprogram_set_output_seekable + (struct sieve_extprogram *sprog); +struct istream *sieve_extprogram_get_output_seekable + (struct sieve_extprogram *sprog); + +void sieve_extprogram_set_input + (struct sieve_extprogram *sprog, struct istream *input); +int sieve_extprogram_set_input_mail + (struct sieve_extprogram *sprog, struct mail *mail); + +int sieve_extprogram_run(struct sieve_extprogram *sprog); + +#endif diff --git a/pigeonhole/src/plugins/sieve-extprograms/sieve-extprograms-plugin.c b/pigeonhole/src/plugins/sieve-extprograms/sieve-extprograms-plugin.c new file mode 100644 index 0000000..bf17a80 --- /dev/null +++ b/pigeonhole/src/plugins/sieve-extprograms/sieve-extprograms-plugin.c @@ -0,0 +1,68 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-extensions.h" + +#include "sieve-extprograms-common.h" +#include "sieve-extprograms-plugin.h" + +/* + * Sieve plugin interface + */ + +struct _plugin_context { + const struct sieve_extension *ext_pipe; + const struct sieve_extension *ext_filter; + const struct sieve_extension *ext_execute; +}; + +const char *sieve_extprograms_plugin_version = PIGEONHOLE_ABI_VERSION; + +void sieve_extprograms_plugin_load +(struct sieve_instance *svinst, void **context) +{ + struct _plugin_context *pctx = i_new(struct _plugin_context, 1); + + pctx->ext_pipe = sieve_extension_register + (svinst, &sieve_ext_vnd_pipe, FALSE); + pctx->ext_filter = sieve_extension_register + (svinst, &sieve_ext_vnd_filter, FALSE); + pctx->ext_execute = sieve_extension_register + (svinst, &sieve_ext_vnd_execute, FALSE); + + if ( svinst->debug ) { + e_debug(svinst->event, + "Sieve Extprograms plugin for %s version %s loaded", + PIGEONHOLE_NAME, PIGEONHOLE_VERSION_FULL); + } + + *context = (void *)pctx; +} + +void sieve_extprograms_plugin_unload +(struct sieve_instance *svinst ATTR_UNUSED, void *context) +{ + struct _plugin_context *pctx = (struct _plugin_context *)context; + + sieve_extension_unregister(pctx->ext_pipe); + sieve_extension_unregister(pctx->ext_filter); + sieve_extension_unregister(pctx->ext_execute); + + i_free(pctx); +} + +/* + * Module interface + */ + +void sieve_extprograms_plugin_init(void) +{ + /* Nothing */ +} + +void sieve_extprograms_plugin_deinit(void) +{ + /* Nothing */ +} diff --git a/pigeonhole/src/plugins/sieve-extprograms/sieve-extprograms-plugin.h b/pigeonhole/src/plugins/sieve-extprograms/sieve-extprograms-plugin.h new file mode 100644 index 0000000..20fa55a --- /dev/null +++ b/pigeonhole/src/plugins/sieve-extprograms/sieve-extprograms-plugin.h @@ -0,0 +1,20 @@ +#ifndef SIEVE_EXTPROGRAMS_PLUGIN_H +#define SIEVE_EXTPROGRAMS_PLUGIN_H + +/* + * Plugin interface + */ + +void sieve_extprograms_plugin_load + (struct sieve_instance *svinst, void **context); +void sieve_extprograms_plugin_unload + (struct sieve_instance *svinst, void *context); + +/* + * Module interface + */ + +void sieve_extprograms_plugin_init(void); +void sieve_extprograms_plugin_deinit(void); + +#endif diff --git a/pigeonhole/src/sieve-tools/Makefile.am b/pigeonhole/src/sieve-tools/Makefile.am new file mode 100644 index 0000000..f2ceffd --- /dev/null +++ b/pigeonhole/src/sieve-tools/Makefile.am @@ -0,0 +1,59 @@ +bin_PROGRAMS = sievec sieve-dump sieve-test sieve-filter + +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + -I$(top_srcdir)/src/lib-sieve-tool \ + -I$(srcdir)/debug \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_SERVICE_INCLUDE) + +libs = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la \ + $(top_builddir)/src/lib-sieve-tool/libsieve-tool.la + +libs_ldadd = $(libs) $(LIBDOVECOT_STORAGE) $(LIBDOVECOT_LDA) $(LIBDOVECOT) +libs_deps = $(libs) $(LIBDOVECOT_STORAGE_DEPS) $(LIBDOVECOT_LDA_DEPS) $(LIBDOVECOT_DEPS) + +# Sieve Compile Tool + +sievec_CPPFLAGS = $(AM_CPPFLAGS) $(BINARY_CFLAGS) +sievec_LDFLAGS = -export-dynamic $(BINARY_LDFLAGS) +sievec_LDADD = $(libs_ldadd) +sievec_DEPENDENCIES = $(libs_deps) + +sievec_SOURCES = \ + sievec.c + +# Sieve Dump Tool + +sieve_dump_CPPFLAGS = $(AM_CPPFLAGS) $(BINARY_CFLAGS) +sieve_dump_LDFLAGS = -export-dynamic $(BINARY_LDFLAGS) +sieve_dump_LDADD = $(libs_ldadd) +sieve_dump_DEPENDENCIES = $(libs_deps) + +sieve_dump_SOURCES = \ + sieve-dump.c + +# Sieve Test Tool + +sieve_test_CPPFLAGS = $(AM_CPPFLAGS) $(BINARY_CFLAGS) +sieve_test_LDFLAGS = -export-dynamic $(BINARY_LDFLAGS) +sieve_test_LDADD = $(libs_ldadd) +sieve_test_DEPENDENCIES = $(libs_deps) + +sieve_test_SOURCES = \ + sieve-test.c + +## Unfinished tools + +# Sieve Filter Tool + +sieve_filter_CPPFLAGS = $(AM_CPPFLAGS) $(BINARY_CFLAGS) +sieve_filter_LDFLAGS = -export-dynamic $(BINARY_LDFLAGS) +sieve_filter_LDADD = $(libs_ldadd) +sieve_filter_DEPENDENCIES = $(libs_deps) + +sieve_filter_SOURCES = \ + sieve-filter.c + +noinst_HEADERS = diff --git a/pigeonhole/src/sieve-tools/Makefile.in b/pigeonhole/src/sieve-tools/Makefile.in new file mode 100644 index 0000000..6b5b0d0 --- /dev/null +++ b/pigeonhole/src/sieve-tools/Makefile.in @@ -0,0 +1,863 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +bin_PROGRAMS = sievec$(EXEEXT) sieve-dump$(EXEEXT) sieve-test$(EXEEXT) \ + sieve-filter$(EXEEXT) +subdir = src/sieve-tools +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am_sieve_dump_OBJECTS = sieve_dump-sieve-dump.$(OBJEXT) +sieve_dump_OBJECTS = $(am_sieve_dump_OBJECTS) +am__DEPENDENCIES_1 = +am__DEPENDENCIES_2 = $(libs) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +sieve_dump_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(sieve_dump_LDFLAGS) $(LDFLAGS) -o $@ +am_sieve_filter_OBJECTS = sieve_filter-sieve-filter.$(OBJEXT) +sieve_filter_OBJECTS = $(am_sieve_filter_OBJECTS) +sieve_filter_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(sieve_filter_LDFLAGS) $(LDFLAGS) -o $@ +am_sieve_test_OBJECTS = sieve_test-sieve-test.$(OBJEXT) +sieve_test_OBJECTS = $(am_sieve_test_OBJECTS) +sieve_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(sieve_test_LDFLAGS) $(LDFLAGS) -o $@ +am_sievec_OBJECTS = sievec-sievec.$(OBJEXT) +sievec_OBJECTS = $(am_sievec_OBJECTS) +sievec_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(sievec_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/sieve_dump-sieve-dump.Po \ + ./$(DEPDIR)/sieve_filter-sieve-filter.Po \ + ./$(DEPDIR)/sieve_test-sieve-test.Po \ + ./$(DEPDIR)/sievec-sievec.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(sieve_dump_SOURCES) $(sieve_filter_SOURCES) \ + $(sieve_test_SOURCES) $(sievec_SOURCES) +DIST_SOURCES = $(sieve_dump_SOURCES) $(sieve_filter_SOURCES) \ + $(sieve_test_SOURCES) $(sievec_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + -I$(top_srcdir)/src/lib-sieve-tool \ + -I$(srcdir)/debug \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_SERVICE_INCLUDE) + +libs = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la \ + $(top_builddir)/src/lib-sieve-tool/libsieve-tool.la + +libs_ldadd = $(libs) $(LIBDOVECOT_STORAGE) $(LIBDOVECOT_LDA) $(LIBDOVECOT) +libs_deps = $(libs) $(LIBDOVECOT_STORAGE_DEPS) $(LIBDOVECOT_LDA_DEPS) $(LIBDOVECOT_DEPS) + +# Sieve Compile Tool +sievec_CPPFLAGS = $(AM_CPPFLAGS) $(BINARY_CFLAGS) +sievec_LDFLAGS = -export-dynamic $(BINARY_LDFLAGS) +sievec_LDADD = $(libs_ldadd) +sievec_DEPENDENCIES = $(libs_deps) +sievec_SOURCES = \ + sievec.c + + +# Sieve Dump Tool +sieve_dump_CPPFLAGS = $(AM_CPPFLAGS) $(BINARY_CFLAGS) +sieve_dump_LDFLAGS = -export-dynamic $(BINARY_LDFLAGS) +sieve_dump_LDADD = $(libs_ldadd) +sieve_dump_DEPENDENCIES = $(libs_deps) +sieve_dump_SOURCES = \ + sieve-dump.c + + +# Sieve Test Tool +sieve_test_CPPFLAGS = $(AM_CPPFLAGS) $(BINARY_CFLAGS) +sieve_test_LDFLAGS = -export-dynamic $(BINARY_LDFLAGS) +sieve_test_LDADD = $(libs_ldadd) +sieve_test_DEPENDENCIES = $(libs_deps) +sieve_test_SOURCES = \ + sieve-test.c + + +# Sieve Filter Tool +sieve_filter_CPPFLAGS = $(AM_CPPFLAGS) $(BINARY_CFLAGS) +sieve_filter_LDFLAGS = -export-dynamic $(BINARY_LDFLAGS) +sieve_filter_LDADD = $(libs_ldadd) +sieve_filter_DEPENDENCIES = $(libs_deps) +sieve_filter_SOURCES = \ + sieve-filter.c + +noinst_HEADERS = +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/sieve-tools/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/sieve-tools/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +sieve-dump$(EXEEXT): $(sieve_dump_OBJECTS) $(sieve_dump_DEPENDENCIES) $(EXTRA_sieve_dump_DEPENDENCIES) + @rm -f sieve-dump$(EXEEXT) + $(AM_V_CCLD)$(sieve_dump_LINK) $(sieve_dump_OBJECTS) $(sieve_dump_LDADD) $(LIBS) + +sieve-filter$(EXEEXT): $(sieve_filter_OBJECTS) $(sieve_filter_DEPENDENCIES) $(EXTRA_sieve_filter_DEPENDENCIES) + @rm -f sieve-filter$(EXEEXT) + $(AM_V_CCLD)$(sieve_filter_LINK) $(sieve_filter_OBJECTS) $(sieve_filter_LDADD) $(LIBS) + +sieve-test$(EXEEXT): $(sieve_test_OBJECTS) $(sieve_test_DEPENDENCIES) $(EXTRA_sieve_test_DEPENDENCIES) + @rm -f sieve-test$(EXEEXT) + $(AM_V_CCLD)$(sieve_test_LINK) $(sieve_test_OBJECTS) $(sieve_test_LDADD) $(LIBS) + +sievec$(EXEEXT): $(sievec_OBJECTS) $(sievec_DEPENDENCIES) $(EXTRA_sievec_DEPENDENCIES) + @rm -f sievec$(EXEEXT) + $(AM_V_CCLD)$(sievec_LINK) $(sievec_OBJECTS) $(sievec_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve_dump-sieve-dump.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve_filter-sieve-filter.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve_test-sieve-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sievec-sievec.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +sieve_dump-sieve-dump.o: sieve-dump.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sieve_dump_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sieve_dump-sieve-dump.o -MD -MP -MF $(DEPDIR)/sieve_dump-sieve-dump.Tpo -c -o sieve_dump-sieve-dump.o `test -f 'sieve-dump.c' || echo '$(srcdir)/'`sieve-dump.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sieve_dump-sieve-dump.Tpo $(DEPDIR)/sieve_dump-sieve-dump.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sieve-dump.c' object='sieve_dump-sieve-dump.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sieve_dump_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sieve_dump-sieve-dump.o `test -f 'sieve-dump.c' || echo '$(srcdir)/'`sieve-dump.c + +sieve_dump-sieve-dump.obj: sieve-dump.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sieve_dump_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sieve_dump-sieve-dump.obj -MD -MP -MF $(DEPDIR)/sieve_dump-sieve-dump.Tpo -c -o sieve_dump-sieve-dump.obj `if test -f 'sieve-dump.c'; then $(CYGPATH_W) 'sieve-dump.c'; else $(CYGPATH_W) '$(srcdir)/sieve-dump.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sieve_dump-sieve-dump.Tpo $(DEPDIR)/sieve_dump-sieve-dump.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sieve-dump.c' object='sieve_dump-sieve-dump.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sieve_dump_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sieve_dump-sieve-dump.obj `if test -f 'sieve-dump.c'; then $(CYGPATH_W) 'sieve-dump.c'; else $(CYGPATH_W) '$(srcdir)/sieve-dump.c'; fi` + +sieve_filter-sieve-filter.o: sieve-filter.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sieve_filter_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sieve_filter-sieve-filter.o -MD -MP -MF $(DEPDIR)/sieve_filter-sieve-filter.Tpo -c -o sieve_filter-sieve-filter.o `test -f 'sieve-filter.c' || echo '$(srcdir)/'`sieve-filter.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sieve_filter-sieve-filter.Tpo $(DEPDIR)/sieve_filter-sieve-filter.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sieve-filter.c' object='sieve_filter-sieve-filter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sieve_filter_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sieve_filter-sieve-filter.o `test -f 'sieve-filter.c' || echo '$(srcdir)/'`sieve-filter.c + +sieve_filter-sieve-filter.obj: sieve-filter.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sieve_filter_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sieve_filter-sieve-filter.obj -MD -MP -MF $(DEPDIR)/sieve_filter-sieve-filter.Tpo -c -o sieve_filter-sieve-filter.obj `if test -f 'sieve-filter.c'; then $(CYGPATH_W) 'sieve-filter.c'; else $(CYGPATH_W) '$(srcdir)/sieve-filter.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sieve_filter-sieve-filter.Tpo $(DEPDIR)/sieve_filter-sieve-filter.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sieve-filter.c' object='sieve_filter-sieve-filter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sieve_filter_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sieve_filter-sieve-filter.obj `if test -f 'sieve-filter.c'; then $(CYGPATH_W) 'sieve-filter.c'; else $(CYGPATH_W) '$(srcdir)/sieve-filter.c'; fi` + +sieve_test-sieve-test.o: sieve-test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sieve_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sieve_test-sieve-test.o -MD -MP -MF $(DEPDIR)/sieve_test-sieve-test.Tpo -c -o sieve_test-sieve-test.o `test -f 'sieve-test.c' || echo '$(srcdir)/'`sieve-test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sieve_test-sieve-test.Tpo $(DEPDIR)/sieve_test-sieve-test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sieve-test.c' object='sieve_test-sieve-test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sieve_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sieve_test-sieve-test.o `test -f 'sieve-test.c' || echo '$(srcdir)/'`sieve-test.c + +sieve_test-sieve-test.obj: sieve-test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sieve_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sieve_test-sieve-test.obj -MD -MP -MF $(DEPDIR)/sieve_test-sieve-test.Tpo -c -o sieve_test-sieve-test.obj `if test -f 'sieve-test.c'; then $(CYGPATH_W) 'sieve-test.c'; else $(CYGPATH_W) '$(srcdir)/sieve-test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sieve_test-sieve-test.Tpo $(DEPDIR)/sieve_test-sieve-test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sieve-test.c' object='sieve_test-sieve-test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sieve_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sieve_test-sieve-test.obj `if test -f 'sieve-test.c'; then $(CYGPATH_W) 'sieve-test.c'; else $(CYGPATH_W) '$(srcdir)/sieve-test.c'; fi` + +sievec-sievec.o: sievec.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sievec_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sievec-sievec.o -MD -MP -MF $(DEPDIR)/sievec-sievec.Tpo -c -o sievec-sievec.o `test -f 'sievec.c' || echo '$(srcdir)/'`sievec.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sievec-sievec.Tpo $(DEPDIR)/sievec-sievec.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sievec.c' object='sievec-sievec.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sievec_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sievec-sievec.o `test -f 'sievec.c' || echo '$(srcdir)/'`sievec.c + +sievec-sievec.obj: sievec.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sievec_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sievec-sievec.obj -MD -MP -MF $(DEPDIR)/sievec-sievec.Tpo -c -o sievec-sievec.obj `if test -f 'sievec.c'; then $(CYGPATH_W) 'sievec.c'; else $(CYGPATH_W) '$(srcdir)/sievec.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sievec-sievec.Tpo $(DEPDIR)/sievec-sievec.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sievec.c' object='sievec-sievec.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sievec_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sievec-sievec.obj `if test -f 'sievec.c'; then $(CYGPATH_W) 'sievec.c'; else $(CYGPATH_W) '$(srcdir)/sievec.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/sieve_dump-sieve-dump.Po + -rm -f ./$(DEPDIR)/sieve_filter-sieve-filter.Po + -rm -f ./$(DEPDIR)/sieve_test-sieve-test.Po + -rm -f ./$(DEPDIR)/sievec-sievec.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/sieve_dump-sieve-dump.Po + -rm -f ./$(DEPDIR)/sieve_filter-sieve-filter.Po + -rm -f ./$(DEPDIR)/sieve_test-sieve-test.Po + -rm -f ./$(DEPDIR)/sievec-sievec.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-binPROGRAMS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/sieve-tools/sieve-dump.c b/pigeonhole/src/sieve-tools/sieve-dump.c new file mode 100644 index 0000000..23b2be4 --- /dev/null +++ b/pigeonhole/src/sieve-tools/sieve-dump.c @@ -0,0 +1,97 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "master-service.h" +#include "master-service-settings.h" +#include "mail-storage-service.h" +#include "mail-user.h" + +#include "sieve.h" +#include "sieve-extensions.h" +#include "sieve-tool.h" + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <sysexits.h> + +/* + * Print help + */ + +static void print_help(void) +{ + printf( +"Usage: sieve-dump [-c <config-file>] [-D] [-h] [-P <plugin>] [-x <extensions>]\n" +" <sieve-binary> [<out-file>]\n" + ); +} + +/* + * Tool implementation + */ + +int main(int argc, char **argv) +{ + struct sieve_instance *svinst; + struct sieve_binary *sbin; + const char *binfile, *outfile; + bool hexdump = FALSE; + int exit_status = EXIT_SUCCESS; + int c; + + sieve_tool = sieve_tool_init("sieve-dump", &argc, &argv, "DhP:x:", FALSE); + + outfile = NULL; + + while ((c = sieve_tool_getopt(sieve_tool)) > 0) { + switch (c) { + case 'h': + /* produce hexdump */ + hexdump = TRUE; + break; + default: + print_help(); + i_fatal_status(EX_USAGE, "Unknown argument: %c", c); + break; + } + } + + if ( optind < argc ) { + binfile = argv[optind++]; + } else { + print_help(); + i_fatal_status(EX_USAGE, "Missing <script-file> argument"); + } + + if ( optind < argc ) { + outfile = argv[optind++]; + } + + /* Finish tool initialization */ + svinst = sieve_tool_init_finish(sieve_tool, FALSE, TRUE); + + /* Enable debug extension */ + sieve_enable_debug_extension(svinst); + + /* Dump binary */ + sbin = sieve_load(svinst, binfile, NULL); + if ( sbin != NULL ) { + sieve_tool_dump_binary_to(sbin, outfile == NULL ? "-" : outfile, hexdump); + + sieve_close(&sbin); + } else { + i_error("failed to load binary: %s", binfile); + exit_status = EXIT_FAILURE; + } + + sieve_tool_deinit(&sieve_tool); + + return exit_status; +} + diff --git a/pigeonhole/src/sieve-tools/sieve-filter.c b/pigeonhole/src/sieve-tools/sieve-filter.c new file mode 100644 index 0000000..2b98fe6 --- /dev/null +++ b/pigeonhole/src/sieve-tools/sieve-filter.c @@ -0,0 +1,614 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "lib-signals.h" +#include "ioloop.h" +#include "env-util.h" +#include "str.h" +#include "str-sanitize.h" +#include "ostream.h" +#include "array.h" +#include "mail-namespace.h" +#include "mail-storage.h" +#include "mail-search-build.h" + +#include "sieve.h" +#include "sieve-extensions.h" +#include "sieve-binary.h" + +#include "sieve-tool.h" + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <pwd.h> +#include <sysexits.h> + +/* + * Print help + */ + +static void print_help(void) +{ + printf( +"Usage: sieve-filter [-c <config-file>] [-C] [-D] [-e] [-m <default-mailbox>]\n" +" [-P <plugin>] [-q <output-mailbox>] [-Q <mail-command>]\n" +" [-s <script-file>] [-u <user>] [-v] [-W] [-x <extensions>]\n" +" <script-file> <source-mailbox> [<discard-action>]\n" + ); +} + +enum sieve_filter_discard_action { + SIEVE_FILTER_DACT_KEEP, /* Keep discarded messages in source folder */ + SIEVE_FILTER_DACT_MOVE, /* Move discarded messages to Trash folder */ + SIEVE_FILTER_DACT_DELETE, /* Flag discarded messages as \DELETED */ + SIEVE_FILTER_DACT_EXPUNGE /* Expunge discarded messages */ +}; + +struct sieve_filter_data { + enum sieve_filter_discard_action discard_action; + struct mailbox *move_mailbox; + + struct sieve_script_env *senv; + struct sieve_binary *main_sbin; + struct sieve_error_handler *ehandler; + + bool execute:1; + bool source_write:1; + bool default_move:1; +}; + +struct sieve_filter_context { + const struct sieve_filter_data *data; + + struct mailbox_transaction_context *move_trans; + + struct ostream *teststream; +}; + +static const char * +result_amend_log_message(const struct sieve_script_env *senv, + enum log_type log_type, const char *message) +{ + const struct sieve_message_data *msgdata = senv->script_context; + string_t *str; + + if (log_type == LOG_TYPE_DEBUG) + return message; + + str = t_str_new(256); + str_printfa(str, "msgid=%s", (msgdata->id == NULL ? + "unspecified" : msgdata->id)); + str_append(str, ": "); + str_append(str, message); + + return str_c(str); +} + +static int filter_message(struct sieve_filter_context *sfctx, struct mail *mail) +{ + struct sieve_error_handler *ehandler = sfctx->data->ehandler; + enum sieve_execute_flags exflags = SIEVE_EXECUTE_FLAG_LOG_RESULT; + struct sieve_script_env *senv = sfctx->data->senv; + struct sieve_exec_status estatus; + struct sieve_binary *sbin; + struct sieve_message_data msgdata; + bool execute = sfctx->data->execute; + bool source_write = sfctx->data->source_write; + const char *subject, *date; + uoff_t size = 0; + int ret; + + /* Initialize execution status */ + i_zero(&estatus); + senv->exec_status = &estatus; + + /* Collect necessary message data */ + i_zero(&msgdata); + msgdata.mail = mail; + msgdata.auth_user = senv->user->username; + (void)mail_get_message_id(mail, &msgdata.id); + senv->script_context = &msgdata; + + sieve_tool_get_envelope_data(&msgdata, mail, NULL, NULL, NULL); + + if (mail_get_virtual_size(mail, &size) < 0) { + if (mail->expunged) + return 1; + + sieve_error(ehandler, NULL, "failed to obtain message size; " + "skipping this message (id=%s)", + (msgdata.id == NULL ? "none" : msgdata.id)); + return 0; + } + + if (mail_get_first_header(mail, "date", &date) <= 0) + date = ""; + if (mail_get_first_header(mail, "subject", &subject) <= 0) + subject = ""; + + /* Single script */ + sbin = sfctx->data->main_sbin; + + /* Execute script */ + if (execute) { + sieve_info(ehandler, NULL, + "filtering: [%s; %"PRIuUOFF_T" bytes] `%s'", + date, size, str_sanitize(subject, 40)); + + ret = sieve_execute(sbin, &msgdata, senv, ehandler, ehandler, + exflags); + } else { + o_stream_nsend_str( + sfctx->teststream, + t_strdup_printf(">> Filtering message:\n\n" + " ID: %s\n" + " Date: %s\n" + " Size: %"PRIuUOFF_T" bytes\n" + " Subject: %s\n", + (msgdata.id == NULL ? + "none" : msgdata.id), date, size, + str_sanitize(subject, 40))); + + ret = sieve_test(sbin, &msgdata, senv, ehandler, + sfctx->teststream, exflags); + } + + /* Handle message in source folder */ + if (ret > 0) { + struct mailbox *move_box = sfctx->data->move_mailbox; + enum sieve_filter_discard_action discard_action = + sfctx->data->discard_action; + + if (!source_write) { + /* READ-ONLY; Do nothing */ + } else if (estatus.keep_original) { + /* Explicitly `stored' in source box; just keep it there */ + sieve_info(ehandler, NULL, + "message kept in source mailbox"); + } else if (estatus.message_saved) { + sieve_info( + ehandler, NULL, + "message expunged from source mailbox upon successful move"); + + if (execute) + mail_expunge(mail); + } else { + switch (discard_action) { + /* Leave it there */ + case SIEVE_FILTER_DACT_KEEP: + sieve_info(ehandler, NULL, + "message left in source mailbox"); + break; + /* Move message to indicated folder */ + case SIEVE_FILTER_DACT_MOVE: + sieve_info( + ehandler, NULL, + "message in source mailbox moved to mailbox '%s'", + mailbox_get_name(move_box)); + + if (execute && move_box != NULL) { + struct mailbox_transaction_context *t = + sfctx->move_trans; + struct mail_save_context *save_ctx; + + save_ctx = mailbox_save_alloc(t); + + if (mailbox_copy(&save_ctx, mail) < 0) { + enum mail_error error; + const char *errstr; + + errstr = mail_storage_get_last_error( + mailbox_get_storage(move_box), &error); + + sieve_error( + ehandler, NULL, + "failed to move message to mailbox %s: %s", + mailbox_get_name(move_box), errstr); + return -1; + } + mail_expunge(mail); + } + break; + /* Flag message as \DELETED */ + case SIEVE_FILTER_DACT_DELETE: + sieve_info( + ehandler, NULL, + "message flagged as deleted in source mailbox"); + if (execute) + mail_update_flags(mail, MODIFY_ADD, MAIL_DELETED); + break; + /* Expunge the message immediately */ + case SIEVE_FILTER_DACT_EXPUNGE: + sieve_info(ehandler, NULL, + "message expunged from source mailbox"); + if (execute) + mail_expunge(mail); + break; + /* Unknown */ + default: + i_unreached(); + break; + } + } + } + + switch (ret) { + case SIEVE_EXEC_OK: + break; + case SIEVE_EXEC_RESOURCE_LIMIT: + sieve_error(ehandler, NULL, "sieve resource limit exceeded"); + return -1; + case SIEVE_EXEC_BIN_CORRUPT: + sieve_error(ehandler, NULL, "sieve script binary is corrupt"); + return -1; + case SIEVE_EXEC_FAILURE: + case SIEVE_EXEC_TEMP_FAILURE: + if (source_write && execute && sfctx->data->default_move && + !estatus.keep_original && estatus.message_saved) { + /* The implicit keep action moved message to default + mailbox, so the source message still needs to be + expunged */ + sieve_error( + ehandler, NULL, + "sieve script execution failed for this message; " + "message moved to default mailbox"); + mail_expunge(mail); + return 0; + } + /* Fall through */ + case SIEVE_EXEC_KEEP_FAILED: + sieve_error( + ehandler, NULL, + "sieve script execution failed for this message; " + "message left in source mailbox"); + return 0; + } + + return 1; +} + +/* FIXME: introduce this into Dovecot */ +static void +mail_search_build_add_flags(struct mail_search_args *args, + enum mail_flags flags, bool not) +{ + struct mail_search_arg *arg; + + arg = p_new(args->pool, struct mail_search_arg, 1); + arg->type = SEARCH_FLAGS; + arg->value.flags = flags; + arg->match_not = not; + + arg->next = args->args; + args->args = arg; +} + +static int +filter_mailbox(const struct sieve_filter_data *sfdata, struct mailbox *src_box) +{ + struct sieve_filter_context sfctx; + struct mailbox *move_box = sfdata->move_mailbox; + struct sieve_error_handler *ehandler = sfdata->ehandler; + struct mail_search_args *search_args; + struct mailbox_transaction_context *t; + struct mail_search_context *search_ctx; + struct mail *mail; + int ret = 1; + + /* Sync source mailbox */ + + if (mailbox_sync(src_box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) { + sieve_error(ehandler, NULL, "failed to sync source mailbox"); + return -1; + } + + /* Initialize */ + + i_zero(&sfctx); + sfctx.data = sfdata; + + /* Create test stream */ + if (!sfdata->execute) { + sfctx.teststream = o_stream_create_fd(1, 0); + o_stream_set_no_error_handling(sfctx.teststream, TRUE); + } + + /* Start move mailbox transaction */ + + if (move_box != NULL) { + sfctx.move_trans = mailbox_transaction_begin( + move_box, MAILBOX_TRANSACTION_FLAG_EXTERNAL, + "sieve_filter_data move_box"); + } + + /* Search non-deleted messages in the source folder */ + + search_args = mail_search_build_init(); + mail_search_build_add_flags(search_args, MAIL_DELETED, TRUE); + + t = mailbox_transaction_begin(src_box, 0, + "sieve_filter_data src_box"); + search_ctx = mailbox_search_init(t, search_args, NULL, 0, NULL); + mail_search_args_unref(&search_args); + + /* Iterate through all requested messages */ + + while (ret >= 0 && mailbox_search_next(search_ctx, &mail)) + ret = filter_message(&sfctx, mail); + + /* Cleanup */ + + if (mailbox_search_deinit(&search_ctx) < 0) + ret = -1; + + if (sfctx.move_trans != NULL) { + if (mailbox_transaction_commit(&sfctx.move_trans) < 0) + ret = -1; + } + + if (mailbox_transaction_commit(&t) < 0) + ret = -1; + + if (sfctx.teststream != NULL) + o_stream_destroy(&sfctx.teststream); + + if (ret < 0) return ret; + + /* Sync mailbox */ + + if (sfdata->execute) { + if (mailbox_sync(src_box, MAILBOX_SYNC_FLAG_FULL_WRITE) < 0) { + sieve_error(ehandler, NULL, + "failed to sync source mailbox"); + return -1; + } + } + + return ret; +} + +/* + * Tool implementation + */ + +int main(int argc, char **argv) +{ + struct sieve_instance *svinst; + ARRAY_TYPE(const_string) scriptfiles; + const char *scriptfile, *src_mailbox, *dst_mailbox, *move_mailbox; + struct sieve_filter_data sfdata; + enum sieve_filter_discard_action discard_action = + SIEVE_FILTER_DACT_KEEP; + struct mail_user *mail_user; + struct sieve_binary *main_sbin; + struct sieve_script_env scriptenv; + struct sieve_error_handler *ehandler; + bool force_compile, execute, source_write, verbose, default_move; + struct mail_namespace *ns; + struct mailbox *src_box = NULL, *move_box = NULL; + enum mailbox_flags open_flags = MAILBOX_FLAG_IGNORE_ACLS; + enum mail_error error; + const char *errstr; + int c; + + sieve_tool = sieve_tool_init("sieve-filter", &argc, &argv, + "m:s:x:P:u:q:Q:DCevW", FALSE); + + t_array_init(&scriptfiles, 16); + + /* Parse arguments */ + dst_mailbox = move_mailbox = NULL; + force_compile = execute = source_write = default_move = FALSE; + verbose = FALSE; + while ((c = sieve_tool_getopt(sieve_tool)) > 0) { + switch (c) { + case 'm': + /* default mailbox (keep box) */ + dst_mailbox = optarg; + break; + case 's': + /* scriptfile executed before main script */ + { + const char *file; + + file = t_strdup(optarg); + array_append(&scriptfiles, &file, 1); + + /* FIXME: */ + i_fatal_status( + EX_USAGE, + "The -s argument is currently NOT IMPLEMENTED"); + } + break; + case 'q': + i_fatal_status( + EX_USAGE, + "The -q argument is currently NOT IMPLEMENTED"); + break; + case 'Q': + i_fatal_status( + EX_USAGE, + "The -Q argument is currently NOT IMPLEMENTED"); + break; + case 'e': + /* execution mode */ + execute = TRUE; + break; + case 'C': + /* force script compile */ + force_compile = TRUE; + break; + case 'W': + /* enable source mailbox write */ + source_write = TRUE; + break; + case 'v': + /* enable verbose output */ + verbose = TRUE; + break; + default: + /* unrecognized option */ + print_help(); + i_fatal_status(EX_USAGE, "Unknown argument: %c", c); + break; + } + } + + /* Script file argument */ + if (optind < argc) + scriptfile = t_strdup(argv[optind++]); + else { + print_help(); + i_fatal_status(EX_USAGE, "Missing <script-file> argument"); + } + + /* Source mailbox argument */ + if (optind < argc) + src_mailbox = t_strdup(argv[optind++]); + else { + print_help(); + i_fatal_status(EX_USAGE, "Missing <source-mailbox> argument"); + } + + /* Source action argument */ + if (optind < argc) { + const char *srcact = argv[optind++]; + + if (strcmp(srcact, "keep") == 0) { + discard_action = SIEVE_FILTER_DACT_KEEP; + } else if (strcmp(srcact, "move") == 0) { + discard_action = SIEVE_FILTER_DACT_MOVE; + if (optind < argc) + move_mailbox = t_strdup(argv[optind++]); + else { + print_help(); + i_fatal_status( + EX_USAGE, + "Invalid <discard-action> argument: " + "the `move' action requires mailbox argument"); + } + } else if (strcmp(srcact, "delete") == 0) { + discard_action = SIEVE_FILTER_DACT_DELETE; + } else if (strcmp(srcact, "expunge") == 0) { + discard_action = SIEVE_FILTER_DACT_EXPUNGE; + } else { + print_help(); + i_fatal_status(EX_USAGE, + "Invalid <discard-action> argument"); + } + } + + if (optind != argc) { + print_help(); + i_fatal_status(EX_USAGE, "Unknown argument: %s", argv[optind]); + } + + if (dst_mailbox == NULL) { + dst_mailbox = src_mailbox; + } else { + /* The (implicit) keep action will move the message */ + default_move = TRUE; + } + + /* Finish tool initialization */ + svinst = sieve_tool_init_finish(sieve_tool, TRUE, FALSE); + + /* Enable debug extension */ + sieve_enable_debug_extension(svinst); + + /* Create error handler */ + ehandler = sieve_stderr_ehandler_create(svinst, 0); + sieve_error_handler_accept_infolog(ehandler, verbose); + sieve_error_handler_accept_debuglog(ehandler, svinst->debug); + + /* Compile main sieve script */ + if (force_compile) { + main_sbin = sieve_tool_script_compile(svinst, scriptfile, NULL); + if (main_sbin != NULL) + (void)sieve_save(main_sbin, TRUE, NULL); + } else { + main_sbin = sieve_tool_script_open(svinst, scriptfile); + } + + /* Initialize mail user */ + mail_user = sieve_tool_get_mail_user(sieve_tool); + + /* Open the source mailbox */ + + ns = mail_namespace_find(mail_user->namespaces, src_mailbox); + if (ns == NULL) { + i_fatal("Unknown namespace for source mailbox '%s'", + src_mailbox); + } + + if (!source_write || !execute) + open_flags |= MAILBOX_FLAG_READONLY; + + src_box = mailbox_alloc(ns->list, src_mailbox, open_flags); + if (mailbox_open(src_box) < 0) { + i_fatal("Couldn't open source mailbox '%s': %s", + src_mailbox, mailbox_get_last_internal_error(src_box, &error)); + } + + /* Open move box if necessary */ + + if (execute && discard_action == SIEVE_FILTER_DACT_MOVE && + move_mailbox != NULL) { + ns = mail_namespace_find(mail_user->namespaces, move_mailbox); + if (ns == NULL) + i_fatal("Unknown namespace for mailbox '%s'", + move_mailbox); + + move_box = mailbox_alloc(ns->list, move_mailbox, open_flags); + if (mailbox_open(move_box) < 0) { + i_fatal("Couldn't open mailbox '%s': %s", + move_mailbox, + mailbox_get_last_internal_error(move_box, &error)); + } + + if (mailbox_backends_equal(src_box, move_box)) + i_fatal("Source mailbox and mailbox for move action are identical."); + } + + /* Compose script environment */ + if (sieve_script_env_init(&scriptenv, mail_user, &errstr) < 0) + i_fatal("Failed to initialize script execution: %s", errstr); + scriptenv.mailbox_autocreate = FALSE; + scriptenv.default_mailbox = dst_mailbox; + scriptenv.result_amend_log_message = result_amend_log_message; + + /* Compose filter context */ + i_zero(&sfdata); + sfdata.senv = &scriptenv; + sfdata.discard_action = discard_action; + sfdata.move_mailbox = move_box; + sfdata.main_sbin = main_sbin; + sfdata.ehandler = ehandler; + sfdata.execute = execute; + sfdata.source_write = source_write; + sfdata.default_move = default_move; + + /* Apply Sieve filter to all messages found */ + (void)filter_mailbox(&sfdata, src_box); + + /* Close the source mailbox */ + if (src_box != NULL) + mailbox_free(&src_box); + + /* Close the move mailbox */ + if (move_box != NULL) + mailbox_free(&move_box); + + /* Close the script binary */ + if (main_sbin != NULL) + sieve_close(&main_sbin); + + /* Cleanup error handler */ + sieve_error_handler_unref(&ehandler); + + sieve_tool_deinit(&sieve_tool); + + return 0; +} diff --git a/pigeonhole/src/sieve-tools/sieve-test.c b/pigeonhole/src/sieve-tools/sieve-test.c new file mode 100644 index 0000000..e7345be --- /dev/null +++ b/pigeonhole/src/sieve-tools/sieve-test.c @@ -0,0 +1,515 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "lib-signals.h" +#include "ioloop.h" +#include "env-util.h" +#include "str.h" +#include "ostream.h" +#include "array.h" +#include "mail-namespace.h" +#include "mail-storage.h" +#include "master-service.h" +#include "master-service-settings.h" +#include "mail-storage-service.h" + +#include "sieve.h" +#include "sieve-binary.h" +#include "sieve-extensions.h" + +#include "sieve-tool.h" + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <pwd.h> +#include <sysexits.h> + + +/* + * Configuration + */ + +#define DEFAULT_SENDMAIL_PATH "/usr/lib/sendmail" + +/* + * Print help + */ + +static void print_help(void) +{ + printf( +"Usage: sieve-test [-a <orig-recipient-address] [-c <config-file>]\n" +" [-C] [-D] [-d <dump-filename>] [-e]\n" +" [-f <envelope-sender>] [-l <mail-location>]\n" +" [-m <default-mailbox>] [-P <plugin>]\n" +" [-r <recipient-address>] [-s <script-file>]\n" +" [-t <trace-file>] [-T <trace-option>] [-x <extensions>]\n" +" <script-file> <mail-file>\n" + ); +} + +/* + * Dummy SMTP session + */ + +static void * +sieve_smtp_start(const struct sieve_script_env *senv ATTR_UNUSED, + const struct smtp_address *mail_from) +{ + struct ostream *output; + + i_info("sending message from <%s>:", smtp_address_encode(mail_from)); + + output = o_stream_create_fd(STDOUT_FILENO, (size_t)-1); + o_stream_set_no_error_handling(output, TRUE); + return (void*)output; +} + +static void +sieve_smtp_add_rcpt(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle ATTR_UNUSED, + const struct smtp_address *rcpt_to) +{ + printf("\nRECIPIENT: %s\n", smtp_address_encode(rcpt_to)); +} + +static struct ostream * +sieve_smtp_send(const struct sieve_script_env *senv ATTR_UNUSED, void *handle) +{ + printf("START MESSAGE:\n"); + + return (struct ostream *)handle; +} + +static void +sieve_smtp_abort(const struct sieve_script_env *senv ATTR_UNUSED, void *handle) +{ + struct ostream *output = (struct ostream *)handle; + + printf("#### ABORT MESSAGE ####\n\n"); + o_stream_unref(&output); +} + +static int +sieve_smtp_finish(const struct sieve_script_env *senv ATTR_UNUSED, void *handle, + const char **error_r ATTR_UNUSED) +{ + struct ostream *output = (struct ostream *)handle; + + printf("END MESSAGE\n\n"); + o_stream_unref(&output); + return 1; +} + +/* + * Dummy duplicate check implementation + */ + +static void * +duplicate_transaction_begin(const struct sieve_script_env *senv ATTR_UNUSED) +{ + return NULL; +} + +static void duplicate_transaction_commit(void **_dup_trans ATTR_UNUSED) +{ +} + +static void duplicate_transaction_rollback(void **_dup_trans ATTR_UNUSED) +{ +} + +static int +duplicate_check(void *_dup_trans ATTR_UNUSED, + const struct sieve_script_env *senv, + const void *id ATTR_UNUSED, size_t id_size ATTR_UNUSED) +{ + i_info("checked duplicate for user %s.\n", senv->user->username); + return 0; +} + +static void +duplicate_mark(void *_dup_trans ATTR_UNUSED, + const struct sieve_script_env *senv, + const void *id ATTR_UNUSED, size_t id_size ATTR_UNUSED, + time_t time ATTR_UNUSED) +{ + i_info("marked duplicate for user %s.\n", senv->user->username); +} + +/* + * Result logging + */ + +static const char * +result_amend_log_message(const struct sieve_script_env *senv, + enum log_type log_type, const char *message) +{ + const struct sieve_message_data *msgdata = senv->script_context; + string_t *str; + + if (log_type == LOG_TYPE_DEBUG) + return message; + + str = t_str_new(256); + str_printfa(str, "msgid=%s", (msgdata->id == NULL ? + "unspecified" : msgdata->id)); + str_append(str, ": "); + str_append(str, message); + + return str_c(str); +} + +/* + * Tool implementation + */ + +int main(int argc, char **argv) +{ + struct sieve_instance *svinst; + ARRAY_TYPE (const_string) scriptfiles; + const char *scriptfile, *mailbox, *dumpfile, *tracefile, *mailfile, + *mailloc, *errstr; + struct smtp_address *rcpt_to, *final_rcpt_to, *mail_from; + struct sieve_trace_config trace_config; + struct mail *mail; + struct sieve_binary *main_sbin, *sbin = NULL; + struct sieve_message_data msgdata; + struct sieve_script_env scriptenv; + struct sieve_exec_status estatus; + enum sieve_execute_flags exflags = SIEVE_EXECUTE_FLAG_LOG_RESULT; + struct sieve_error_handler *ehandler; + struct ostream *teststream = NULL; + struct sieve_trace_log *trace_log = NULL; + bool force_compile = FALSE, execute = FALSE; + int exit_status = EXIT_SUCCESS; + int ret, c; + + sieve_tool = sieve_tool_init("sieve-test", &argc, &argv, + "r:a:f:m:d:l:s:eCt:T:DP:x:u:", FALSE); + + ehandler = NULL; + t_array_init(&scriptfiles, 16); + + /* Parse arguments */ + mailbox = dumpfile = tracefile = mailloc = NULL; + mail_from = final_rcpt_to = rcpt_to = NULL; + i_zero(&trace_config); + trace_config.level = SIEVE_TRLVL_ACTIONS; + while ((c = sieve_tool_getopt(sieve_tool)) > 0) { + switch (c) { + case 'r': + /* final recipient address */ + if (smtp_address_parse_mailbox( + pool_datastack_create(), optarg, + SMTP_ADDRESS_PARSE_FLAG_ALLOW_LOCALPART, + &final_rcpt_to, &errstr) < 0) + i_fatal("Invalid -r parameter: %s", errstr); + break; + case 'a': + /* original recipient address */ + if (smtp_address_parse_mailbox( + pool_datastack_create(), optarg, + SMTP_ADDRESS_PARSE_FLAG_ALLOW_LOCALPART, + &rcpt_to, &errstr) < 0) + i_fatal("Invalid -a parameter: %s", errstr); + break; + case 'f': + /* envelope sender address */ + if (smtp_address_parse_mailbox( + pool_datastack_create(), optarg, + 0, &mail_from, &errstr) < 0) + i_fatal("Invalid -f parameter: %s", errstr); + break; + case 'm': + /* default mailbox (keep box) */ + mailbox = optarg; + break; + case 'l': + /* mail location */ + mailloc = optarg; + break; + case 't': + /* trace file */ + tracefile = optarg; + break; + /* trace options */ + case 'T': + sieve_tool_parse_trace_option(&trace_config, optarg); + break; + case 'd': + /* dump file */ + dumpfile = optarg; + break; + case 's': + /* scriptfile executed before main script */ + { + const char *file; + + file = t_strdup(optarg); + array_append(&scriptfiles, &file, 1); + } + break; + /* execution mode */ + case 'e': + execute = TRUE; + break; + /* force script compile */ + case 'C': + force_compile = TRUE; + break; + default: + /* unrecognized option */ + print_help(); + i_fatal_status(EX_USAGE, "Unknown argument: %c", c); + break; + } + } + + if (optind < argc) + scriptfile = argv[optind++]; + else { + print_help(); + i_fatal_status(EX_USAGE, "Missing <script-file> argument"); + } + + if (optind < argc) + mailfile = argv[optind++]; + else { + print_help(); + i_fatal_status(EX_USAGE, "Missing <mail-file> argument"); + } + + if (optind != argc) { + print_help(); + i_fatal_status(EX_USAGE, "Unknown argument: %s", argv[optind]); + } + + /* Finish tool initialization */ + svinst = sieve_tool_init_finish(sieve_tool, mailloc == NULL, FALSE); + + /* Enable debug extension */ + sieve_enable_debug_extension(svinst); + + /* Create error handler */ + ehandler = sieve_stderr_ehandler_create(svinst, 0); + sieve_error_handler_accept_infolog(ehandler, TRUE); + sieve_error_handler_accept_debuglog(ehandler, svinst->debug); + + /* Compile main sieve script */ + if (force_compile) { + main_sbin = sieve_tool_script_compile(svinst, scriptfile, NULL); + if (main_sbin != NULL) + (void)sieve_save(main_sbin, TRUE, NULL); + } else { + main_sbin = sieve_tool_script_open(svinst, scriptfile); + } + + if (main_sbin == NULL) { + exit_status = EXIT_FAILURE; + } else { + /* Dump script */ + sieve_tool_dump_binary_to(main_sbin, dumpfile, FALSE); + + /* Obtain mail namespaces from -l argument */ + if (mailloc != NULL) + sieve_tool_init_mail_user(sieve_tool, mailloc); + + /* Initialize raw mail object */ + mail = sieve_tool_open_file_as_mail(sieve_tool, mailfile); + + if (mailbox == NULL) + mailbox = "INBOX"; + + /* Collect necessary message data */ + i_zero(&msgdata); + msgdata.mail = mail; + msgdata.auth_user = sieve_tool_get_username(sieve_tool); + (void)mail_get_message_id(mail, &msgdata.id); + + sieve_tool_get_envelope_data(&msgdata, mail, + mail_from, rcpt_to, final_rcpt_to); + + /* Create streams for test and trace output */ + + if (!execute) { + teststream = o_stream_create_fd(1, 0); + o_stream_set_no_error_handling(teststream, TRUE); + } + + if (tracefile != NULL) { + (void)sieve_trace_log_create( + svinst, (strcmp(tracefile, "-") == 0 ? + NULL : tracefile), &trace_log); + } + + /* Compose script environment */ + if (sieve_script_env_init( + &scriptenv, sieve_tool_get_mail_user(sieve_tool), + &errstr) < 0) { + i_fatal("Failed to initialize script execution: %s", + errstr); + } + + scriptenv.default_mailbox = mailbox; + scriptenv.smtp_start = sieve_smtp_start; + scriptenv.smtp_add_rcpt = sieve_smtp_add_rcpt; + scriptenv.smtp_send = sieve_smtp_send; + scriptenv.smtp_abort = sieve_smtp_abort; + scriptenv.smtp_finish = sieve_smtp_finish; + scriptenv.duplicate_transaction_begin = + duplicate_transaction_begin; + scriptenv.duplicate_transaction_commit = + duplicate_transaction_commit; + scriptenv.duplicate_transaction_rollback = + duplicate_transaction_rollback; + scriptenv.duplicate_mark = duplicate_mark; + scriptenv.duplicate_check = duplicate_check; + scriptenv.result_amend_log_message = result_amend_log_message; + scriptenv.trace_log = trace_log; + scriptenv.trace_config = trace_config; + scriptenv.script_context = &msgdata; + + i_zero(&estatus); + scriptenv.exec_status = &estatus; + + /* Run the test */ + ret = 1; + if (array_count(&scriptfiles) == 0) { + /* Single script */ + sbin = main_sbin; + main_sbin = NULL; + + /* Execute/Test script */ + if (execute) { + ret = sieve_execute(sbin, &msgdata, &scriptenv, + ehandler, ehandler, + exflags); + } else { + ret = sieve_test(sbin, &msgdata, &scriptenv, + ehandler, teststream, exflags); + } + } else { + /* Multiple scripts */ + const char *const *sfiles; + unsigned int i, count; + struct sieve_multiscript *mscript; + bool more = TRUE; + + if (execute) + mscript = sieve_multiscript_start_execute( + svinst, &msgdata, &scriptenv); + else + mscript = sieve_multiscript_start_test( + svinst, &msgdata, &scriptenv, + teststream); + + /* Execute scripts sequentially */ + sfiles = array_get(&scriptfiles, &count); + for (i = 0; i < count && more; i++) { + if (teststream != NULL) { + o_stream_nsend_str( + teststream, + t_strdup_printf("\n## Executing script: %s\n", + sfiles[i])); + } + + /* Close previous script */ + if (sbin != NULL) + sieve_close(&sbin); + + /* Compile sieve script */ + if (force_compile) { + sbin = sieve_tool_script_compile( + svinst, sfiles[i], sfiles[i]); + if (sbin != NULL) + (void)sieve_save(sbin, FALSE, NULL); + } else { + sbin = sieve_tool_script_open(svinst, sfiles[i]); + } + + if (sbin == NULL) { + ret = SIEVE_EXEC_FAILURE; + break; + } + + /* Execute/Test script */ + more = sieve_multiscript_run( + mscript, sbin, ehandler, ehandler, + exflags); + } + + /* Execute/Test main script */ + if (more && ret > 0) { + if (teststream != NULL) { + o_stream_nsend_str( + teststream, + t_strdup_printf("## Executing script: %s\n", + scriptfile)); + } + + /* Close previous script */ + if (sbin != NULL) + sieve_close(&sbin); + + sbin = main_sbin; + main_sbin = NULL; + + (void)sieve_multiscript_run( + mscript, sbin, ehandler, ehandler, + exflags); + } + + ret = sieve_multiscript_finish(&mscript, ehandler, + exflags, ret); + } + + /* Run */ + switch (ret) { + case SIEVE_EXEC_OK: + i_info("final result: success"); + break; + case SIEVE_EXEC_RESOURCE_LIMIT: + i_info("resource limit exceeded"); + exit_status = EXIT_FAILURE; + break; + case SIEVE_EXEC_BIN_CORRUPT: + i_info("corrupt binary deleted."); + i_unlink_if_exists(sieve_binary_path(sbin)); + /* fall through */ + case SIEVE_EXEC_FAILURE: + i_info("final result: failed; " + "resolved with successful implicit keep"); + exit_status = EXIT_FAILURE; + break; + case SIEVE_EXEC_TEMP_FAILURE: + i_info("final result: temporary failure"); + exit_status = EXIT_FAILURE; + break; + case SIEVE_EXEC_KEEP_FAILED: + i_info("final result: utter failure"); + exit_status = EXIT_FAILURE; + break; + } + + if (teststream != NULL) + o_stream_destroy(&teststream); + if (trace_log != NULL) + sieve_trace_log_free(&trace_log); + + /* Cleanup remaining binaries */ + if (sbin != NULL) + sieve_close(&sbin); + if (main_sbin != NULL) + sieve_close(&main_sbin); + } + + /* Cleanup error handler */ + sieve_error_handler_unref(&ehandler); + + sieve_tool_deinit(&sieve_tool); + + return exit_status; +} diff --git a/pigeonhole/src/sieve-tools/sievec.c b/pigeonhole/src/sieve-tools/sievec.c new file mode 100644 index 0000000..d70435d --- /dev/null +++ b/pigeonhole/src/sieve-tools/sievec.c @@ -0,0 +1,157 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "master-service.h" +#include "master-service-settings.h" +#include "mail-storage-service.h" +#include "mail-user.h" + +#include "sieve.h" +#include "sieve-extensions.h" +#include "sieve-script.h" +#include "sieve-tool.h" + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <dirent.h> +#include <sysexits.h> + +/* + * Print help + */ + +static void print_help(void) +{ + printf( +"Usage: sievec [-c <config-file>] [-d] [-D] [-P <plugin>] [-x <extensions>] \n" +" <script-file> [<out-file>]\n" + ); +} + +/* + * Tool implementation + */ + +int main(int argc, char **argv) +{ + struct sieve_instance *svinst; + struct stat st; + struct sieve_binary *sbin; + bool dump = FALSE; + const char *scriptfile, *outfile; + int exit_status = EXIT_SUCCESS; + int c; + + sieve_tool = sieve_tool_init("sievec", &argc, &argv, "DdP:x:u:", FALSE); + + outfile = NULL; + while ((c = sieve_tool_getopt(sieve_tool)) > 0) { + switch (c) { + case 'd': + /* dump file */ + dump = TRUE; + break; + default: + print_help(); + i_fatal_status(EX_USAGE, "Unknown argument: %c", c); + break; + } + } + + if ( optind < argc ) { + scriptfile = argv[optind++]; + } else { + print_help(); + i_fatal_status(EX_USAGE, "Missing <script-file> argument"); + } + + if ( optind < argc ) { + outfile = argv[optind++]; + } else if ( dump ) { + outfile = "-"; + } + + svinst = sieve_tool_init_finish(sieve_tool, FALSE, TRUE); + + /* Enable debug extension */ + sieve_enable_debug_extension(svinst); + + if ( stat(scriptfile, &st) == 0 && S_ISDIR(st.st_mode) ) { + /* Script directory */ + DIR *dirp; + struct dirent *dp; + + /* Sanity checks on some of the arguments */ + + if ( dump ) + i_fatal_status(EX_USAGE, + "the -d option is not allowed when scriptfile is a directory."); + + if ( outfile != NULL ) + i_fatal_status(EX_USAGE, + "the outfile argument is not allowed when scriptfile is a directory."); + + /* Open the directory */ + if ( (dirp = opendir(scriptfile)) == NULL ) + i_fatal("opendir(%s) failed: %m", scriptfile); + + /* Compile each sieve file */ + for (;;) { + + errno = 0; + if ( (dp = readdir(dirp)) == NULL ) { + if ( errno != 0 ) + i_fatal("readdir(%s) failed: %m", scriptfile); + break; + } + + if ( sieve_script_file_has_extension(dp->d_name) ) { + const char *file; + + if ( scriptfile[strlen(scriptfile)-1] == '/' ) + file = t_strconcat(scriptfile, dp->d_name, NULL); + else + file = t_strconcat(scriptfile, "/", dp->d_name, NULL); + + sbin = sieve_tool_script_compile(svinst, file, NULL); + + if ( sbin != NULL ) { + sieve_save(sbin, TRUE, NULL); + sieve_close(&sbin); + } + } + } + + /* Close the directory */ + if ( closedir(dirp) < 0 ) + i_fatal("closedir(%s) failed: %m", scriptfile); + } else { + /* Script file (i.e. not a directory) + * + * NOTE: For consistency, stat errors are handled here as well + */ + sbin = sieve_tool_script_compile(svinst, scriptfile, NULL); + + if ( sbin != NULL ) { + if ( dump ) + sieve_tool_dump_binary_to(sbin, outfile, FALSE); + else { + sieve_save_as(sbin, outfile, TRUE, 0600, NULL); + } + + sieve_close(&sbin); + } else { + exit_status = EXIT_FAILURE; + } + } + + sieve_tool_deinit(&sieve_tool); + + return exit_status; +} diff --git a/pigeonhole/src/testsuite/Makefile.am b/pigeonhole/src/testsuite/Makefile.am new file mode 100644 index 0000000..f7b85dc --- /dev/null +++ b/pigeonhole/src/testsuite/Makefile.am @@ -0,0 +1,74 @@ +noinst_PROGRAMS = testsuite + +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + -I$(top_srcdir)/src/lib-sieve/util \ + -I$(top_srcdir)/src/lib-sieve/plugins/variables \ + -I$(top_srcdir)/src/lib-sieve-tool \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_SERVICE_INCLUDE) + +testsuite_LDFLAGS = -export-dynamic + +libs = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la \ + $(top_builddir)/src/lib-sieve-tool/libsieve-tool.la + +testsuite_LDADD = $(libs) $(LIBDOVECOT_STORAGE) $(LIBDOVECOT_LDA) $(LIBDOVECOT) +testsuite_DEPENDENCIES = $(libs) $(LIBDOVECOT_STORAGE_DEPS) $(LIBDOVECOT_LDA_DEPS) $(LIBDOVECOT_DEPS) + +commands = \ + cmd-test.c \ + cmd-test-fail.c \ + cmd-test-config.c \ + cmd-test-set.c \ + cmd-test-result.c \ + cmd-test-message.c \ + cmd-test-mailbox.c \ + cmd-test-binary.c \ + cmd-test-imap-metadata.c + +tests = \ + tst-test-script-compile.c \ + tst-test-script-run.c \ + tst-test-multiscript.c \ + tst-test-error.c \ + tst-test-result-action.c \ + tst-test-result-execute.c + +testsuite_SOURCES = \ + testsuite-common.c \ + testsuite-settings.c \ + testsuite-objects.c \ + testsuite-substitutions.c \ + testsuite-variables.c \ + testsuite-arguments.c \ + testsuite-message.c \ + testsuite-log.c \ + testsuite-script.c \ + testsuite-result.c \ + testsuite-smtp.c \ + testsuite-mailstore.c \ + testsuite-binary.c \ + $(commands) \ + $(tests) \ + ext-testsuite.c \ + testsuite.c + +noinst_HEADERS = \ + testsuite-common.h \ + testsuite-settings.h \ + testsuite-objects.h \ + testsuite-substitutions.h \ + testsuite-variables.h \ + testsuite-arguments.h \ + testsuite-message.h \ + testsuite-log.h \ + testsuite-script.h \ + testsuite-result.h \ + testsuite-smtp.h \ + testsuite-mailstore.h \ + testsuite-binary.h + +clean-local: + -rm -rf test.out.* diff --git a/pigeonhole/src/testsuite/Makefile.in b/pigeonhole/src/testsuite/Makefile.in new file mode 100644 index 0000000..1f9043f --- /dev/null +++ b/pigeonhole/src/testsuite/Makefile.in @@ -0,0 +1,869 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = testsuite$(EXEEXT) +subdir = src/testsuite +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +am__objects_1 = cmd-test.$(OBJEXT) cmd-test-fail.$(OBJEXT) \ + cmd-test-config.$(OBJEXT) cmd-test-set.$(OBJEXT) \ + cmd-test-result.$(OBJEXT) cmd-test-message.$(OBJEXT) \ + cmd-test-mailbox.$(OBJEXT) cmd-test-binary.$(OBJEXT) \ + cmd-test-imap-metadata.$(OBJEXT) +am__objects_2 = tst-test-script-compile.$(OBJEXT) \ + tst-test-script-run.$(OBJEXT) tst-test-multiscript.$(OBJEXT) \ + tst-test-error.$(OBJEXT) tst-test-result-action.$(OBJEXT) \ + tst-test-result-execute.$(OBJEXT) +am_testsuite_OBJECTS = testsuite-common.$(OBJEXT) \ + testsuite-settings.$(OBJEXT) testsuite-objects.$(OBJEXT) \ + testsuite-substitutions.$(OBJEXT) \ + testsuite-variables.$(OBJEXT) testsuite-arguments.$(OBJEXT) \ + testsuite-message.$(OBJEXT) testsuite-log.$(OBJEXT) \ + testsuite-script.$(OBJEXT) testsuite-result.$(OBJEXT) \ + testsuite-smtp.$(OBJEXT) testsuite-mailstore.$(OBJEXT) \ + testsuite-binary.$(OBJEXT) $(am__objects_1) $(am__objects_2) \ + ext-testsuite.$(OBJEXT) testsuite.$(OBJEXT) +testsuite_OBJECTS = $(am_testsuite_OBJECTS) +am__DEPENDENCIES_1 = +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +testsuite_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(testsuite_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/cmd-test-binary.Po \ + ./$(DEPDIR)/cmd-test-config.Po ./$(DEPDIR)/cmd-test-fail.Po \ + ./$(DEPDIR)/cmd-test-imap-metadata.Po \ + ./$(DEPDIR)/cmd-test-mailbox.Po \ + ./$(DEPDIR)/cmd-test-message.Po ./$(DEPDIR)/cmd-test-result.Po \ + ./$(DEPDIR)/cmd-test-set.Po ./$(DEPDIR)/cmd-test.Po \ + ./$(DEPDIR)/ext-testsuite.Po \ + ./$(DEPDIR)/testsuite-arguments.Po \ + ./$(DEPDIR)/testsuite-binary.Po \ + ./$(DEPDIR)/testsuite-common.Po ./$(DEPDIR)/testsuite-log.Po \ + ./$(DEPDIR)/testsuite-mailstore.Po \ + ./$(DEPDIR)/testsuite-message.Po \ + ./$(DEPDIR)/testsuite-objects.Po \ + ./$(DEPDIR)/testsuite-result.Po \ + ./$(DEPDIR)/testsuite-script.Po \ + ./$(DEPDIR)/testsuite-settings.Po \ + ./$(DEPDIR)/testsuite-smtp.Po \ + ./$(DEPDIR)/testsuite-substitutions.Po \ + ./$(DEPDIR)/testsuite-variables.Po ./$(DEPDIR)/testsuite.Po \ + ./$(DEPDIR)/tst-test-error.Po \ + ./$(DEPDIR)/tst-test-multiscript.Po \ + ./$(DEPDIR)/tst-test-result-action.Po \ + ./$(DEPDIR)/tst-test-result-execute.Po \ + ./$(DEPDIR)/tst-test-script-compile.Po \ + ./$(DEPDIR)/tst-test-script-run.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(testsuite_SOURCES) +DIST_SOURCES = $(testsuite_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + -I$(top_srcdir)/src/lib-sieve/util \ + -I$(top_srcdir)/src/lib-sieve/plugins/variables \ + -I$(top_srcdir)/src/lib-sieve-tool \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_SERVICE_INCLUDE) + +testsuite_LDFLAGS = -export-dynamic +libs = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la \ + $(top_builddir)/src/lib-sieve-tool/libsieve-tool.la + +testsuite_LDADD = $(libs) $(LIBDOVECOT_STORAGE) $(LIBDOVECOT_LDA) $(LIBDOVECOT) +testsuite_DEPENDENCIES = $(libs) $(LIBDOVECOT_STORAGE_DEPS) $(LIBDOVECOT_LDA_DEPS) $(LIBDOVECOT_DEPS) +commands = \ + cmd-test.c \ + cmd-test-fail.c \ + cmd-test-config.c \ + cmd-test-set.c \ + cmd-test-result.c \ + cmd-test-message.c \ + cmd-test-mailbox.c \ + cmd-test-binary.c \ + cmd-test-imap-metadata.c + +tests = \ + tst-test-script-compile.c \ + tst-test-script-run.c \ + tst-test-multiscript.c \ + tst-test-error.c \ + tst-test-result-action.c \ + tst-test-result-execute.c + +testsuite_SOURCES = \ + testsuite-common.c \ + testsuite-settings.c \ + testsuite-objects.c \ + testsuite-substitutions.c \ + testsuite-variables.c \ + testsuite-arguments.c \ + testsuite-message.c \ + testsuite-log.c \ + testsuite-script.c \ + testsuite-result.c \ + testsuite-smtp.c \ + testsuite-mailstore.c \ + testsuite-binary.c \ + $(commands) \ + $(tests) \ + ext-testsuite.c \ + testsuite.c + +noinst_HEADERS = \ + testsuite-common.h \ + testsuite-settings.h \ + testsuite-objects.h \ + testsuite-substitutions.h \ + testsuite-variables.h \ + testsuite-arguments.h \ + testsuite-message.h \ + testsuite-log.h \ + testsuite-script.h \ + testsuite-result.h \ + testsuite-smtp.h \ + testsuite-mailstore.h \ + testsuite-binary.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/testsuite/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/testsuite/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +testsuite$(EXEEXT): $(testsuite_OBJECTS) $(testsuite_DEPENDENCIES) $(EXTRA_testsuite_DEPENDENCIES) + @rm -f testsuite$(EXEEXT) + $(AM_V_CCLD)$(testsuite_LINK) $(testsuite_OBJECTS) $(testsuite_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-test-binary.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-test-config.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-test-fail.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-test-imap-metadata.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-test-mailbox.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-test-message.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-test-result.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-test-set.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-testsuite.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testsuite-arguments.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testsuite-binary.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testsuite-common.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testsuite-log.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testsuite-mailstore.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testsuite-message.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testsuite-objects.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testsuite-result.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testsuite-script.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testsuite-settings.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testsuite-smtp.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testsuite-substitutions.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testsuite-variables.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testsuite.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-test-error.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-test-multiscript.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-test-result-action.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-test-result-execute.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-test-script-compile.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-test-script-run.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-local clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-test-binary.Po + -rm -f ./$(DEPDIR)/cmd-test-config.Po + -rm -f ./$(DEPDIR)/cmd-test-fail.Po + -rm -f ./$(DEPDIR)/cmd-test-imap-metadata.Po + -rm -f ./$(DEPDIR)/cmd-test-mailbox.Po + -rm -f ./$(DEPDIR)/cmd-test-message.Po + -rm -f ./$(DEPDIR)/cmd-test-result.Po + -rm -f ./$(DEPDIR)/cmd-test-set.Po + -rm -f ./$(DEPDIR)/cmd-test.Po + -rm -f ./$(DEPDIR)/ext-testsuite.Po + -rm -f ./$(DEPDIR)/testsuite-arguments.Po + -rm -f ./$(DEPDIR)/testsuite-binary.Po + -rm -f ./$(DEPDIR)/testsuite-common.Po + -rm -f ./$(DEPDIR)/testsuite-log.Po + -rm -f ./$(DEPDIR)/testsuite-mailstore.Po + -rm -f ./$(DEPDIR)/testsuite-message.Po + -rm -f ./$(DEPDIR)/testsuite-objects.Po + -rm -f ./$(DEPDIR)/testsuite-result.Po + -rm -f ./$(DEPDIR)/testsuite-script.Po + -rm -f ./$(DEPDIR)/testsuite-settings.Po + -rm -f ./$(DEPDIR)/testsuite-smtp.Po + -rm -f ./$(DEPDIR)/testsuite-substitutions.Po + -rm -f ./$(DEPDIR)/testsuite-variables.Po + -rm -f ./$(DEPDIR)/testsuite.Po + -rm -f ./$(DEPDIR)/tst-test-error.Po + -rm -f ./$(DEPDIR)/tst-test-multiscript.Po + -rm -f ./$(DEPDIR)/tst-test-result-action.Po + -rm -f ./$(DEPDIR)/tst-test-result-execute.Po + -rm -f ./$(DEPDIR)/tst-test-script-compile.Po + -rm -f ./$(DEPDIR)/tst-test-script-run.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/cmd-test-binary.Po + -rm -f ./$(DEPDIR)/cmd-test-config.Po + -rm -f ./$(DEPDIR)/cmd-test-fail.Po + -rm -f ./$(DEPDIR)/cmd-test-imap-metadata.Po + -rm -f ./$(DEPDIR)/cmd-test-mailbox.Po + -rm -f ./$(DEPDIR)/cmd-test-message.Po + -rm -f ./$(DEPDIR)/cmd-test-result.Po + -rm -f ./$(DEPDIR)/cmd-test-set.Po + -rm -f ./$(DEPDIR)/cmd-test.Po + -rm -f ./$(DEPDIR)/ext-testsuite.Po + -rm -f ./$(DEPDIR)/testsuite-arguments.Po + -rm -f ./$(DEPDIR)/testsuite-binary.Po + -rm -f ./$(DEPDIR)/testsuite-common.Po + -rm -f ./$(DEPDIR)/testsuite-log.Po + -rm -f ./$(DEPDIR)/testsuite-mailstore.Po + -rm -f ./$(DEPDIR)/testsuite-message.Po + -rm -f ./$(DEPDIR)/testsuite-objects.Po + -rm -f ./$(DEPDIR)/testsuite-result.Po + -rm -f ./$(DEPDIR)/testsuite-script.Po + -rm -f ./$(DEPDIR)/testsuite-settings.Po + -rm -f ./$(DEPDIR)/testsuite-smtp.Po + -rm -f ./$(DEPDIR)/testsuite-substitutions.Po + -rm -f ./$(DEPDIR)/testsuite-variables.Po + -rm -f ./$(DEPDIR)/testsuite.Po + -rm -f ./$(DEPDIR)/tst-test-error.Po + -rm -f ./$(DEPDIR)/tst-test-multiscript.Po + -rm -f ./$(DEPDIR)/tst-test-result-action.Po + -rm -f ./$(DEPDIR)/tst-test-result-execute.Po + -rm -f ./$(DEPDIR)/tst-test-script-compile.Po + -rm -f ./$(DEPDIR)/tst-test-script-run.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-local clean-noinstPROGRAMS \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +clean-local: + -rm -rf test.out.* + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/testsuite/cmd-test-binary.c b/pigeonhole/src/testsuite/cmd-test-binary.c new file mode 100644 index 0000000..6f810bd --- /dev/null +++ b/pigeonhole/src/testsuite/cmd-test-binary.c @@ -0,0 +1,208 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-dump.h" + +#include "testsuite-common.h" +#include "testsuite-binary.h" +#include "testsuite-script.h" + +/* + * Commands + */ + +static bool cmd_test_binary_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_test_binary_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +/* Test_binary_load command + * + * Syntax: + * test_binary_load <binary-name: string> + */ + +const struct sieve_command_def cmd_test_binary_load = { + .identifier = "test_binary_load", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_test_binary_validate, + .generate = cmd_test_binary_generate +}; + +/* Test_binary_save command + * + * Syntax: + * test_binary_save <binary-name: string> + */ + +const struct sieve_command_def cmd_test_binary_save = { + .identifier = "test_binary_save", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_test_binary_validate, + .generate = cmd_test_binary_generate, +}; + +/* + * Operations + */ + +static bool cmd_test_binary_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_test_binary_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +/* test_binary_create operation */ + +const struct sieve_operation_def test_binary_load_operation = { + .mnemonic = "TEST_BINARY_LOAD", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_BINARY_LOAD, + .dump = cmd_test_binary_operation_dump, + .execute = cmd_test_binary_operation_execute +}; + +/* test_binary_delete operation */ + +const struct sieve_operation_def test_binary_save_operation = { + .mnemonic = "TEST_BINARY_SAVE", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_BINARY_SAVE, + .dump = cmd_test_binary_operation_dump, + .execute = cmd_test_binary_operation_execute +}; + +/* + * Validation + */ + +static bool cmd_test_binary_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "binary-name", 1, SAAT_STRING) ) { + return FALSE; + } + + return sieve_validator_argument_activate(valdtr, cmd, arg, FALSE); +} + +/* + * Code generation + */ + +static bool cmd_test_binary_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + /* Emit operation */ + if ( sieve_command_is(cmd, cmd_test_binary_load) ) + sieve_operation_emit(cgenv->sblock, cmd->ext, &test_binary_load_operation); + else if ( sieve_command_is(cmd, cmd_test_binary_save) ) + sieve_operation_emit(cgenv->sblock, cmd->ext, &test_binary_save_operation); + else + i_unreached(); + + /* Generate arguments */ + if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) + return FALSE; + + return TRUE; +} + +/* + * Code dump + */ + +static bool cmd_test_binary_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "%s:", sieve_operation_mnemonic(denv->oprtn)); + + sieve_code_descend(denv); + + return sieve_opr_string_dump(denv, address, "binary-name"); +} + +/* + * Intepretation + */ + +static int cmd_test_binary_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_operation *oprtn = renv->oprtn; + string_t *binary_name = NULL; + int ret; + + /* + * Read operands + */ + + /* Binary Name */ + + if ( (ret=sieve_opr_string_read(renv, address, "binary-name", &binary_name)) + <= 0 ) + return ret; + + /* + * Perform operation + */ + + if ( sieve_operation_is(oprtn, test_binary_load_operation) ) { + struct sieve_binary *sbin = testsuite_binary_load(str_c(binary_name)); + + if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) { + sieve_runtime_trace(renv, 0, "testsuite: test_binary_load command"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace(renv, 0, "load binary `%s'", str_c(binary_name)); + } + + if ( sbin != NULL ) { + testsuite_script_set_binary(renv, sbin); + + sieve_binary_unref(&sbin); + } else { + e_error(testsuite_sieve_instance->event, + "failed to load binary %s", str_c(binary_name)); + return SIEVE_EXEC_FAILURE; + } + + } else if ( sieve_operation_is(oprtn, test_binary_save_operation) ) { + struct sieve_binary *sbin = testsuite_script_get_binary(renv); + + if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) { + sieve_runtime_trace(renv, 0, "testsuite: test_binary_save command"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace(renv, 0, "save binary `%s'", str_c(binary_name)); + } + + if ( sbin != NULL ) + testsuite_binary_save(sbin, str_c(binary_name)); + else { + e_error(testsuite_sieve_instance->event, + "no compiled binary to save as %s", + str_c(binary_name)); + return SIEVE_EXEC_FAILURE; + } + } else { + i_unreached(); + } + + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/testsuite/cmd-test-config.c b/pigeonhole/src/testsuite/cmd-test-config.c new file mode 100644 index 0000000..c1399b0 --- /dev/null +++ b/pigeonhole/src/testsuite/cmd-test-config.c @@ -0,0 +1,504 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-settings.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-dump.h" + +#include "testsuite-common.h" +#include "testsuite-settings.h" + +/* + * Commands + */ + +static bool +cmd_test_config_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +/* Test_config_set command + * + * Syntax: + * test_config_set <setting: string> <value: string> + */ + +static bool +cmd_test_config_set_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd); + +const struct sieve_command_def cmd_test_config_set = { + .identifier = "test_config_set", + .type = SCT_COMMAND, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_test_config_set_validate, + .generate = cmd_test_config_generate +}; + +/* Test_config_unset command + * + * Syntax: + * test_config_unset <setting: string> + */ + +static bool +cmd_test_config_unset_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd); + +const struct sieve_command_def cmd_test_config_unset = { + .identifier = "test_config_unset", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_test_config_unset_validate, + .generate = cmd_test_config_generate, +}; + +/* Test_config_reload command + * + * Syntax: + * test_config_reload [:extension <extension: string>] + */ + +static bool +cmd_test_config_reload_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); + +const struct sieve_command_def cmd_test_config_reload = { + .identifier = "test_config_reload", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_test_config_reload_registered, + .generate = cmd_test_config_generate +}; + +/* + * Command tags + */ + +/* Forward declarations */ + +static bool +cmd_test_config_reload_validate_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +/* Argument objects */ + +static const struct sieve_argument_def test_config_reload_extension_tag = { + .identifier = "extension", + .validate = cmd_test_config_reload_validate_tag, +}; + +/* Codes for optional arguments */ + +enum cmd_test_config_optional { + OPT_END, + OPT_EXTENSION +}; + +/* + * Operations + */ + +/* Test_config_set operation */ + +static bool +cmd_test_config_set_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_test_config_set_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def test_config_set_operation = { + .mnemonic = "TEST_CONFIG_SET", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_CONFIG_SET, + .dump = cmd_test_config_set_operation_dump, + .execute = cmd_test_config_set_operation_execute +}; + +/* Test_config_unset operation */ + +static bool +cmd_test_config_unset_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_test_config_unset_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def test_config_unset_operation = { + .mnemonic = "TEST_CONFIG_UNSET", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_CONFIG_UNSET, + .dump = cmd_test_config_unset_operation_dump, + .execute = cmd_test_config_unset_operation_execute +}; + +/* Test_config_read operation */ + +static bool +cmd_test_config_reload_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_test_config_reload_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def test_config_reload_operation = { + .mnemonic = "TEST_CONFIG_RELOAD", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_CONFIG_RELOAD, + .dump = cmd_test_config_reload_operation_dump, + .execute = cmd_test_config_reload_operation_execute +}; + +/* + * Tag validation + */ + +static bool +cmd_test_config_reload_validate_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :extension <extension: string> + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING, TRUE)) + return FALSE; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Command registration + */ + +static bool +cmd_test_config_reload_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &test_config_reload_extension_tag, + OPT_EXTENSION); + return TRUE; +} + +/* + * Command validation + */ + +static bool +cmd_test_config_set_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + /* Check syntax: + * <setting: string> <value: string> + */ + + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "setting", + 1, SAAT_STRING)) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE)) + return FALSE; + + arg = sieve_ast_argument_next(arg); + + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "value", 2, + SAAT_STRING)) + return FALSE; + + return sieve_validator_argument_activate(valdtr, cmd, arg, FALSE); +} + +static bool +cmd_test_config_unset_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + /* Check syntax: + * <setting: string> + */ + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "setting", 1, + SAAT_STRING)) + return FALSE; + + return sieve_validator_argument_activate(valdtr, cmd, arg, FALSE); +} + +/* + * Code generation + */ + +static bool +cmd_test_config_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + if (sieve_command_is(cmd, cmd_test_config_set)) { + sieve_operation_emit(cgenv->sblock, cmd->ext, + &test_config_set_operation); + } else if (sieve_command_is(cmd, cmd_test_config_unset)) { + sieve_operation_emit(cgenv->sblock, cmd->ext, + &test_config_unset_operation); + } else if (sieve_command_is(cmd, cmd_test_config_reload)) { + sieve_operation_emit(cgenv->sblock, cmd->ext, + &test_config_reload_operation); + } else { + i_unreached(); + } + + /* Generate arguments */ + if (!sieve_generate_arguments(cgenv, cmd, NULL)) + return FALSE; + return TRUE; +} + +/* + * Code dump + */ + +static bool +cmd_test_config_set_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_code_dumpf(denv, "TEST_CONFIG_SET:"); + + sieve_code_descend(denv); + + return (sieve_opr_string_dump(denv, address, "setting") && + sieve_opr_string_dump(denv, address, "value")); +} + +static bool +cmd_test_config_unset_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_code_dumpf(denv, "TEST_CONFIG_UNSET:"); + + sieve_code_descend(denv); + + return sieve_opr_string_dump(denv, address, "setting"); +} + +static bool +cmd_test_config_reload_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "TEST_CONFIG_RELOAD:"); + sieve_code_descend(denv); + + /* Dump optional operands */ + + for (;;) { + int opt; + bool opok = TRUE; + + if ((opt = sieve_opr_optional_dump(denv, address, + &opt_code)) < 0) + return FALSE; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_EXTENSION: + opok = sieve_opr_string_dump(denv, address, + "extensions"); + break; + default: + opok = FALSE; + break; + } + + if (!opok) + return FALSE; + } + + return TRUE; +} + +/* + * Interpretation + */ + +static int +cmd_test_config_set_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + string_t *setting; + string_t *value; + int ret; + + /* + * Read operands + */ + + /* Setting */ + if ((ret = sieve_opr_string_read(renv, address, "setting", + &setting)) <= 0) + return ret; + + /* Value */ + if ((ret = sieve_opr_string_read(renv, address, "value", + &value)) <= 0) + return ret; + + /* + * Perform operation + */ + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) { + sieve_runtime_trace( + renv, 0, "testsuite: test_config_set command"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace( + renv, 0, "set config `%s' = `%s'", + str_c(setting), str_c(value)); + } + + testsuite_setting_set(str_c(setting), str_c(value)); + + return SIEVE_EXEC_OK; +} + +static int +cmd_test_config_unset_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + string_t *setting; + int ret; + + /* + * Read operands + */ + + /* Setting */ + if ((ret = sieve_opr_string_read(renv, address, "setting", + &setting)) <= 0) + return ret; + + /* + * Perform operation + */ + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) { + sieve_runtime_trace( + renv, 0, "testsuite: test_config_unset command"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace( + renv, 0, "unset config `%s'", str_c(setting)); + } + + testsuite_setting_unset(str_c(setting)); + + return SIEVE_EXEC_OK; +} + +static int +cmd_test_config_reload_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_extension *ext; + int opt_code = 0; + string_t *extension = NULL; + int ret; + + /* + * Read operands + */ + + /* Optional operands */ + for (;;) { + int opt; + + if ((opt = sieve_opr_optional_read(renv, address, + &opt_code)) < 0) + return SIEVE_EXEC_BIN_CORRUPT; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_EXTENSION: + ret = sieve_opr_string_read(renv, address, "extension", + &extension); + break; + default: + sieve_runtime_trace_error( + renv, "unknown optional operand"); + ret = SIEVE_EXEC_BIN_CORRUPT; + } + + if (ret <= 0) + return ret; + } + + /* + * Perform operation + */ + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) { + sieve_runtime_trace( + renv, 0, "testsuite: test_config_reload command"); + sieve_runtime_trace_descend(renv); + } + + if (extension == NULL) { + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) { + sieve_runtime_trace( + renv, 0, + "reload configuration for sieve engine"); + } + + sieve_settings_load(eenv->svinst); + } else { + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) { + sieve_runtime_trace( + renv, 0, + "reload configuration for extension `%s'", + str_c(extension)); + } + + ext = sieve_extension_get_by_name(eenv->svinst, + str_c(extension)); + if (ext == NULL) { + return testsuite_test_failf( + renv, "test_config_reload: " + "unknown extension '%s'", str_c(extension)); + } + sieve_extension_reload(ext); + } + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/testsuite/cmd-test-fail.c b/pigeonhole/src/testsuite/cmd-test-fail.c new file mode 100644 index 0000000..346c187 --- /dev/null +++ b/pigeonhole/src/testsuite/cmd-test-fail.c @@ -0,0 +1,129 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-dump.h" + +#include "testsuite-common.h" + +/* + * Test_fail command + * + * Syntax: + * test_fail <reason: string> + */ + +static bool +cmd_test_fail_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd); +static bool +cmd_test_fail_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def cmd_test_fail = { + .identifier = "test_fail", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_test_fail_validate, + .generate = cmd_test_fail_generate, +}; + +/* + * Test operation + */ + +static bool +cmd_test_fail_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_test_fail_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def test_fail_operation = { + .mnemonic = "TEST_FAIL", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_FAIL, + .dump = cmd_test_fail_operation_dump, + .execute = cmd_test_fail_operation_execute, +}; + +/* + * Validation + */ + +static bool +cmd_test_fail_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "reason", 1, + SAAT_STRING)) + return FALSE; + + return sieve_validator_argument_activate(valdtr, cmd, arg, FALSE); +} + +/* + * Code generation + */ + +static bool +cmd_test_fail_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &test_fail_operation); + + /* Generate arguments */ + if (!sieve_generate_arguments(cgenv, cmd, NULL)) + return FALSE; + + return TRUE; +} + +/* + * Code dump + */ + +static bool +cmd_test_fail_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_code_dumpf(denv, "TEST_FAIL:"); + sieve_code_descend(denv); + + if (!sieve_opr_string_dump(denv, address, "reason")) + return FALSE; + + return TRUE; +} + +/* + * Intepretation + */ + +static int +cmd_test_fail_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + string_t *reason; + int ret; + + ret = sieve_opr_string_read(renv, address, "reason", &reason); + if (ret <= 0) + return ret; + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "testsuite: " + "test_fail command; FAIL current test"); + + return testsuite_test_fail(renv, reason); +} diff --git a/pigeonhole/src/testsuite/cmd-test-imap-metadata.c b/pigeonhole/src/testsuite/cmd-test-imap-metadata.c new file mode 100644 index 0000000..1c5e2a9 --- /dev/null +++ b/pigeonhole/src/testsuite/cmd-test-imap-metadata.c @@ -0,0 +1,284 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-dump.h" + +#include "testsuite-common.h" +#include "testsuite-mailstore.h" + +/* + * Commands + */ + +static bool cmd_test_imap_metadata_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool cmd_test_imap_metadata_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_test_imap_metadata_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +/* Test_mailbox_create command + * + * Syntax: + * test_imap_metadata_set + * <mailbox: string> <annotation: string> <value:string> + */ + +const struct sieve_command_def cmd_test_imap_metadata_set = { + .identifier = "test_imap_metadata_set", + .type = SCT_COMMAND, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_test_imap_metadata_registered, + .validate = cmd_test_imap_metadata_validate, + .generate = cmd_test_imap_metadata_generate, +}; + +/* + * Command tags + */ + +static bool cmd_test_imap_metadata_validate_mailbox_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +static const struct sieve_argument_def test_imap_metadata_mailbox_tag = { + .identifier = "mailbox", + .validate = cmd_test_imap_metadata_validate_mailbox_tag +}; + +/* + * Operations + */ + +static bool cmd_test_imap_metadata_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_test_imap_metadata_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +/* Test_mailbox_create operation */ + +const struct sieve_operation_def test_imap_metadata_set_operation = { + .mnemonic = "TEST_IMAP_METADATA_SET", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_IMAP_METADATA_SET, + .dump = cmd_test_imap_metadata_operation_dump, + .execute = cmd_test_imap_metadata_operation_execute +}; + +/* Codes for optional arguments */ + +enum cmd_vacation_optional { + OPT_END, + OPT_MAILBOX +}; + +/* + * Tag validation + */ + +static bool cmd_test_imap_metadata_validate_mailbox_tag +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + + /* Delete this tag */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + /* Check syntax: + * :mailbox string + */ + if ( !sieve_validate_tag_parameter + (valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING, FALSE) ) { + return FALSE; + } + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + return TRUE; +} + +/* + * Command registration + */ + +static bool cmd_test_imap_metadata_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &test_imap_metadata_mailbox_tag, OPT_MAILBOX); + return TRUE; +} + + +/* + * Validation + */ + +static bool cmd_test_imap_metadata_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "annotation", 2, SAAT_STRING) ) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE)) + return FALSE; + + arg = sieve_ast_argument_next(arg); + + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "value", 3, SAAT_STRING) ) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE)) + return FALSE; + return TRUE; +} + +/* + * Code generation + */ + +static bool cmd_test_imap_metadata_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + /* Emit operation */ + if ( sieve_command_is(cmd, cmd_test_imap_metadata_set) ) + sieve_operation_emit + (cgenv->sblock, cmd->ext, &test_imap_metadata_set_operation); + else + i_unreached(); + + /* Generate arguments */ + if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) + return FALSE; + return TRUE; +} + +/* + * Code dump + */ + +static bool cmd_test_imap_metadata_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "%s:", sieve_operation_mnemonic(denv->oprtn)); + sieve_code_descend(denv); + + /* Dump optional operands */ + + for (;;) { + int opt; + bool opok = TRUE; + + if ( (opt=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_MAILBOX: + opok = sieve_opr_string_dump(denv, address, "mailbox"); + break; + default: + return FALSE; + } + + if ( !opok ) return FALSE; + } + + return + ( sieve_opr_string_dump(denv, address, "annotation") && + sieve_opr_string_dump(denv, address, "value") ); +} + +/* + * Intepretation + */ + +static int cmd_test_imap_metadata_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_operation *oprtn = renv->oprtn; + int opt_code = 0; + string_t *mailbox = NULL, *annotation = NULL, *value = NULL; + int ret; + + /* + * Read operands + */ + + /* Optional operands */ + + for (;;) { + int opt; + + if ( (opt=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_MAILBOX: + ret = sieve_opr_string_read(renv, address, "mailbox", &mailbox); + break; + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + ret = SIEVE_EXEC_BIN_CORRUPT; + } + + if ( ret <= 0 ) return ret; + } + + /* Fixed operands */ + + if ( (ret=sieve_opr_string_read + (renv, address, "annotation", &annotation)) <= 0 ) + return ret; + if ( (ret=sieve_opr_string_read + (renv, address, "value", &value)) <= 0 ) + return ret; + + /* + * Perform operation + */ + + if ( sieve_operation_is(oprtn, test_imap_metadata_set_operation) ) { + if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) { + sieve_runtime_trace(renv, 0, "testsuite/test_imap_metadata_set command"); + sieve_runtime_trace_descend(renv); + if (mailbox == NULL) { + sieve_runtime_trace(renv, 0, + "set server annotation `%s'", str_c(annotation)); + } else { + sieve_runtime_trace(renv, 0, + "set annotation `%s' for mailbox `%s'", + str_c(annotation), str_c(mailbox)); + } + } + + if (testsuite_mailstore_set_imap_metadata + (( mailbox == NULL ? NULL : str_c(mailbox) ), + str_c(annotation), str_c(value)) < 0) + return SIEVE_EXEC_FAILURE; + } + + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/testsuite/cmd-test-mailbox.c b/pigeonhole/src/testsuite/cmd-test-mailbox.c new file mode 100644 index 0000000..b5d946c --- /dev/null +++ b/pigeonhole/src/testsuite/cmd-test-mailbox.c @@ -0,0 +1,261 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-dump.h" +#include "sieve-actions.h" + +#include "testsuite-common.h" +#include "testsuite-mailstore.h" + +/* + * Commands + */ + +static bool +cmd_test_mailbox_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd); +static bool +cmd_test_mailbox_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +/* Test_mailbox_create command + * + * Syntax: + * test_mailbox_create <mailbox: string> + */ + +const struct sieve_command_def cmd_test_mailbox_create = { + .identifier = "test_mailbox_create", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_test_mailbox_validate, + .generate = cmd_test_mailbox_generate, +}; + +/* Test_mailbox_delete command + * + * Syntax: + * test_mailbox_create <mailbox: string> + */ + +const struct sieve_command_def cmd_test_mailbox_delete = { + .identifier = "test_mailbox_delete", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_test_mailbox_validate, + .generate = cmd_test_mailbox_generate, +}; + +/* + * Operations + */ + +static bool +cmd_test_mailbox_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_test_mailbox_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +/* Test_mailbox_create operation */ + +const struct sieve_operation_def test_mailbox_create_operation = { + .mnemonic = "TEST_MAILBOX_CREATE", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_MAILBOX_CREATE, + .dump = cmd_test_mailbox_operation_dump, + .execute = cmd_test_mailbox_operation_execute, +}; + +/* Test_mailbox_delete operation */ + +const struct sieve_operation_def test_mailbox_delete_operation = { + .mnemonic = "TEST_MAILBOX_DELETE", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_MAILBOX_DELETE, + .dump = cmd_test_mailbox_operation_dump, + .execute = cmd_test_mailbox_operation_execute, +}; + +/* + * Validation + */ + +static bool +cmd_test_mailbox_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "mailbox", 1, + SAAT_STRING)) + return FALSE; + + if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) ) + return FALSE; + + /* Check name validity when folder argument is not a variable */ + if ( sieve_argument_is_string_literal(arg) ) { + const char *folder = sieve_ast_argument_strc(arg), *error; + + if ( !sieve_mailbox_check_name(folder, &error) ) { + sieve_command_validate_error( + valdtr, cmd, "%s command: " + "invalid mailbox `%s' specified: %s", + sieve_command_identifier(cmd), + str_sanitize(folder, 256), error); + return FALSE; + } + } + + return TRUE; +} + +/* + * Code generation + */ + +static bool +cmd_test_mailbox_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + /* Emit operation */ + if (sieve_command_is(cmd, cmd_test_mailbox_create)) { + sieve_operation_emit(cgenv->sblock, cmd->ext, + &test_mailbox_create_operation); + } else if (sieve_command_is(cmd, cmd_test_mailbox_delete)) { + sieve_operation_emit(cgenv->sblock, cmd->ext, + &test_mailbox_delete_operation); + } else { + i_unreached(); + } + + /* Generate arguments */ + if (!sieve_generate_arguments(cgenv, cmd, NULL)) + return FALSE; + + return TRUE; +} + +/* + * Code dump + */ + +static bool +cmd_test_mailbox_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_code_dumpf(denv, "%s:", sieve_operation_mnemonic(denv->oprtn)); + + sieve_code_descend(denv); + + return sieve_opr_string_dump(denv, address, "mailbox"); +} + +/* + * Intepretation + */ + +static const char * +cmd_test_mailbox_get_command_name(const struct sieve_operation *oprtn) +{ + if (sieve_operation_is(oprtn, test_mailbox_create_operation)) + return "test_mailbox_create"; + if (sieve_operation_is(oprtn, test_mailbox_delete_operation)) + return "test_mailbox_delete"; + + i_unreached(); +} + +static int +cmd_test_mailbox_create_execute(const struct sieve_runtime_env *renv, + const char *mailbox) +{ + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) { + sieve_runtime_trace( + renv, 0, + "testsuite/test_mailbox_create command"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace( + renv, 0, "create mailbox `%s'", mailbox); + } + + testsuite_mailstore_mailbox_create(renv, mailbox); + return SIEVE_EXEC_OK; +} + +static int +cmd_test_mailbox_delete_execute(const struct sieve_runtime_env *renv, + const char *mailbox) +{ + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) { + sieve_runtime_trace( + renv, 0, + "testsuite/test_mailbox_delete command"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace( + renv, 0, "delete mailbox `%s'", mailbox); + } + + /* FIXME: implement */ + return testsuite_test_failf( + renv, "test_mailbox_delete: NOT IMPLEMENTED"); +} + +static int +cmd_test_mailbox_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_operation *oprtn = renv->oprtn; + string_t *mailbox = NULL; + const char *error; + int ret; + + /* + * Read operands + */ + + /* Mailbox */ + + ret = sieve_opr_string_read(renv, address, "mailbox", &mailbox); + if (ret <= 0) + return ret; + + if (!sieve_mailbox_check_name(str_c(mailbox), &error)) { + sieve_runtime_error( + renv, NULL, "%s command: " + "invalid mailbox `%s' specified: %s", + cmd_test_mailbox_get_command_name(oprtn), + str_c(mailbox), error); + return SIEVE_EXEC_FAILURE; + } + + /* + * Perform operation + */ + + if (sieve_operation_is(oprtn, test_mailbox_create_operation)) + ret = cmd_test_mailbox_create_execute(renv, str_c(mailbox)); + else if (sieve_operation_is(oprtn, test_mailbox_delete_operation)) + ret = cmd_test_mailbox_delete_execute(renv, str_c(mailbox)); + else + i_unreached(); + + return ret; +} diff --git a/pigeonhole/src/testsuite/cmd-test-message.c b/pigeonhole/src/testsuite/cmd-test-message.c new file mode 100644 index 0000000..ff36704 --- /dev/null +++ b/pigeonhole/src/testsuite/cmd-test-message.c @@ -0,0 +1,569 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" +#include "istream.h" +#include "mail-storage.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-message.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-dump.h" + +#include "testsuite-common.h" +#include "testsuite-smtp.h" +#include "testsuite-mailstore.h" + +/* + * Commands + */ + +/* Test_message command + * + * Syntax: + * test_message ( :smtp / :mailbox <mailbox: string> ) <index: number> + */ + +static bool +cmd_test_message_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool +cmd_test_message_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd); +static bool +cmd_test_message_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def cmd_test_message = { + .identifier = "test_message", + .type = SCT_HYBRID, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_test_message_registered, + .validate = cmd_test_message_validate, + .generate = cmd_test_message_generate, +}; + +/* Test_message_print command + * + * Syntax: + * test_message_print + */ + +static bool +cmd_test_message_print_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd); + +const struct sieve_command_def cmd_test_message_print = { + .identifier = "test_message_print", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .generate = cmd_test_message_print_generate, +}; + +/* + * Operations + */ + +/* Test_message_smtp operation */ + +static bool +cmd_test_message_smtp_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_test_message_smtp_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def test_message_smtp_operation = { + .mnemonic = "TEST_MESSAGE_SMTP", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_MESSAGE_SMTP, + .dump = cmd_test_message_smtp_operation_dump, + .execute = cmd_test_message_smtp_operation_execute, +}; + +/* Test_message_mailbox operation */ + +static bool +cmd_test_message_mailbox_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_test_message_mailbox_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def test_message_mailbox_operation = { + .mnemonic = "TEST_MESSAGE_MAILBOX", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_MESSAGE_MAILBOX, + .dump = cmd_test_message_mailbox_operation_dump, + .execute = cmd_test_message_mailbox_operation_execute, +}; + +/* Test_message_print operation */ + +static bool +cmd_test_message_print_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_test_message_print_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def test_message_print_operation = { + .mnemonic = "TEST_MESSAGE_PRINT", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_MESSAGE_PRINT, + .dump = cmd_test_message_print_operation_dump, + .execute = cmd_test_message_print_operation_execute, +}; + +/* + * Compiler context data + */ + +enum test_message_source { + MSG_SOURCE_SMTP, + MSG_SOURCE_MAILBOX, + MSG_SOURCE_LAST, +}; + +const struct sieve_operation_def *test_message_operations[] = { + &test_message_smtp_operation, + &test_message_mailbox_operation, +}; + +struct cmd_test_message_context_data { + enum test_message_source msg_source; + const char *folder; +}; + +#define CMD_TEST_MESSAGE_ERROR_DUP_TAG \ + "exactly one of the ':smtp' or ':folder' tags must be specified " \ + "for the test_message command, but more were found" + +/* + * Command tags + */ + +static bool +cmd_test_message_validate_smtp_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +cmd_test_message_validate_folder_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +static const struct sieve_argument_def test_message_smtp_tag = { + .identifier = "smtp", + .validate = cmd_test_message_validate_smtp_tag, +}; + +static const struct sieve_argument_def test_message_folder_tag = { + .identifier = "folder", + .validate = cmd_test_message_validate_folder_tag, +}; + +static bool +cmd_test_message_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + /* Register our tags */ + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &test_message_folder_tag, 0); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &test_message_smtp_tag, 0); + return TRUE; +} + +static struct cmd_test_message_context_data * +cmd_test_message_validate_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct cmd_test_message_context_data *ctx_data = + (struct cmd_test_message_context_data *)cmd->data; + + if (ctx_data != NULL) { + sieve_argument_validate_error(valdtr, *arg, + CMD_TEST_MESSAGE_ERROR_DUP_TAG); + return NULL; + } + + ctx_data = p_new(sieve_command_pool(cmd), + struct cmd_test_message_context_data, 1); + cmd->data = ctx_data; + + /* Delete this tag */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + return ctx_data; +} + +static bool +cmd_test_message_validate_smtp_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct cmd_test_message_context_data *ctx_data = + cmd_test_message_validate_tag(valdtr, arg, cmd); + + /* Return value is NULL on error */ + if (ctx_data == NULL) + return FALSE; + + /* Assign chosen message source */ + ctx_data->msg_source = MSG_SOURCE_SMTP; + + return TRUE; +} + +static bool +cmd_test_message_validate_folder_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct cmd_test_message_context_data *ctx_data = + cmd_test_message_validate_tag(valdtr, arg, cmd); + + /* Return value is NULL on error */ + if (ctx_data == NULL) + return FALSE; + + /* Assign chose message source */ + ctx_data->msg_source = MSG_SOURCE_MAILBOX; + + /* Check syntax: + * :folder string + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING, FALSE)) { + return FALSE; + } + + /* Check name validity when folder argument is not a variable */ + if ( sieve_argument_is_string_literal(*arg) ) { + const char *folder = sieve_ast_argument_strc(*arg), *error; + + if ( !sieve_mailbox_check_name(folder, &error) ) { + sieve_command_validate_error( + valdtr, cmd, "%s command: " + "invalid mailbox `%s' specified: %s", + sieve_command_identifier(cmd), + str_sanitize(folder, 256), error); + return FALSE; + } + } + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Validation + */ + +static bool +cmd_test_message_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + if (cmd->data == NULL) { + sieve_command_validate_error( + valdtr, cmd, + "the test_message command requires either " + "the :smtp or the :mailbox tag to be specified"); + return FALSE; + } + + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "index", 1, + SAAT_NUMBER)) + return FALSE; + + return sieve_validator_argument_activate(valdtr, cmd, arg, FALSE); +} + +/* + * Code generation + */ + +static bool +cmd_test_message_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + struct cmd_test_message_context_data *ctx_data = + (struct cmd_test_message_context_data *)cmd->data; + + i_assert(ctx_data->msg_source < MSG_SOURCE_LAST); + + /* Emit operation */ + sieve_operation_emit(cgenv->sblock, cmd->ext, + test_message_operations[ctx_data->msg_source]); + + /* Emit is_test flag */ + sieve_binary_emit_byte(cgenv->sblock, + (cmd->ast_node->type == SAT_TEST ? 1 : 0)); + + /* Generate arguments */ + if (!sieve_generate_arguments(cgenv, cmd, NULL)) + return FALSE; + + return TRUE; +} + +static bool +cmd_test_message_print_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + /* Emit operation */ + sieve_operation_emit(cgenv->sblock, cmd->ext, + &test_message_print_operation); + return TRUE; +} + +/* + * Code dump + */ + +static bool +cmd_test_message_smtp_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + unsigned int is_test; + + if (!sieve_binary_read_byte(denv->sblock, address, &is_test)) + return FALSE; + + sieve_code_dumpf(denv, "TEST_MESSAGE_SMTP (%s):", + (is_test > 0 ? "TEST" : "COMMAND")); + + sieve_code_descend(denv); + + return sieve_opr_number_dump(denv, address, "index"); +} + +static bool +cmd_test_message_mailbox_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + unsigned int is_test; + + if (!sieve_binary_read_byte(denv->sblock, address, &is_test)) + return FALSE; + + sieve_code_dumpf(denv, "TEST_MESSAGE_MAILBOX (%s):", + (is_test > 0 ? "TEST" : "COMMAND")); + + sieve_code_descend(denv); + + return (sieve_opr_string_dump(denv, address, "folder") && + sieve_opr_number_dump(denv, address, "index")); +} + +static bool +cmd_test_message_print_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address ATTR_UNUSED) +{ + sieve_code_dumpf(denv, "TEST_MESSAGE_PRINT"); + + return TRUE; +} + +/* + * Intepretation + */ + +static int +cmd_test_message_smtp_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + sieve_number_t msg_index; + unsigned int is_test = 0; + bool result; + int ret; + + /* + * Read operands + */ + + /* Is test */ + + if (!sieve_binary_read_byte(renv->sblock, address, &is_test)) { + sieve_runtime_trace_error(renv, "invalid is_test flag"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + /* Index */ + + ret = sieve_opr_number_read(renv, address, "index", &msg_index); + if (ret <= 0) + return ret; + + /* + * Perform operation + */ + + if (is_test > 0) { + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_TESTS)) { + sieve_runtime_trace( + renv, 0, "testsuite: test_message test"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace( + renv, 0, + "check and retrieve smtp message [index=%llu]", + (unsigned long long)msg_index); + } + } else { + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) { + sieve_runtime_trace( + renv, 0, "testsuite: test_message command"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace( + renv, 0, + "retrieve smtp message [index=%llu]", + (unsigned long long)msg_index); + } + } + + result = testsuite_smtp_get(renv, msg_index); + + if (is_test > 0) { + sieve_interpreter_set_test_result(renv->interp, result); + return SIEVE_EXEC_OK; + } + + if (!result) { + return testsuite_test_failf( + renv, "no outgoing SMTP message with index %llu", + (unsigned long long)msg_index); + } + + return SIEVE_EXEC_OK; +} + +static int +cmd_test_message_mailbox_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + string_t *folder; + sieve_number_t msg_index; + unsigned int is_test = 0; + bool result; + const char *error; + int ret; + + /* + * Read operands + */ + + /* Is test */ + if (!sieve_binary_read_byte(renv->sblock, address, &is_test)) { + sieve_runtime_trace_error(renv, "invalid is_test flag"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + /* Folder */ + ret = sieve_opr_string_read(renv, address, "folder", &folder); + if (ret <= 0) + return ret; + + /* Index */ + ret = sieve_opr_number_read(renv, address, "index", &msg_index); + if (ret <= 0) + return ret; + + if (!sieve_mailbox_check_name(str_c(folder), &error)) { + return testsuite_test_failf( + renv, "invalid mailbox `%s' specified: %s", + str_c(folder), error); + } + + /* + * Perform operation + */ + + if (is_test > 0) { + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_TESTS)) { + sieve_runtime_trace( + renv, 0, "testsuite: test_message test"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace( + renv, 0, "check and retrieve mailbox message " + "[mailbox=`%s' index=%llu]", + str_c(folder), (unsigned long long)msg_index); + } + } else { + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) { + sieve_runtime_trace( + renv, 0, "testsuite: test_message command"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace( + renv, 0, "retrieve mailbox message " + "[mailbox=`%s' index=%llu]", + str_c(folder), (unsigned long long)msg_index); + } + } + + result = testsuite_mailstore_mail_index(renv, str_c(folder), msg_index); + + if (is_test > 0) { + sieve_interpreter_set_test_result(renv->interp, result); + return SIEVE_EXEC_OK; + } + + if (!result) { + return testsuite_test_failf( + renv, "no message in folder '%s' with index %llu", + str_c(folder), (unsigned long long)msg_index); + } + + return SIEVE_EXEC_OK; +} + +static int +cmd_test_message_print_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + struct mail *mail = sieve_message_get_mail(renv->msgctx); + struct istream *input; + const unsigned char *data; + size_t size; + + if (mail_get_stream(mail, NULL, NULL, &input) < 0) { + sieve_runtime_error(renv, NULL, "test_message_print: " + "failed to read current message"); + return SIEVE_EXEC_OK; + } + + printf("\n--MESSAGE: \n"); + + /* Pipe the message to the outgoing SMTP transport */ + while (i_stream_read_more(input, &data, &size) > 0) { + ssize_t wret; + + wret = write(1, data, size); + if (wret <= 0) + break; + i_stream_skip(input, wret); + } + printf("\n--MESSAGE--\n"); + + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/testsuite/cmd-test-result.c b/pigeonhole/src/testsuite/cmd-test-result.c new file mode 100644 index 0000000..230aa62 --- /dev/null +++ b/pigeonhole/src/testsuite/cmd-test-result.c @@ -0,0 +1,138 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-script.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-dump.h" +#include "sieve.h" + +#include "testsuite-common.h" +#include "testsuite-result.h" +#include "testsuite-message.h" +#include "testsuite-smtp.h" + +/* + * Commands + */ + +static bool +cmd_test_result_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd); + +/* Test_result_reset command + * + * Syntax: + * test_result_reset + */ + +const struct sieve_command_def cmd_test_result_reset = { + .identifier = "test_result_reset", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .generate = cmd_test_result_generate, +}; + +/* Test_result_print command + * + * Syntax: + * test_result_print + */ + +const struct sieve_command_def cmd_test_result_print = { + .identifier = "test_result_print", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .generate = cmd_test_result_generate, +}; + +/* + * Operations + */ + +/* test_result_reset */ + +static int +cmd_test_result_reset_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def test_result_reset_operation = { + .mnemonic = "TEST_RESULT_RESET", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_RESULT_RESET, + .execute = cmd_test_result_reset_operation_execute, +}; + +/* test_result_print */ + +static int +cmd_test_result_print_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def test_result_print_operation = { + .mnemonic = "TEST_RESULT_PRINT", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_RESULT_PRINT, + .execute = cmd_test_result_print_operation_execute, +}; + +/* + * Code generation + */ + +static bool +cmd_test_result_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + if (sieve_command_is(cmd, cmd_test_result_reset)) { + sieve_operation_emit(cgenv->sblock, cmd->ext, + &test_result_reset_operation); + } else if (sieve_command_is(cmd, cmd_test_result_print)) { + sieve_operation_emit(cgenv->sblock, cmd->ext, + &test_result_print_operation); + } else { + i_unreached(); + } + + return TRUE; +} + +/* + * Intepretation + */ + +static int +cmd_test_result_reset_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "testsuite: " + "test_result_reset command; reset script result"); + + testsuite_result_reset(renv); + testsuite_smtp_reset(); + + return SIEVE_EXEC_OK; +} + +static int +cmd_test_result_print_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "testsuite: " + "test_result_print command; print script result "); + + testsuite_result_print(renv); + + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/testsuite/cmd-test-set.c b/pigeonhole/src/testsuite/cmd-test-set.c new file mode 100644 index 0000000..22b51d2 --- /dev/null +++ b/pigeonhole/src/testsuite/cmd-test-set.c @@ -0,0 +1,161 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "ioloop.h" +#include "str-sanitize.h" +#include "istream.h" +#include "istream-header-filter.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-code-dumper.h" +#include "sieve-result.h" + +#include "testsuite-common.h" +#include "testsuite-objects.h" + +#include <stdio.h> + +/* + * Test_set command + * + * Syntax + * test_set <testsuite object (member): string> <value: string> + */ + +static bool cmd_test_set_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_test_set_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + +const struct sieve_command_def cmd_test_set = { + .identifier = "test_set", + .type = SCT_COMMAND, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_test_set_validate, + .generate = cmd_test_set_generate +}; + +/* + * Test_set operation + */ + +static bool cmd_test_set_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_test_set_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def test_set_operation = { + .mnemonic = "TEST_SET", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_SET, + .dump = cmd_test_set_operation_dump, + .execute = cmd_test_set_operation_execute +}; + +/* + * Validation + */ + +static bool cmd_test_set_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + /* Check arguments */ + + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "object", 1, SAAT_STRING) ) { + return FALSE; + } + + if ( !testsuite_object_argument_activate(valdtr, arg, cmd) ) + return FALSE; + + arg = sieve_ast_argument_next(arg); + + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "value", 2, SAAT_STRING) ) { + return FALSE; + } + + return sieve_validator_argument_activate(valdtr, cmd, arg, FALSE); +} + +/* + * Code generation + */ + +static bool cmd_test_set_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &test_set_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool cmd_test_set_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "TEST SET:"); + sieve_code_descend(denv); + + return + testsuite_object_dump(denv, address) && + sieve_opr_string_dump(denv, address, "value"); +} + +/* + * Intepretation + */ + +static int cmd_test_set_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct testsuite_object tobj; + string_t *value; + int member_id; + int ret; + + if ( !testsuite_object_read_member + (renv->sblock, address, &tobj, &member_id) ) { + sieve_runtime_trace_error(renv, "invalid testsuite object member"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( (ret=sieve_opr_string_read(renv, address, "string", &value)) <= 0 ) + return ret; + + if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) { + sieve_runtime_trace(renv, 0, "testsuite: test_set command"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace(renv, 0, + "set test parameter '%s' = \"%s\"", + testsuite_object_member_name(&tobj, member_id), str_c(value)); + } + + if ( tobj.def == NULL || tobj.def->set_member == NULL ) { + sieve_runtime_trace_error(renv, "unimplemented testsuite object"); + return SIEVE_EXEC_FAILURE; + } + + tobj.def->set_member(renv, member_id, value); + return SIEVE_EXEC_OK; +} + + + diff --git a/pigeonhole/src/testsuite/cmd-test.c b/pigeonhole/src/testsuite/cmd-test.c new file mode 100644 index 0000000..c817aed --- /dev/null +++ b/pigeonhole/src/testsuite/cmd-test.c @@ -0,0 +1,208 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-dump.h" + +#include "testsuite-common.h" + +/* + * Test command + * + * Syntax: + * test <test-name: string> <block> + */ + +static bool +cmd_test_validate(struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool +cmd_test_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *md); + +const struct sieve_command_def cmd_test = { + .identifier = "test", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = TRUE, + .block_required = TRUE, + .validate = cmd_test_validate, + .generate = cmd_test_generate, +}; + +/* + * Test operations + */ + +/* Test operation */ + +static bool +cmd_test_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_test_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def test_operation = { + .mnemonic = "TEST", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST, + .dump = cmd_test_operation_dump, + .execute = cmd_test_operation_execute, +}; + +/* Test_finish operation */ + +static int +cmd_test_finish_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def test_finish_operation = { + .mnemonic = "TEST-FINISH", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_FINISH, + .execute = cmd_test_finish_operation_execute, +}; + +/* + * Validation + */ + +static bool +cmd_test_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + /* Check valid command placement */ + if (!sieve_command_is_toplevel(cmd)) { + sieve_command_validate_error( + valdtr, cmd, "tests cannot be nested: test " + "command must be issued at top-level"); + return FALSE; + } + + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "test-name", + 1, SAAT_STRING)) + return FALSE; + + return sieve_validator_argument_activate(valdtr, cmd, arg, FALSE); +} + +/* + * Code generation + */ + +static inline struct testsuite_generator_context * +_get_generator_context(struct sieve_generator *gentr) +{ + return (struct testsuite_generator_context *) + sieve_generator_extension_get_context(gentr, testsuite_ext); +} + +static bool +cmd_test_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + struct testsuite_generator_context *genctx = + _get_generator_context(cgenv->gentr); + + sieve_operation_emit(cgenv->sblock, cmd->ext, &test_operation); + + /* Generate arguments */ + if (!sieve_generate_arguments(cgenv, cmd, NULL)) + return FALSE; + + /* Prepare jumplist */ + sieve_jumplist_reset(genctx->exit_jumps); + sieve_jumplist_add(genctx->exit_jumps, + sieve_binary_emit_offset(cgenv->sblock, 0)); + + /* Test body */ + if (!sieve_generate_block(cgenv, cmd->ast_node)) + return FALSE; + + sieve_operation_emit(cgenv->sblock, cmd->ext, &test_finish_operation); + + /* Resolve exit jumps to this point */ + sieve_jumplist_resolve(genctx->exit_jumps); + + return TRUE; +} + +/* + * Code dump + */ + +static bool +cmd_test_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_size_t tst_begin; + sieve_offset_t tst_end_offset; + + sieve_code_dumpf(denv, "TEST:"); + sieve_code_descend(denv); + + if (!sieve_opr_string_dump(denv, address, "test name")) + return FALSE; + + sieve_code_mark(denv); + tst_begin = *address; + if (!sieve_binary_read_offset(denv->sblock, address, &tst_end_offset)) + return FALSE; + sieve_code_dumpf(denv, "end: %d [%08llx]", + tst_end_offset, + (unsigned long long)tst_begin + tst_end_offset); + + return TRUE; +} + +/* + * Interpretation + */ + +static int +cmd_test_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + sieve_size_t tst_begin, tst_end; + sieve_offset_t tst_end_offset; + string_t *test_name; + int ret; + + ret = sieve_opr_string_read(renv, address, "test name", &test_name); + if (ret <= 0) + return ret; + + tst_begin = *address; + if (!sieve_binary_read_offset(renv->sblock, address, &tst_end_offset)) { + sieve_runtime_trace_error(renv, "invalid end offset"); + return SIEVE_EXEC_BIN_CORRUPT; + } + tst_end = tst_begin + tst_end_offset; + + sieve_runtime_trace_sep(renv); + sieve_runtime_trace(renv, SIEVE_TRLVL_NONE, + "** Testsuite test start: \"%s\" (end: %08llx)", + str_c(test_name), + (unsigned long long)tst_end); + + return testsuite_test_start(renv, test_name, tst_end); +} + +static int +cmd_test_finish_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + sieve_runtime_trace(renv, SIEVE_TRLVL_NONE, "** Testsuite test end"); + sieve_runtime_trace_sep(renv); + + return testsuite_test_succeed(renv, address, NULL); +} diff --git a/pigeonhole/src/testsuite/ext-testsuite.c b/pigeonhole/src/testsuite/ext-testsuite.c new file mode 100644 index 0000000..cb9c92f --- /dev/null +++ b/pigeonhole/src/testsuite/ext-testsuite.c @@ -0,0 +1,175 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension testsuite + * ------------------- + * + * Authors: Stephan Bosch + * Specification: vendor-specific + * (FIXME: provide specification for test authors) + * + */ + +/* + * Purpose: This custom extension is used to add sieve commands and tests that + * act the Sieve engine and on the test suite itself. This practically + * provides the means to completely control and thereby test the Sieve + * compiler and interpreter. This extension transforms the basic Sieve + * language into something much more powerful and suitable to perform + * complex self-test operations. Of course, this extension is only + * available (as vnd.dovecot.testsuite) when the sieve engine is used + * from within the testsuite commandline tool. Test scripts have the + * extension .svtest by convention to distinguish them from any normal + * sieve scripts that may reside in the same directory. + * + * WARNING: Although this code can serve as an example on how to write + * extensions to the Sieve interpreter, it is generally _NOT_ to be + * used as a source for ideas on new Sieve extensions. Many of the + * commands and tests that this extension introduces conflict with the + * goal and the implied restrictions of the Sieve language. These + * restrictions were put in place with good reason. Therefore, do + * _NOT_ export functionality provided by this testsuite extension to + * your custom extensions that are to be put to general use. + */ + +#include <stdio.h> + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "testsuite-common.h" +#include "testsuite-variables.h" +#include "testsuite-arguments.h" + +/* + * Operations + */ + +const struct sieve_operation_def *testsuite_operations[] = { + &test_operation, + &test_finish_operation, + &test_fail_operation, + &test_config_set_operation, + &test_config_unset_operation, + &test_config_reload_operation, + &test_set_operation, + &test_script_compile_operation, + &test_script_run_operation, + &test_multiscript_operation, + &test_error_operation, + &test_result_action_operation, + &test_result_execute_operation, + &test_result_reset_operation, + &test_result_print_operation, + &test_message_smtp_operation, + &test_message_mailbox_operation, + &test_message_print_operation, + &test_mailbox_create_operation, + &test_mailbox_delete_operation, + &test_binary_load_operation, + &test_binary_save_operation, + &test_imap_metadata_set_operation +}; + +/* + * Operands + */ + +const struct sieve_operand_def *testsuite_operands[] = { + &testsuite_object_operand, + &testsuite_substitution_operand, + &testsuite_namespace_operand +}; + +/* + * Extension + */ + +/* Forward declarations */ + +static bool ext_testsuite_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); +static bool ext_testsuite_generator_load + (const struct sieve_extension *ext, const struct sieve_codegen_env *cgenv); +static bool ext_testsuite_interpreter_load + (const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address); +static bool ext_testsuite_binary_load + (const struct sieve_extension *ext, struct sieve_binary *sbin); + +/* Extension object */ + +const struct sieve_extension_def testsuite_extension = { + .name = "vnd.dovecot.testsuite", + .validator_load = ext_testsuite_validator_load, + .generator_load = ext_testsuite_generator_load, + .interpreter_load = ext_testsuite_interpreter_load, + .binary_load = ext_testsuite_binary_load, + SIEVE_EXT_DEFINE_OPERATIONS(testsuite_operations), + SIEVE_EXT_DEFINE_OPERANDS(testsuite_operands) +}; + +/* Extension implementation */ + +static bool ext_testsuite_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + sieve_validator_register_command(valdtr, ext, &cmd_test); + sieve_validator_register_command(valdtr, ext, &cmd_test_fail); + sieve_validator_register_command(valdtr, ext, &cmd_test_config_set); + sieve_validator_register_command(valdtr, ext, &cmd_test_config_unset); + sieve_validator_register_command(valdtr, ext, &cmd_test_config_reload); + sieve_validator_register_command(valdtr, ext, &cmd_test_set); + sieve_validator_register_command(valdtr, ext, &cmd_test_result_print); + sieve_validator_register_command(valdtr, ext, &cmd_test_result_reset); + sieve_validator_register_command(valdtr, ext, &cmd_test_message); + sieve_validator_register_command(valdtr, ext, &cmd_test_message_print); + sieve_validator_register_command(valdtr, ext, &cmd_test_mailbox_create); + sieve_validator_register_command(valdtr, ext, &cmd_test_mailbox_delete); + sieve_validator_register_command(valdtr, ext, &cmd_test_binary_load); + sieve_validator_register_command(valdtr, ext, &cmd_test_binary_save); + sieve_validator_register_command(valdtr, ext, &cmd_test_imap_metadata_set); + + sieve_validator_register_command(valdtr, ext, &tst_test_script_compile); + sieve_validator_register_command(valdtr, ext, &tst_test_script_run); + sieve_validator_register_command(valdtr, ext, &tst_test_multiscript); + sieve_validator_register_command(valdtr, ext, &tst_test_error); + sieve_validator_register_command(valdtr, ext, &tst_test_result_action); + sieve_validator_register_command(valdtr, ext, &tst_test_result_execute); + +/* sieve_validator_argument_override(valdtr, SAT_VAR_STRING, ext, + &testsuite_string_argument);*/ + + testsuite_variables_init(ext, valdtr); + + return testsuite_validator_context_initialize(valdtr); +} + +static bool ext_testsuite_generator_load +(const struct sieve_extension *ext, const struct sieve_codegen_env *cgenv) +{ + return testsuite_generator_context_initialize(cgenv->gentr, ext); +} + +static bool ext_testsuite_interpreter_load +(const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + return testsuite_interpreter_context_initialize(renv->interp, ext); +} + +static bool ext_testsuite_binary_load +(const struct sieve_extension *ext ATTR_UNUSED, struct sieve_binary *sbin ATTR_UNUSED) +{ + return TRUE; +} + + + diff --git a/pigeonhole/src/testsuite/testsuite-arguments.c b/pigeonhole/src/testsuite/testsuite-arguments.c new file mode 100644 index 0000000..f1e17f4 --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-arguments.c @@ -0,0 +1,190 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-ast.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-dump.h" + +#include "testsuite-common.h" +#include "testsuite-substitutions.h" +#include "testsuite-arguments.h" + +#include <ctype.h> + +/* + * Testsuite string argument + */ + +static bool arg_testsuite_string_validate + (struct sieve_validator *validator, struct sieve_ast_argument **arg, + struct sieve_command *context); + +const struct sieve_argument_def testsuite_string_argument = { + .identifier = "@testsuite-string", + .validate = arg_testsuite_string_validate, + .generate = sieve_arg_catenated_string_generate, +}; + +static bool arg_testsuite_string_validate +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + enum { ST_NONE, ST_OPEN, ST_SUBSTITUTION, ST_PARAM, ST_CLOSE } state = + ST_NONE; + pool_t pool = sieve_ast_pool((*arg)->ast); + struct sieve_arg_catenated_string *catstr = NULL; + string_t *str = sieve_ast_argument_str(*arg); + const char *p, *strstart, *substart = NULL; + const char *strval = (const char *) str_data(str); + const char *strend = strval + str_len(str); + bool result = TRUE; + string_t *subs_name = t_str_new(256); + string_t *subs_param = t_str_new(256); + + T_BEGIN { + /* Initialize substitution structure */ + + p = strval; + strstart = p; + while ( result && p < strend ) { + switch ( state ) { + + /* Nothing found yet */ + case ST_NONE: + if ( *p == '%' ) { + substart = p; + state = ST_OPEN; + str_truncate(subs_name, 0); + str_truncate(subs_param, 0); + } + p++; + break; + + /* Got '%' */ + case ST_OPEN: + if ( *p == '{' ) { + state = ST_SUBSTITUTION; + p++; + } else + state = ST_NONE; + break; + + /* Got '%{' */ + case ST_SUBSTITUTION: + state = ST_PARAM; + + while ( *p != '}' && *p != ':' ) { + if ( !i_isalnum(*p) ) { + state = ST_NONE; + break; + } + str_append_c(subs_name, *p); + p++; + } + break; + + /* Got '%{name' */ + case ST_PARAM: + if ( *p == ':' ) { + p++; + while ( *p != '}' ) { + str_append_c(subs_param, *p); + p++; + } + } + state = ST_CLOSE; + break; + + /* Finished parsing param, expecting '}' */ + case ST_CLOSE: + if ( *p == '}' ) { + struct sieve_ast_argument *strarg; + + /* We now know that the substitution is valid */ + + if ( catstr == NULL ) { + catstr = sieve_arg_catenated_string_create(*arg); + } + + /* Add the substring that is before the substitution to the + * variable-string AST. + */ + if ( substart > strstart ) { + string_t *newstr = str_new(pool, substart - strstart); + str_append_data(newstr, strstart, substart - strstart); + + strarg = sieve_ast_argument_string_create_raw + ((*arg)->ast, newstr, (*arg)->source_line); + sieve_arg_catenated_string_add_element(catstr, strarg); + + /* Give other substitution extensions a chance to do their work */ + if ( !sieve_validator_argument_activate_super + (valdtr, cmd, strarg, FALSE) ) { + result = FALSE; + break; + } + } + + strarg = testsuite_substitution_argument_create + (valdtr, (*arg)->ast, (*arg)->source_line, str_c(subs_name), + str_c(subs_param)); + + if ( strarg != NULL ) + sieve_arg_catenated_string_add_element(catstr, strarg); + else { + sieve_argument_validate_error(valdtr, *arg, + "unknown testsuite substitution type '%s'", str_c(subs_name)); + } + + strstart = p + 1; + substart = strstart; + + p++; + } + + /* Finished, reset for the next substitution */ + state = ST_NONE; + } + } + } T_END; + + /* Bail out early if substitution is invalid */ + if ( !result ) return FALSE; + + /* Check whether any substitutions were found */ + if ( catstr == NULL ) { + /* No substitutions in this string, pass it on to any other substution + * extension. + */ + return sieve_validator_argument_activate_super(valdtr, cmd, *arg, TRUE); + } + + /* Add the final substring that comes after the last substitution to the + * variable-string AST. + */ + if ( strend > strstart ) { + struct sieve_ast_argument *strarg; + string_t *newstr = str_new(pool, strend - strstart); + str_append_data(newstr, strstart, strend - strstart); + + strarg = sieve_ast_argument_string_create_raw + ((*arg)->ast, newstr, (*arg)->source_line); + sieve_arg_catenated_string_add_element(catstr, strarg); + + /* Give other substitution extensions a chance to do their work */ + if ( !sieve_validator_argument_activate_super + (valdtr, cmd, strarg, FALSE) ) + return FALSE; + } + + return TRUE; +} diff --git a/pigeonhole/src/testsuite/testsuite-arguments.h b/pigeonhole/src/testsuite/testsuite-arguments.h new file mode 100644 index 0000000..22ab82b --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-arguments.h @@ -0,0 +1,6 @@ +#ifndef TESTSUITE_ARGUMENTS_H +#define TESTSUITE_ARGUMENTS_H + +extern const struct sieve_argument_def testsuite_string_argument; + +#endif diff --git a/pigeonhole/src/testsuite/testsuite-binary.c b/pigeonhole/src/testsuite/testsuite-binary.c new file mode 100644 index 0000000..6c875a7 --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-binary.c @@ -0,0 +1,82 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "mempool.h" +#include "imem.h" +#include "array.h" +#include "strfuncs.h" +#include "unlink-directory.h" + +#include "sieve.h" +#include "sieve-common.h" +#include "sieve-script.h" +#include "sieve-binary.h" +#include "sieve-error.h" + +#include "testsuite-common.h" +#include "testsuite-binary.h" + +#include <sys/stat.h> +#include <sys/types.h> + +/* + * State + */ + +static char *testsuite_binary_tmp = NULL; + +/* + * Initialization + */ + +void testsuite_binary_init(void) +{ + testsuite_binary_tmp = i_strconcat + (testsuite_tmp_dir_get(), "/binaries", NULL); + + if ( mkdir(testsuite_binary_tmp, 0700) < 0 ) { + i_fatal("failed to create temporary directory '%s': %m.", + testsuite_binary_tmp); + } +} + +void testsuite_binary_deinit(void) +{ + const char *error; + + if ( unlink_directory(testsuite_binary_tmp, UNLINK_DIRECTORY_FLAG_RMDIR, &error) < 0 ) { + i_warning("failed to remove temporary directory '%s': %s.", + testsuite_binary_tmp, error); + } + + i_free(testsuite_binary_tmp); +} + +void testsuite_binary_reset(void) +{ + testsuite_binary_init(); + testsuite_binary_deinit(); +} + +/* + * Binary Access + */ + +bool testsuite_binary_save(struct sieve_binary *sbin, const char *name) +{ + return ( sieve_save_as(sbin, t_strdup_printf + ("%s/%s", testsuite_binary_tmp, sieve_binfile_from_name(name)), TRUE, + 0600, NULL) > 0 ); +} + +struct sieve_binary *testsuite_binary_load(const char *name) +{ + struct sieve_instance *svinst = testsuite_sieve_instance; + + return sieve_load(svinst, t_strdup_printf + ("%s/%s", testsuite_binary_tmp, sieve_binfile_from_name(name)), NULL); +} + + + diff --git a/pigeonhole/src/testsuite/testsuite-binary.h b/pigeonhole/src/testsuite/testsuite-binary.h new file mode 100644 index 0000000..0a09d2b --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-binary.h @@ -0,0 +1,17 @@ +#ifndef TESTSUITE_BINARY_H +#define TESTSUITE_BINARY_H + +#include "sieve-common.h" + +void testsuite_binary_init(void); +void testsuite_binary_deinit(void); +void testsuite_binary_reset(void); + +/* + * Binary Access + */ + +bool testsuite_binary_save(struct sieve_binary *sbin, const char *name); +struct sieve_binary *testsuite_binary_load(const char *name); + +#endif diff --git a/pigeonhole/src/testsuite/testsuite-common.c b/pigeonhole/src/testsuite/testsuite-common.c new file mode 100644 index 0000000..269deee --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-common.c @@ -0,0 +1,374 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "string.h" +#include "ostream.h" +#include "hash.h" +#include "mail-storage.h" +#include "env-util.h" +#include "unlink-directory.h" + +#include "mail-raw.h" + +#include "sieve-common.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-commands.h" +#include "sieve-extensions.h" +#include "sieve-binary.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" +#include "sieve-dump.h" + +#include "testsuite-common.h" +#include "testsuite-settings.h" +#include "testsuite-objects.h" +#include "testsuite-log.h" +#include "testsuite-script.h" +#include "testsuite-binary.h" +#include "testsuite-result.h" +#include "testsuite-smtp.h" + +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <time.h> +#include <sys/stat.h> +#include <sys/types.h> + +/* + * Global data + */ + +struct sieve_instance *testsuite_sieve_instance = NULL; +char *testsuite_test_path = NULL; + +/* Test context */ + +static string_t *test_name; +static sieve_size_t test_block_end; +static unsigned int test_index; +static unsigned int test_failures; + +/* Extension */ + +const struct sieve_extension *testsuite_ext; + +/* + * Validator context + */ + +bool testsuite_validator_context_initialize(struct sieve_validator *valdtr) +{ + pool_t pool = sieve_validator_pool(valdtr); + struct testsuite_validator_context *ctx = + p_new(pool, struct testsuite_validator_context, 1); + + /* Setup object registry */ + ctx->object_registrations = + sieve_validator_object_registry_create(valdtr); + testsuite_register_core_objects(ctx); + + sieve_validator_extension_set_context(valdtr, testsuite_ext, ctx); + + return TRUE; +} + +struct testsuite_validator_context * +testsuite_validator_context_get(struct sieve_validator *valdtr) +{ + return (struct testsuite_validator_context *) + sieve_validator_extension_get_context(valdtr, testsuite_ext); +} + +/* + * Generator context + */ + +bool testsuite_generator_context_initialize( + struct sieve_generator *gentr, const struct sieve_extension *this_ext) +{ + pool_t pool = sieve_generator_pool(gentr); + struct sieve_binary_block *sblock = sieve_generator_get_block(gentr); + struct testsuite_generator_context *ctx = + p_new(pool, struct testsuite_generator_context, 1); + + /* Setup exit jumplist */ + ctx->exit_jumps = sieve_jumplist_create(pool, sblock); + + sieve_generator_extension_set_context(gentr, this_ext, ctx); + + return TRUE; +} + +/* + * Interpreter context + */ + +static void +testsuite_interpreter_free(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_interpreter *interp ATTR_UNUSED, + void *context) +{ + struct testsuite_interpreter_context *ctx = + (struct testsuite_interpreter_context *)context; + + sieve_binary_unref(&ctx->compiled_script); +} + +const struct sieve_interpreter_extension testsuite_interpreter_ext = { + .ext_def = &testsuite_extension, + .free = testsuite_interpreter_free, +}; + +bool testsuite_interpreter_context_initialize( + struct sieve_interpreter *interp, const struct sieve_extension *this_ext) +{ + pool_t pool = sieve_interpreter_pool(interp); + struct testsuite_interpreter_context *ctx = + p_new(pool, struct testsuite_interpreter_context, 1); + + sieve_interpreter_extension_register(interp, this_ext, + &testsuite_interpreter_ext, ctx); + return TRUE; +} + +struct testsuite_interpreter_context * +testsuite_interpreter_context_get(struct sieve_interpreter *interp, + const struct sieve_extension *this_ext) +{ + struct testsuite_interpreter_context *ctx = + sieve_interpreter_extension_get_context(interp, this_ext); + + return ctx; +} + +/* + * Test context + */ + +static void testsuite_test_context_init(void) +{ + test_name = str_new(default_pool, 128); + test_block_end = 0; + test_index = 0; + test_failures = 0; +} + +int testsuite_test_start(const struct sieve_runtime_env *renv, + string_t *name, sieve_size_t block_end) +{ + if (test_block_end != 0) { + sieve_runtime_trace_error(renv, "already inside test block"); + return SIEVE_EXEC_BIN_CORRUPT; + } + str_truncate(test_name, 0); + str_append_str(test_name, name); + + test_block_end = block_end; + test_index++; + + return SIEVE_EXEC_OK; +} + +int testsuite_test_fail(const struct sieve_runtime_env *renv, + string_t *reason) +{ + return testsuite_test_fail_cstr(renv, str_c(reason)); +} + +int testsuite_test_failf(const struct sieve_runtime_env *renv, + const char *fmt, ...) +{ + va_list args; + int ret; + + va_start(args, fmt); + ret = testsuite_test_fail_cstr(renv, t_strdup_vprintf(fmt, args)); + va_end(args); + + return ret; +} + +int testsuite_test_fail_cstr(const struct sieve_runtime_env *renv, + const char *reason) +{ + sieve_size_t end = test_block_end; + + if (str_len(test_name) == 0) { + if (reason == NULL || *reason == '\0') + printf("%2d: Test FAILED\n", test_index); + else + printf("%2d: Test FAILED: %s\n", test_index, reason); + } else { + if (reason == NULL || *reason == '\0') { + printf("%2d: Test '%s' FAILED\n", + test_index, str_c(test_name)); + } else { + printf("%2d: Test '%s' FAILED: %s\n", + test_index, str_c(test_name), reason); + } + } + + str_truncate(test_name, 0); + test_block_end = 0; + + test_failures++; + + return sieve_interpreter_program_jump_to(renv->interp, end, FALSE); +} + +void testsuite_testcase_fail(const char *reason) +{ + if (reason == NULL || *reason == '\0') + printf("XX: Test CASE FAILED\n"); + else + printf("XX: Test CASE FAILED: %s\n", reason); + + test_failures++; +} + +int testsuite_test_succeed(const struct sieve_runtime_env *renv, + sieve_size_t *address, string_t *reason) +{ + sieve_size_t end = test_block_end; + int ret; + + if (str_len(test_name) == 0) { + if (reason == NULL || str_len(reason) == 0) + printf("%2d: Test SUCCEEDED\n", test_index); + else { + printf("%2d: Test SUCCEEDED: %s\n", + test_index, str_c(reason)); + } + } else { + if (reason == NULL || str_len(reason) == 0) { + printf("%2d: Test '%s' SUCCEEDED\n", + test_index, str_c(test_name)); + } else { + printf("%2d: Test '%s' SUCCEEDED: %s\n", test_index, + str_c(test_name), str_c(reason)); + } + } + + str_truncate(test_name, 0); + test_block_end = 0; + + if (*address > end) { + sieve_runtime_trace_error( + renv, "invalid test block end offset"); + return SIEVE_EXEC_BIN_CORRUPT; + } else if (*address < end) { + ret = sieve_interpreter_program_jump_to( + renv->interp, end, FALSE); + if (ret <= 0) + return ret; + } + + return SIEVE_EXEC_OK; +} + +static void testsuite_test_context_deinit(void) +{ + str_free(&test_name); +} + +bool testsuite_testcase_result(bool expect_failure) +{ + if (expect_failure) { + if (test_failures < test_index) { + printf("\nFAIL: Only %d of %d tests failed " + "(all expected to fail).\n\n", + test_failures, test_index); + return FALSE; + } + + printf("\nPASS: %d tests failed (expected to fail).\n\n", + (test_index == 0 ? 1 : test_index)); + return TRUE; + } + + if (test_failures > 0) { + printf("\nFAIL: %d of %d tests failed.\n\n", + test_failures, test_index); + return FALSE; + } + + printf("\nPASS: %d tests succeeded.\n\n", test_index); + return TRUE; +} + +/* + * Testsuite temporary directory + */ + +static char *testsuite_tmp_dir; + +static void testsuite_tmp_dir_init(void) +{ + testsuite_tmp_dir = i_strdup_printf("/tmp/dsieve-testsuite.%s.%s", + dec2str(time(NULL)), + dec2str(getpid())); + + if (mkdir(testsuite_tmp_dir, 0700) < 0) { + i_fatal("failed to create temporary directory '%s': %m.", + testsuite_tmp_dir); + } +} + +static void testsuite_tmp_dir_deinit(void) +{ + const char *error; + + if (unlink_directory(testsuite_tmp_dir, + UNLINK_DIRECTORY_FLAG_RMDIR, &error) < 0) + i_warning("failed to remove temporary directory '%s': %s.", + testsuite_tmp_dir, error); + + i_free(testsuite_tmp_dir); +} + +const char *testsuite_tmp_dir_get(void) +{ + return testsuite_tmp_dir; +} + +/* + * Main testsuite init/deinit + */ + +void testsuite_init(struct sieve_instance *svinst, const char *test_path, + bool log_stdout) +{ + testsuite_sieve_instance = svinst; + + testsuite_test_context_init(); + testsuite_log_init(log_stdout); + testsuite_tmp_dir_init(); + + testsuite_script_init(); + testsuite_binary_init(); + testsuite_smtp_init(); + + testsuite_ext = + sieve_extension_register(svinst, &testsuite_extension, TRUE); + + testsuite_test_path = i_strdup(test_path); +} + +void testsuite_deinit(void) +{ + i_free(testsuite_test_path); + + testsuite_smtp_deinit(); + testsuite_binary_deinit(); + testsuite_script_deinit(); + + testsuite_tmp_dir_deinit(); + testsuite_log_deinit(); + testsuite_test_context_deinit(); +} diff --git a/pigeonhole/src/testsuite/testsuite-common.h b/pigeonhole/src/testsuite/testsuite-common.h new file mode 100644 index 0000000..9a40cdd --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-common.h @@ -0,0 +1,193 @@ +#ifndef TESTSUITE_COMMON_H +#define TESTSUITE_COMMON_H + +#include "sieve-common.h" + +#include "sieve-tool.h" + +/* + * Global data + */ + +extern struct sieve_instance *testsuite_sieve_instance; + +extern const struct sieve_extension_def testsuite_extension; + +extern const struct sieve_extension *testsuite_ext; + +extern const struct sieve_script_env *testsuite_scriptenv; + +extern char *testsuite_test_path; + + +/* + * Validator context + */ + +struct testsuite_validator_context { + struct sieve_validator_object_registry *object_registrations; +}; + +bool testsuite_validator_context_initialize(struct sieve_validator *valdtr); +struct testsuite_validator_context * +testsuite_validator_context_get(struct sieve_validator *valdtr); + +/* + * Generator context + */ + +struct testsuite_generator_context { + struct sieve_jumplist *exit_jumps; +}; + +bool testsuite_generator_context_initialize( + struct sieve_generator *gentr, const struct sieve_extension *this_ext); + +/* + * Interpreter context + */ + +struct testsuite_interpreter_context { + struct sieve_binary *compiled_script; +}; + +bool testsuite_interpreter_context_initialize( + struct sieve_interpreter *interp, + const struct sieve_extension *this_ext); +struct testsuite_interpreter_context * +testsuite_interpreter_context_get(struct sieve_interpreter *interp, + const struct sieve_extension *this_ext); + +/* + * Commands + */ + +extern const struct sieve_command_def cmd_test; +extern const struct sieve_command_def cmd_test_fail; +extern const struct sieve_command_def cmd_test_config_set; +extern const struct sieve_command_def cmd_test_config_unset; +extern const struct sieve_command_def cmd_test_config_reload; +extern const struct sieve_command_def cmd_test_set; +extern const struct sieve_command_def cmd_test_result_reset; +extern const struct sieve_command_def cmd_test_result_print; +extern const struct sieve_command_def cmd_test_message; +extern const struct sieve_command_def cmd_test_message_print; +extern const struct sieve_command_def cmd_test_mailbox; +extern const struct sieve_command_def cmd_test_mailbox_create; +extern const struct sieve_command_def cmd_test_mailbox_delete; +extern const struct sieve_command_def cmd_test_binary_load; +extern const struct sieve_command_def cmd_test_binary_save; +extern const struct sieve_command_def cmd_test_imap_metadata_set; + +/* + * Tests + */ + +extern const struct sieve_command_def tst_test_script_compile; +extern const struct sieve_command_def tst_test_script_run; +extern const struct sieve_command_def tst_test_multiscript; +extern const struct sieve_command_def tst_test_error; +extern const struct sieve_command_def tst_test_result_action; +extern const struct sieve_command_def tst_test_result_execute; + +/* + * Operations + */ + +enum testsuite_operation_code { + TESTSUITE_OPERATION_TEST, + TESTSUITE_OPERATION_TEST_FINISH, + TESTSUITE_OPERATION_TEST_FAIL, + TESTSUITE_OPERATION_TEST_CONFIG_SET, + TESTSUITE_OPERATION_TEST_CONFIG_UNSET, + TESTSUITE_OPERATION_TEST_CONFIG_RELOAD, + TESTSUITE_OPERATION_TEST_SET, + TESTSUITE_OPERATION_TEST_SCRIPT_COMPILE, + TESTSUITE_OPERATION_TEST_SCRIPT_RUN, + TESTSUITE_OPERATION_TEST_MULTISCRIPT, + TESTSUITE_OPERATION_TEST_ERROR, + TESTSUITE_OPERATION_TEST_RESULT_ACTION, + TESTSUITE_OPERATION_TEST_RESULT_EXECUTE, + TESTSUITE_OPERATION_TEST_RESULT_RESET, + TESTSUITE_OPERATION_TEST_RESULT_PRINT, + TESTSUITE_OPERATION_TEST_MESSAGE_SMTP, + TESTSUITE_OPERATION_TEST_MESSAGE_MAILBOX, + TESTSUITE_OPERATION_TEST_MESSAGE_PRINT, + TESTSUITE_OPERATION_TEST_MAILBOX_CREATE, + TESTSUITE_OPERATION_TEST_MAILBOX_DELETE, + TESTSUITE_OPERATION_TEST_BINARY_LOAD, + TESTSUITE_OPERATION_TEST_BINARY_SAVE, + TESTSUITE_OPERATION_TEST_IMAP_METADATA_SET +}; + +extern const struct sieve_operation_def test_operation; +extern const struct sieve_operation_def test_finish_operation; +extern const struct sieve_operation_def test_fail_operation; +extern const struct sieve_operation_def test_config_set_operation; +extern const struct sieve_operation_def test_config_unset_operation; +extern const struct sieve_operation_def test_config_reload_operation; +extern const struct sieve_operation_def test_set_operation; +extern const struct sieve_operation_def test_script_compile_operation; +extern const struct sieve_operation_def test_script_run_operation; +extern const struct sieve_operation_def test_multiscript_operation; +extern const struct sieve_operation_def test_error_operation; +extern const struct sieve_operation_def test_result_action_operation; +extern const struct sieve_operation_def test_result_execute_operation; +extern const struct sieve_operation_def test_result_reset_operation; +extern const struct sieve_operation_def test_result_print_operation; +extern const struct sieve_operation_def test_message_smtp_operation; +extern const struct sieve_operation_def test_message_mailbox_operation; +extern const struct sieve_operation_def test_message_print_operation; +extern const struct sieve_operation_def test_mailbox_create_operation; +extern const struct sieve_operation_def test_mailbox_delete_operation; +extern const struct sieve_operation_def test_binary_load_operation; +extern const struct sieve_operation_def test_binary_save_operation; +extern const struct sieve_operation_def test_imap_metadata_set_operation; + +/* + * Operands + */ + +extern const struct sieve_operand_def testsuite_object_operand; +extern const struct sieve_operand_def testsuite_substitution_operand; + +enum testsuite_operand_code { + TESTSUITE_OPERAND_OBJECT, + TESTSUITE_OPERAND_SUBSTITUTION, + TESTSUITE_OPERAND_NAMESPACE +}; + +/* + * Test context + */ + +int testsuite_test_start(const struct sieve_runtime_env *renv, + string_t *name, sieve_size_t block_end); +int testsuite_test_fail(const struct sieve_runtime_env *renv, + string_t *reason); +int testsuite_test_failf(const struct sieve_runtime_env *renv, + const char *fmt, ...) ATTR_FORMAT(2, 3); +int testsuite_test_fail_cstr(const struct sieve_runtime_env *renv, + const char *reason); + +int testsuite_test_succeed(const struct sieve_runtime_env *renv, + sieve_size_t *address, string_t *reason); + +void testsuite_testcase_fail(const char *reason); +bool testsuite_testcase_result(bool expect_failure); + +/* + * Testsuite temporary directory + */ + +const char *testsuite_tmp_dir_get(void); + +/* + * Testsuite init/deinit + */ + +void testsuite_init(struct sieve_instance *svinst, const char *test_path, + bool log_stdout); +void testsuite_deinit(void); + +#endif diff --git a/pigeonhole/src/testsuite/testsuite-log.c b/pigeonhole/src/testsuite/testsuite-log.c new file mode 100644 index 0000000..d06b744 --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-log.c @@ -0,0 +1,319 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-error-private.h" + +#include "testsuite-common.h" +#include "testsuite-log.h" + +/* + * Configuration + */ + +bool _testsuite_log_stdout = FALSE; + +/* + * Testsuite log error handlers + */ + +struct sieve_error_handler *testsuite_log_ehandler = NULL; +struct sieve_error_handler *testsuite_log_main_ehandler = NULL; + +struct _testsuite_log_message { + const char *location; + const char *message; +}; + +static pool_t _testsuite_logmsg_pool = NULL; +ARRAY(struct _testsuite_log_message) _testsuite_log_errors; +ARRAY(struct _testsuite_log_message) _testsuite_log_warnings; +ARRAY(struct _testsuite_log_message) _testsuite_log_messages; + +static inline void +_testsuite_stdout_log(const struct sieve_error_params *params, + const char *prefix, const char *message) +{ + if (_testsuite_log_stdout) { + if (params->location == NULL || *params->location == '\0') { + fprintf(stdout, "LOG: %s: %s\n", + prefix, message); + } else { + fprintf(stdout, "LOG: %s: %s: %s\n", + params->location, prefix, message); + } + } +} + +static void +_testsuite_log(struct sieve_error_handler *ehandler ATTR_UNUSED, + const struct sieve_error_params *params, + enum sieve_error_flags flags ATTR_UNUSED, const char *message) +{ + pool_t pool = _testsuite_logmsg_pool; + struct _testsuite_log_message msg; + const char *prefix; + + switch (params->log_type) { + case LOG_TYPE_ERROR: + prefix = "error"; + break; + case LOG_TYPE_WARNING: + prefix = "warning"; + break; + case LOG_TYPE_INFO: + prefix = "info"; + break; + case LOG_TYPE_DEBUG: + prefix = "debug"; + break; + default: + i_unreached(); + } + + _testsuite_stdout_log(params, prefix, message); + + msg.location = p_strdup(pool, params->location); + msg.message = p_strdup(pool, message); + + switch (params->log_type) { + case LOG_TYPE_ERROR: + array_append(&_testsuite_log_errors, &msg, 1); + break; + case LOG_TYPE_WARNING: + array_append(&_testsuite_log_warnings, &msg, 1); + break; + case LOG_TYPE_INFO: + array_append(&_testsuite_log_messages, &msg, 1); + break; + case LOG_TYPE_DEBUG: + break; + default: + i_unreached(); + } +} + +static void +_testsuite_main_log(struct sieve_error_handler *ehandler, + const struct sieve_error_params *params, + enum sieve_error_flags flags, const char *message) +{ + if (params->log_type != LOG_TYPE_ERROR) + return _testsuite_log(ehandler, params, flags, message); + + if (params->location == NULL || *params->location == '\0') + fprintf(stderr, "error: %s\n", message); + else + fprintf(stderr, "%s: error: %s\n", params->location, message); +} + +static struct sieve_error_handler *_testsuite_log_ehandler_create(void) +{ + pool_t pool; + struct sieve_error_handler *ehandler; + + pool = pool_alloconly_create("testsuite_log_ehandler", + sizeof(struct sieve_error_handler)); + ehandler = p_new(pool, struct sieve_error_handler, 1); + sieve_error_handler_init(ehandler, testsuite_sieve_instance, pool, 0); + + ehandler->log = _testsuite_log; + + return ehandler; +} + +static struct sieve_error_handler *_testsuite_log_main_ehandler_create(void) +{ + pool_t pool; + struct sieve_error_handler *ehandler; + + pool = pool_alloconly_create("testsuite_log_main_ehandler", + sizeof(struct sieve_error_handler)); + ehandler = p_new(pool, struct sieve_error_handler, 1); + sieve_error_handler_init(ehandler, testsuite_sieve_instance, pool, 0); + + ehandler->log = _testsuite_main_log; + + return ehandler; +} + +static void ATTR_FORMAT(2, 0) +testsuite_error_handler(const struct failure_context *ctx, const char *fmt, + va_list args) +{ + struct sieve_error_params params = { + .location = NULL, + }; + pool_t pool = _testsuite_logmsg_pool; + struct _testsuite_log_message msg; + + i_zero(&msg); + switch (ctx->type) { + case LOG_TYPE_DEBUG: + T_BEGIN { + _testsuite_stdout_log(¶ms, "debug", + t_strdup_vprintf(fmt, args)); + } T_END; + break; + case LOG_TYPE_INFO: + msg.message = p_strdup_vprintf(pool, fmt, args); + array_append(&_testsuite_log_messages, &msg, 1); + + _testsuite_stdout_log(¶ms, "info", msg.message); + break; + case LOG_TYPE_WARNING: + msg.message = p_strdup_vprintf(pool, fmt, args); + array_append(&_testsuite_log_warnings, &msg, 1); + + _testsuite_stdout_log(¶ms, "warning", msg.message); + break; + case LOG_TYPE_ERROR: + msg.message = p_strdup_vprintf(pool, fmt, args); + array_append(&_testsuite_log_errors, &msg, 1); + + _testsuite_stdout_log(¶ms, "error", msg.message); + break; + default: + default_error_handler(ctx, fmt, args); + break; + } +} + +/* + * + */ + +void testsuite_log_clear_messages(void) +{ + if (_testsuite_logmsg_pool != NULL) { + if (array_count(&_testsuite_log_errors) == 0) + return; + pool_unref(&_testsuite_logmsg_pool); + } + + _testsuite_logmsg_pool = + pool_alloconly_create("testsuite_log_messages", 8192); + + p_array_init(&_testsuite_log_errors, _testsuite_logmsg_pool, 128); + p_array_init(&_testsuite_log_warnings, _testsuite_logmsg_pool, 128); + p_array_init(&_testsuite_log_messages, _testsuite_logmsg_pool, 128); + + sieve_error_handler_reset(testsuite_log_ehandler); +} + +/* + * + */ + +void testsuite_log_init(bool log_stdout) +{ + _testsuite_log_stdout = log_stdout; + + testsuite_log_ehandler = _testsuite_log_ehandler_create(); + sieve_error_handler_accept_infolog(testsuite_log_ehandler, TRUE); + sieve_error_handler_accept_debuglog(testsuite_log_ehandler, TRUE); + + testsuite_log_main_ehandler = _testsuite_log_main_ehandler_create(); + sieve_error_handler_accept_infolog(testsuite_log_main_ehandler, TRUE); + sieve_error_handler_accept_debuglog(testsuite_log_main_ehandler, TRUE); + + i_set_error_handler(testsuite_error_handler); + i_set_info_handler(testsuite_error_handler); + i_set_debug_handler(testsuite_error_handler); + + testsuite_log_clear_messages(); +} + +void testsuite_log_deinit(void) +{ + sieve_error_handler_unref(&testsuite_log_ehandler); + sieve_error_handler_unref(&testsuite_log_main_ehandler); + + i_set_error_handler(default_error_handler); + i_set_info_handler(default_error_handler); + i_set_debug_handler(default_error_handler); + + pool_unref(&_testsuite_logmsg_pool); +} + +/* + * Log stringlist + */ + +/* Forward declarations */ + +static int +testsuite_log_stringlist_next_item(struct sieve_stringlist *_strlist, + string_t **str_r); +static void testsuite_log_stringlist_reset(struct sieve_stringlist *_strlist); + +/* Stringlist object */ + +struct testsuite_log_stringlist { + struct sieve_stringlist strlist; + + int pos, index; +}; + +struct sieve_stringlist * +testsuite_log_stringlist_create(const struct sieve_runtime_env *renv, + int index) +{ + struct testsuite_log_stringlist *strlist; + + strlist = t_new(struct testsuite_log_stringlist, 1); + strlist->strlist.runenv = renv; + strlist->strlist.exec_status = SIEVE_EXEC_OK; + strlist->strlist.next_item = testsuite_log_stringlist_next_item; + strlist->strlist.reset = testsuite_log_stringlist_reset; + + strlist->index = index; + strlist->pos = 0; + + return &strlist->strlist; +} + +static int +testsuite_log_stringlist_next_item(struct sieve_stringlist *_strlist, + string_t **str_r) +{ + struct testsuite_log_stringlist *strlist = + (struct testsuite_log_stringlist *) _strlist; + const struct _testsuite_log_message *msg; + int pos; + + *str_r = NULL; + + if (strlist->pos < 0) + return 0; + + if (strlist->index > 0) { + pos = strlist->index - 1; + strlist->pos = -1; + } else { + pos = strlist->pos++; + } + + if (pos >= (int) array_count(&_testsuite_log_errors)) { + strlist->pos = -1; + return 0; + } + + msg = array_idx(&_testsuite_log_errors, (unsigned int) pos); + + *str_r = t_str_new_const(msg->message, strlen(msg->message)); + return 1; +} + +static void testsuite_log_stringlist_reset(struct sieve_stringlist *_strlist) +{ + struct testsuite_log_stringlist *strlist = + (struct testsuite_log_stringlist *) _strlist; + + strlist->pos = 0; +} diff --git a/pigeonhole/src/testsuite/testsuite-log.h b/pigeonhole/src/testsuite/testsuite-log.h new file mode 100644 index 0000000..335d044 --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-log.h @@ -0,0 +1,26 @@ +#ifndef TESTSUITE_LOG_H +#define TESTSUITE_LOG_H + +#include "sieve-common.h" + +extern struct sieve_error_handler *testsuite_log_ehandler; +extern struct sieve_error_handler *testsuite_log_main_ehandler; + +/* + * Initialization + */ + +void testsuite_log_init(bool log_stdout); +void testsuite_log_deinit(void); + +/* + * Access + */ + +void testsuite_log_clear_messages(void); + +struct sieve_stringlist * +testsuite_log_stringlist_create(const struct sieve_runtime_env *renv, + int index); + +#endif diff --git a/pigeonhole/src/testsuite/testsuite-mailstore.c b/pigeonhole/src/testsuite/testsuite-mailstore.c new file mode 100644 index 0000000..7762d50 --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-mailstore.c @@ -0,0 +1,349 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "mempool.h" +#include "imem.h" +#include "array.h" +#include "strfuncs.h" +#include "str-sanitize.h" +#include "path-util.h" +#include "unlink-directory.h" +#include "env-util.h" +#include "mail-namespace.h" +#include "mail-storage.h" +#include "imap-metadata.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-actions.h" +#include "sieve-interpreter.h" + +#include "testsuite-message.h" +#include "testsuite-common.h" +#include "testsuite-smtp.h" + +#include "testsuite-mailstore.h" + +#include <sys/stat.h> +#include <sys/types.h> + +struct testsuite_mailstore_mail { + struct testsuite_mailstore_mail *next; + + char *folder; + struct mailbox *box; + struct mailbox_transaction_context *trans; + struct mail *mail; +}; + +/* + * Forward declarations + */ + +static void testsuite_mailstore_free(bool all); + +/* + * State + */ + +static struct mail_user *testsuite_mailstore_user = NULL; + +static struct testsuite_mailstore_mail *testsuite_mailstore_mail = NULL; + +static char *testsuite_mailstore_location = NULL; +static char *testsuite_mailstore_attrs = NULL; + +/* + * Initialization + */ + +void testsuite_mailstore_init(void) +{ + struct mail_user *mail_user_dovecot, *mail_user; + struct mail_namespace *ns; + struct mail_namespace_settings *ns_set; + struct mail_storage_settings *mail_set; + const char *tmpdir, *error, *cwd; + + tmpdir = testsuite_tmp_dir_get(); + testsuite_mailstore_location = + i_strconcat(tmpdir, "/mailstore", NULL); + testsuite_mailstore_attrs = + i_strconcat(tmpdir, "/mail-attrs.dict", NULL); + + if (mkdir(testsuite_mailstore_location, 0700) < 0) { + i_fatal("failed to create temporary directory '%s': %m.", + testsuite_mailstore_location); + } + + mail_user_dovecot = sieve_tool_get_mail_user(sieve_tool); + mail_user = mail_user_alloc(NULL, "testsuite-mail-user@example.org", + mail_user_dovecot->set_info, + mail_user_dovecot->unexpanded_set); + mail_user->autocreated = TRUE; + if (t_get_working_dir(&cwd, &error) < 0) + i_fatal("Failed to get working directory: %s", error); + mail_user_set_home(mail_user, cwd); + if (mail_user_init(mail_user, &error) < 0) + i_fatal("Testsuite user initialization failed: %s", error); + + ns_set = p_new(mail_user->pool, struct mail_namespace_settings, 1); + ns_set->location = testsuite_mailstore_location; + ns_set->separator = "."; + + ns = mail_namespaces_init_empty(mail_user); + ns->flags |= NAMESPACE_FLAG_INBOX_USER; + ns->set = ns_set; + /* absolute paths are ok with raw storage */ + mail_set = p_new(mail_user->pool, struct mail_storage_settings, 1); + *mail_set = *ns->mail_set; + mail_set->mail_location = p_strconcat( + mail_user->pool, "maildir:", + testsuite_mailstore_location, NULL); + mail_set->mail_attribute_dict = p_strconcat( + mail_user->pool, "file:", + testsuite_mailstore_attrs, NULL); + ns->mail_set = mail_set; + + if (mail_storage_create(ns, "maildir", 0, &error) < 0) + i_fatal("Couldn't create testsuite storage: %s", error); + if (mail_namespaces_init_finish(ns, &error) < 0) + i_fatal("Couldn't create testsuite namespace: %s", error); + + testsuite_mailstore_user = mail_user; +} + +void testsuite_mailstore_deinit(void) +{ + const char *error; + + testsuite_mailstore_free(TRUE); + + if (unlink_directory(testsuite_mailstore_location, + UNLINK_DIRECTORY_FLAG_RMDIR, &error) < 0) { + i_warning("failed to remove temporary directory '%s': %s.", + testsuite_mailstore_location, error); + } + + i_free(testsuite_mailstore_location); + i_free(testsuite_mailstore_attrs); + mail_user_unref(&testsuite_mailstore_user); +} + +/* + * Mail user + */ + +struct mail_user *testsuite_mailstore_get_user(void) +{ + if (testsuite_mailstore_user == NULL) + return sieve_tool_get_mail_user(sieve_tool); + return testsuite_mailstore_user; +} + +/* + * Mailbox Access + */ + +bool testsuite_mailstore_mailbox_create( + const struct sieve_runtime_env *renv ATTR_UNUSED, const char *folder) +{ + struct mail_user *mail_user = testsuite_mailstore_user; + struct mail_namespace *ns = mail_user->namespaces; + struct mailbox *box; + + box = mailbox_alloc(ns->list, folder, 0); + + if (mailbox_create(box, NULL, FALSE) < 0) { + mailbox_free(&box); + return FALSE; + } + + mailbox_free(&box); + + return TRUE; +} + +static struct testsuite_mailstore_mail * +testsuite_mailstore_open(const char *folder) +{ + enum mailbox_flags flags = + MAILBOX_FLAG_SAVEONLY | MAILBOX_FLAG_POST_SESSION; + struct mail_user *mail_user = testsuite_mailstore_user; + struct mail_namespace *ns = mail_user->namespaces; + struct mailbox *box; + struct mailbox_transaction_context *t; + struct testsuite_mailstore_mail *tmail, *tmail_prev; + const char *error; + + if (!sieve_mailbox_check_name(folder, &error)) { + e_error(testsuite_sieve_instance->event, + "testsuite: invalid mailbox name `%s' specified: %s", + folder, error); + return NULL; + } + + tmail = testsuite_mailstore_mail; + tmail_prev = NULL; + while (tmail != NULL) { + if (strcmp(tmail->folder, folder) == 0) { + if (tmail_prev != NULL) { + /* Remove it from list if it is not first. */ + tmail_prev->next = tmail->next; + } + break; + } + tmail_prev = tmail; + tmail = tmail->next; + } + if (tmail != NULL) { + if (tmail != testsuite_mailstore_mail) { + /* Bring it to front */ + tmail->next = testsuite_mailstore_mail; + testsuite_mailstore_mail = tmail; + } + return tmail; + } + + box = mailbox_alloc(ns->list, folder, flags); + if (mailbox_open(box) < 0) { + e_error(testsuite_sieve_instance->event, + "testsuite: failed to open mailbox '%s'", folder); + mailbox_free(&box); + return NULL; + } + + /* Sync mailbox */ + + if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) { + e_error(testsuite_sieve_instance->event, + "testsuite: failed to sync mailbox '%s'", folder); + mailbox_free(&box); + return NULL; + } + + /* Start transaction */ + + t = mailbox_transaction_begin(box, 0, __func__); + + tmail = i_new(struct testsuite_mailstore_mail, 1); + tmail->next = testsuite_mailstore_mail; + testsuite_mailstore_mail = tmail; + + tmail->folder = i_strdup(folder); + tmail->box = box; + tmail->trans = t; + tmail->mail = mail_alloc(t, 0, NULL); + + return tmail; +} + +static void testsuite_mailstore_free(bool all) +{ + struct testsuite_mailstore_mail *tmail; + + if (testsuite_mailstore_mail == NULL) + return; + + tmail = (all ? + testsuite_mailstore_mail : testsuite_mailstore_mail->next); + while (tmail != NULL) { + struct testsuite_mailstore_mail *tmail_next = tmail->next; + + mail_free(&tmail->mail); + mailbox_transaction_rollback(&tmail->trans); + mailbox_free(&tmail->box); + i_free(tmail->folder); + i_free(tmail); + + tmail = tmail_next; + } + if (all) + testsuite_mailstore_mail = NULL; + else + testsuite_mailstore_mail->next = NULL; +} + +void testsuite_mailstore_flush(void) +{ + testsuite_mailstore_free(FALSE); +} + +bool testsuite_mailstore_mail_index(const struct sieve_runtime_env *renv, + const char *folder, unsigned int index) +{ + struct testsuite_mailstore_mail *tmail; + struct mailbox_status status; + + tmail = testsuite_mailstore_open(folder); + if (tmail == NULL) + return FALSE; + + mailbox_get_open_status(tmail->box, STATUS_MESSAGES, &status); + if (index >= status.messages) + return FALSE; + + mail_set_seq(tmail->mail, index+1); + testsuite_message_set_mail(renv, tmail->mail); + + return TRUE; +} + +/* + * IMAP metadata + */ + +int testsuite_mailstore_set_imap_metadata(const char *mailbox, + const char *annotation, + const char *value) +{ + struct imap_metadata_transaction *imtrans; + struct mail_attribute_value avalue; + struct mailbox *box; + enum mail_error error_code; + const char *error; + int ret; + + if (!imap_metadata_verify_entry_name(annotation, &error)) { + e_error(testsuite_sieve_instance->event, + "testsuite: imap metadata: " + "specified annotation name `%s' is invalid: %s", + str_sanitize(annotation, 256), error); + return -1; + } + + if (mailbox != NULL) { + struct mail_namespace *ns; + ns = mail_namespace_find(testsuite_mailstore_user->namespaces, + mailbox); + box = mailbox_alloc(ns->list, mailbox, 0); + imtrans = imap_metadata_transaction_begin(box); + } else { + box = NULL; + imtrans = imap_metadata_transaction_begin_server( + testsuite_mailstore_user); + } + + i_zero(&avalue); + avalue.value = value; + if ((ret = imap_metadata_set(imtrans, annotation, &avalue)) < 0) { + error = imap_metadata_transaction_get_last_error( + imtrans, &error_code); + imap_metadata_transaction_rollback(&imtrans); + } else { + ret = imap_metadata_transaction_commit(&imtrans, + &error_code, &error); + } + if (box != NULL) + mailbox_free(&box); + + if (ret < 0) { + e_error(testsuite_sieve_instance->event, + "testsuite: imap metadata: " + "failed to assign annotation `%s': %s", + str_sanitize(annotation, 256), error); + return -1; + } + return 0; +} diff --git a/pigeonhole/src/testsuite/testsuite-mailstore.h b/pigeonhole/src/testsuite/testsuite-mailstore.h new file mode 100644 index 0000000..07b0ab0 --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-mailstore.h @@ -0,0 +1,40 @@ +#ifndef TESTSUITE_MAILSTORE_H +#define TESTSUITE_MAILSTORE_H + +#include "lib.h" + +#include "sieve-common.h" + +/* + * Initialization + */ + +void testsuite_mailstore_init(void); +void testsuite_mailstore_deinit(void); +void testsuite_mailstore_flush(void); + +/* + * Mail user + */ + +struct mail_user *testsuite_mailstore_get_user(void); + +/* + * Mailbox Access + */ + +bool testsuite_mailstore_mailbox_create( + const struct sieve_runtime_env *renv ATTR_UNUSED, const char *folder); + +bool testsuite_mailstore_mail_index(const struct sieve_runtime_env *renv, + const char *folder, unsigned int index); + +/* + * IMAP metadata + */ + +int testsuite_mailstore_set_imap_metadata(const char *mailbox, + const char *annotation, + const char *value); + +#endif diff --git a/pigeonhole/src/testsuite/testsuite-message.c b/pigeonhole/src/testsuite/testsuite-message.c new file mode 100644 index 0000000..68e20eb --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-message.c @@ -0,0 +1,339 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "istream.h" +#include "smtp-params.h" +#include "message-address.h" +#include "mail-storage.h" +#include "master-service.h" +#include "mail-raw.h" + +#include "sieve-common.h" +#include "sieve-address.h" +#include "sieve-error.h" +#include "sieve-message.h" +#include "sieve-interpreter.h" + +#include "sieve-tool.h" + +#include "testsuite-common.h" +#include "testsuite-message.h" + +/* + * Testsuite message environment + */ + +struct testsuite_message { + struct testsuite_message *next; + + struct mail_raw *mail_raw; +}; + +struct sieve_message_data testsuite_msgdata; +static struct smtp_params_rcpt testsuite_rcpt_params; + +static struct testsuite_message *testsuite_msg; + +static const char *_default_message_data = +"From: sender@example.com\n" +"To: recipient@example.org\n" +"Subject: Frop!\n" +"\n" +"Friep!\n"; + +static struct smtp_address *testsuite_env_mail_from = NULL; +static struct smtp_address *testsuite_env_rcpt_to = NULL; +static struct smtp_address *testsuite_env_orig_rcpt_to = NULL; +static char *testsuite_env_auth = NULL; + +static pool_t testsuite_msg_pool; +static char *testsuite_msg_id = NULL; + +static const struct smtp_address * +testsuite_message_get_address(struct mail *mail, const char *header) +{ + struct message_address *addr; + struct smtp_address *smtp_addr; + const char *str; + + if (mail_get_first_header(mail, header, &str) <= 0) + return NULL; + addr = message_address_parse(pool_datastack_create(), + (const unsigned char *)str, + strlen(str), 1, 0); + if (addr == NULL || addr->mailbox == NULL || *addr->mailbox == '\0') + return NULL; + if (smtp_address_create_from_msg_temp(addr, &smtp_addr) < 0) + return NULL; + return smtp_addr; +} + +static void testsuite_message_set_data(struct mail *mail) +{ + const struct smtp_address *recipient = NULL, *sender = NULL; + const char *msg_id; + + static const struct smtp_address default_recipient = { + .localpart = "recipient", + .domain = "example.com", + }; + static const struct smtp_address default_sender = { + .localpart = "sender", + .domain = "example.com", + }; + + i_free(testsuite_env_mail_from); + i_free(testsuite_env_rcpt_to); + i_free(testsuite_env_orig_rcpt_to); + i_free(testsuite_env_auth); + i_free(testsuite_msg_id); + + /* + * Collect necessary message data + */ + + /* Get recipient address */ + recipient = testsuite_message_get_address(mail, "Envelope-To"); + if (recipient == NULL) + recipient = testsuite_message_get_address(mail, "To"); + if (recipient == NULL) + recipient = &default_recipient; + + /* Get sender address */ + sender = testsuite_message_get_address(mail, "Return-path"); + if (sender == NULL) + sender = testsuite_message_get_address(mail, "Sender"); + if (sender == NULL) + sender = testsuite_message_get_address(mail, "From"); + if (sender == NULL) + sender = &default_sender; + + testsuite_env_mail_from = smtp_address_clone(default_pool, sender); + testsuite_env_rcpt_to = smtp_address_clone(default_pool, recipient); + testsuite_env_orig_rcpt_to = smtp_address_clone(default_pool, recipient); + + (void)mail_get_message_id(mail, &msg_id); + testsuite_msg_id = i_strdup(msg_id); + + i_zero(&testsuite_msgdata); + testsuite_msgdata.mail = mail; + testsuite_msgdata.auth_user = sieve_tool_get_username(sieve_tool); + testsuite_msgdata.envelope.mail_from = testsuite_env_mail_from; + testsuite_msgdata.envelope.rcpt_to = testsuite_env_rcpt_to; + testsuite_msgdata.id = testsuite_msg_id; + + i_zero(&testsuite_rcpt_params); + testsuite_rcpt_params.orcpt.addr = testsuite_env_orig_rcpt_to; + + testsuite_msgdata.envelope.rcpt_params = &testsuite_rcpt_params; +} + +static struct testsuite_message *testsuite_message_new(void) +{ + struct testsuite_message *msg; + + msg = i_new(struct testsuite_message, 1); + msg->next = testsuite_msg; + testsuite_msg = msg; + + return msg; +} + +static void testsuite_message_new_string(string_t *mail_str) +{ + struct mail_user *mail_raw_user = + sieve_tool_get_mail_raw_user(sieve_tool); + struct testsuite_message *msg; + + msg = testsuite_message_new(); + msg->mail_raw = mail_raw_open_data(mail_raw_user, mail_str); + + testsuite_message_set_data(msg->mail_raw->mail); +} + +static void testsuite_message_new_file(const char *mail_path) +{ + struct mail_user *mail_raw_user = + sieve_tool_get_mail_raw_user(sieve_tool); + struct testsuite_message *msg; + + msg = testsuite_message_new(); + msg->mail_raw = mail_raw_open_file(mail_raw_user, mail_path); + + testsuite_message_set_data(msg->mail_raw->mail); +} + +static void testsuite_message_free(bool all) +{ + struct testsuite_message *msg; + + if (testsuite_msg == NULL) + return; + + msg = (all ? testsuite_msg : testsuite_msg->next); + while (msg != NULL) { + struct testsuite_message *msg_next = msg->next; + + mail_raw_close(&msg->mail_raw); + i_free(msg); + + msg = msg_next; + } + if (all) + testsuite_msg = NULL; + else + testsuite_msg->next = NULL; +} + +void testsuite_message_flush(void) +{ + testsuite_message_free(FALSE); +} + +void testsuite_message_init(void) +{ + testsuite_msg_pool = pool_alloconly_create("testsuite_message", 6096); + + string_t *default_message = str_new(testsuite_msg_pool, 1024); + str_append(default_message, _default_message_data); + + testsuite_message_new_string(default_message); +} + +void testsuite_message_set_string(const struct sieve_runtime_env *renv, + string_t *message) +{ + sieve_message_context_reset(renv->msgctx); + + testsuite_message_new_string(message); +} + +void testsuite_message_set_file(const struct sieve_runtime_env *renv, + const char *file_path) +{ + sieve_message_context_reset(renv->msgctx); + + testsuite_message_new_file(file_path); +} + +void testsuite_message_set_mail(const struct sieve_runtime_env *renv, + struct mail *mail) +{ + sieve_message_context_reset(renv->msgctx); + + testsuite_message_set_data(mail); +} + +void testsuite_message_deinit(void) +{ + testsuite_message_free(TRUE); + + i_free(testsuite_env_mail_from); + i_free(testsuite_env_rcpt_to); + i_free(testsuite_env_orig_rcpt_to); + i_free(testsuite_env_auth); + pool_unref(&testsuite_msg_pool); + i_free(testsuite_msg_id); +} + +void testsuite_envelope_set_sender_address(const struct sieve_runtime_env *renv, + const struct smtp_address *address) +{ + sieve_message_context_reset(renv->msgctx); + + i_free(testsuite_env_mail_from); + + testsuite_env_mail_from = smtp_address_clone(default_pool, address); + testsuite_msgdata.envelope.mail_from = testsuite_env_mail_from; +} + +void testsuite_envelope_set_sender(const struct sieve_runtime_env *renv, + const char *value) +{ + struct smtp_address *address = NULL; + const char *error; + + if (smtp_address_parse_path(pool_datastack_create(), value, + (SMTP_ADDRESS_PARSE_FLAG_ALLOW_EMPTY | + SMTP_ADDRESS_PARSE_FLAG_BRACKETS_OPTIONAL), + &address, &error) < 0) { + e_error(testsuite_sieve_instance->event, + "testsuite: envelope sender address " + "`%s' is invalid: %s", value, error); + } + testsuite_envelope_set_sender_address(renv, address); +} + +void testsuite_envelope_set_recipient_address( + const struct sieve_runtime_env *renv, + const struct smtp_address *address) +{ + sieve_message_context_reset(renv->msgctx); + + i_free(testsuite_env_rcpt_to); + i_free(testsuite_env_orig_rcpt_to); + + testsuite_env_rcpt_to = smtp_address_clone(default_pool, address); + testsuite_env_orig_rcpt_to = smtp_address_clone(default_pool, address); + testsuite_msgdata.envelope.rcpt_to = testsuite_env_rcpt_to; + testsuite_rcpt_params.orcpt.addr = testsuite_env_orig_rcpt_to; +} + +void testsuite_envelope_set_recipient(const struct sieve_runtime_env *renv, + const char *value) +{ + struct smtp_address *address = NULL; + const char *error; + + if (smtp_address_parse_path(pool_datastack_create(), value, + (SMTP_ADDRESS_PARSE_FLAG_ALLOW_LOCALPART | + SMTP_ADDRESS_PARSE_FLAG_BRACKETS_OPTIONAL), + &address, &error) < 0) { + e_error(testsuite_sieve_instance->event, + "testsuite: envelope recipient address " + "`%s' is invalid: %s", value, error); + } + testsuite_envelope_set_recipient_address(renv, address); +} + +void testsuite_envelope_set_orig_recipient_address( + const struct sieve_runtime_env *renv, + const struct smtp_address *address) +{ + sieve_message_context_reset(renv->msgctx); + + i_free(testsuite_env_orig_rcpt_to); + + testsuite_env_orig_rcpt_to = smtp_address_clone(default_pool, address); + testsuite_rcpt_params.orcpt.addr = testsuite_env_orig_rcpt_to; +} + +void testsuite_envelope_set_orig_recipient(const struct sieve_runtime_env *renv, + const char *value) +{ + struct smtp_address *address = NULL; + const char *error; + + if (smtp_address_parse_path(pool_datastack_create(), value, + (SMTP_ADDRESS_PARSE_FLAG_ALLOW_LOCALPART | + SMTP_ADDRESS_PARSE_FLAG_BRACKETS_OPTIONAL), + &address, &error) < 0) { + e_error(testsuite_sieve_instance->event, + "testsuite: envelope recipient address " + "`%s' is invalid: %s", value, error); + } + testsuite_envelope_set_orig_recipient_address(renv, address); +} + +void testsuite_envelope_set_auth_user(const struct sieve_runtime_env *renv, + const char *value) +{ + sieve_message_context_reset(renv->msgctx); + + i_free(testsuite_env_auth); + + testsuite_env_auth = i_strdup(value); + testsuite_msgdata.auth_user = testsuite_env_auth; +} diff --git a/pigeonhole/src/testsuite/testsuite-message.h b/pigeonhole/src/testsuite/testsuite-message.h new file mode 100644 index 0000000..2a4d3b4 --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-message.h @@ -0,0 +1,44 @@ +#ifndef TESTSUITE_MESSAGE_H +#define TESTSUITE_MESSAGE_H + +#include "lib.h" +#include "master-service.h" + +#include "sieve-common.h" +#include "sieve-tool.h" + +extern struct sieve_message_data testsuite_msgdata; + +void testsuite_message_init(void); +void testsuite_message_deinit(void); + +void testsuite_message_flush(void); + +void testsuite_message_set_string(const struct sieve_runtime_env *renv, + string_t *message); +void testsuite_message_set_file(const struct sieve_runtime_env *renv, + const char *file_path); +void testsuite_message_set_mail(const struct sieve_runtime_env *renv, + struct mail *mail); + +void testsuite_envelope_set_sender_address(const struct sieve_runtime_env *renv, + const struct smtp_address *address); +void testsuite_envelope_set_sender(const struct sieve_runtime_env *renv, + const char *value); + +void testsuite_envelope_set_recipient_address( + const struct sieve_runtime_env *renv, + const struct smtp_address *address); +void testsuite_envelope_set_recipient(const struct sieve_runtime_env *renv, + const char *value); + +void testsuite_envelope_set_orig_recipient_address( + const struct sieve_runtime_env *renv, + const struct smtp_address *address); +void testsuite_envelope_set_orig_recipient(const struct sieve_runtime_env *renv, + const char *value); + +void testsuite_envelope_set_auth_user(const struct sieve_runtime_env *renv, + const char *value); + +#endif diff --git a/pigeonhole/src/testsuite/testsuite-objects.c b/pigeonhole/src/testsuite/testsuite-objects.c new file mode 100644 index 0000000..4c09c85 --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-objects.c @@ -0,0 +1,369 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "string.h" +#include "ostream.h" +#include "hash.h" +#include "mail-storage.h" + +#include "sieve.h" +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-extensions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-dump.h" + +#include "testsuite-common.h" +#include "testsuite-objects.h" +#include "testsuite-message.h" + +/* + * Testsuite core objects + */ + +enum testsuite_object_code { + TESTSUITE_OBJECT_MESSAGE, + TESTSUITE_OBJECT_ENVELOPE +}; + +const struct testsuite_object_def *testsuite_core_objects[] = { + &message_testsuite_object, &envelope_testsuite_object +}; + +const unsigned int testsuite_core_objects_count = + N_ELEMENTS(testsuite_core_objects); + +/* + * Testsuite object registry + */ + +static inline struct sieve_validator_object_registry *_get_object_registry +(struct sieve_validator *valdtr) +{ + struct testsuite_validator_context *ctx = + testsuite_validator_context_get(valdtr); + + return ctx->object_registrations; +} + +void testsuite_object_register +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + const struct testsuite_object_def *tobj_def) +{ + struct sieve_validator_object_registry *regs = _get_object_registry(valdtr); + + sieve_validator_object_registry_add(regs, ext, &tobj_def->obj_def); +} + +static const struct testsuite_object *testsuite_object_create +(struct sieve_validator *valdtr, struct sieve_command *cmd, + const char *identifier) +{ + struct sieve_validator_object_registry *regs = _get_object_registry(valdtr); + struct sieve_object object; + struct testsuite_object *tobj; + + if ( !sieve_validator_object_registry_find(regs, identifier, &object) ) + return NULL; + + tobj = p_new(sieve_command_pool(cmd), struct testsuite_object, 1); + tobj->object = object; + tobj->def = (const struct testsuite_object_def *) object.def; + + return tobj; +} + +void testsuite_register_core_objects +(struct testsuite_validator_context *ctx) +{ + struct sieve_validator_object_registry *regs = ctx->object_registrations; + unsigned int i; + + /* Register core testsuite objects */ + for ( i = 0; i < testsuite_core_objects_count; i++ ) { + const struct testsuite_object_def *tobj_def = testsuite_core_objects[i]; + + sieve_validator_object_registry_add + (regs, testsuite_ext, &tobj_def->obj_def); + } +} + +/* + * Testsuite object code + */ + +const struct sieve_operand_class sieve_testsuite_object_operand_class = + { "testsuite object" }; + +static const struct sieve_extension_objects core_testsuite_objects = + SIEVE_EXT_DEFINE_OBJECTS(testsuite_core_objects); + +const struct sieve_operand_def testsuite_object_operand = { + .name = "testsuite-object", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERAND_OBJECT, + .class = &sieve_testsuite_object_operand_class, + .interface = &core_testsuite_objects +}; + +static void testsuite_object_emit +(struct sieve_binary_block *sblock, const struct testsuite_object *tobj, + int member_id) +{ + sieve_opr_object_emit(sblock, tobj->object.ext, tobj->object.def); + + if ( tobj->def != NULL && tobj->def->get_member_id != NULL ) { + (void) sieve_binary_emit_byte(sblock, (unsigned char) member_id); + } +} + +bool testsuite_object_read +(struct sieve_binary_block *sblock, sieve_size_t *address, + struct testsuite_object *tobj) +{ + struct sieve_operand oprnd; + + if ( !sieve_operand_read(sblock, address, NULL, &oprnd) ) + return FALSE; + + if ( !sieve_opr_object_read_data + (sblock, &oprnd, &sieve_testsuite_object_operand_class, address, + &tobj->object) ) + return FALSE; + + tobj->def = (const struct testsuite_object_def *) tobj->object.def; + i_assert(tobj->def != NULL); + return TRUE; +} + +bool testsuite_object_read_member +(struct sieve_binary_block *sblock, sieve_size_t *address, + struct testsuite_object *tobj, int *member_id_r) +{ + if ( !testsuite_object_read(sblock, address, tobj) ) + return FALSE; + + *member_id_r = -1; + if ( tobj->def->get_member_id != NULL ) { + if ( !sieve_binary_read_code(sblock, address, member_id_r) ) + return FALSE; + } + + return TRUE; +} + +const char *testsuite_object_member_name +(const struct testsuite_object *object, int member_id) +{ + const struct testsuite_object_def *obj_def = object->def; + const char *member = NULL; + + if ( obj_def->get_member_id != NULL ) { + if ( obj_def->get_member_name != NULL ) + member = obj_def->get_member_name(member_id); + } else + return obj_def->obj_def.identifier; + + if ( member == NULL ) + return t_strdup_printf("%s.%d", obj_def->obj_def.identifier, member_id); + + return t_strdup_printf("%s.%s", obj_def->obj_def.identifier, member); +} + +bool testsuite_object_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + struct testsuite_object object; + int member_id; + + sieve_code_mark(denv); + + if ( !testsuite_object_read_member + (denv->sblock, address, &object, &member_id) ) + return FALSE; + + sieve_code_dumpf(denv, "%s: %s", + sieve_testsuite_object_operand_class.name, + testsuite_object_member_name(&object, member_id)); + + return TRUE; +} + +/* + * Testsuite object argument + */ + +static bool arg_testsuite_object_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd); + +const struct sieve_argument_def testsuite_object_argument = { + .identifier = "testsuite-object", + .generate = arg_testsuite_object_generate +}; + +struct testsuite_object_argctx { + const struct testsuite_object *object; + int member; +}; + +bool testsuite_object_argument_activate +(struct sieve_validator *valdtr, struct sieve_ast_argument *arg, + struct sieve_command *cmd) +{ + const char *objname = sieve_ast_argument_strc(arg); + const struct testsuite_object *tobj; + int member_id; + const char *member; + struct testsuite_object_argctx *ctx; + + /* Parse the object specifier */ + + member = strchr(objname, '.'); + if ( member != NULL ) { + objname = t_strdup_until(objname, member); + member++; + } + + /* Find the object */ + + tobj = testsuite_object_create(valdtr, cmd, objname); + if ( tobj == NULL ) { + sieve_argument_validate_error(valdtr, arg, + "unknown testsuite object '%s'", objname); + return FALSE; + } + + /* Find the object member */ + + member_id = -1; + if ( member != NULL ) { + if ( tobj->def == NULL || tobj->def->get_member_id == NULL || + (member_id=tobj->def->get_member_id(member)) == -1 ) { + sieve_argument_validate_error(valdtr, arg, + "member '%s' does not exist for testsuite object '%s'", member, objname); + return FALSE; + } + } + + /* Assign argument context */ + + ctx = p_new(sieve_command_pool(cmd), struct testsuite_object_argctx, 1); + ctx->object = tobj; + ctx->member = member_id; + + arg->argument = sieve_argument_create + (arg->ast, &testsuite_object_argument, testsuite_ext, 0); + arg->argument->data = (void *) ctx; + + return TRUE; +} + +static bool arg_testsuite_object_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + struct testsuite_object_argctx *ctx = + (struct testsuite_object_argctx *) arg->argument->data; + + testsuite_object_emit(cgenv->sblock, ctx->object, ctx->member); + + return TRUE; +} + +/* + * Testsuite core object implementation + */ + +static bool tsto_message_set_member + (const struct sieve_runtime_env *renv, int id, string_t *value); + +static int tsto_envelope_get_member_id(const char *identifier); +static const char *tsto_envelope_get_member_name(int id); +static bool tsto_envelope_set_member + (const struct sieve_runtime_env *renv, int id, string_t *value); + +const struct testsuite_object_def message_testsuite_object = { + SIEVE_OBJECT("message", + &testsuite_object_operand, TESTSUITE_OBJECT_MESSAGE), + .set_member = tsto_message_set_member +}; + +const struct testsuite_object_def envelope_testsuite_object = { + SIEVE_OBJECT("envelope", + &testsuite_object_operand, TESTSUITE_OBJECT_ENVELOPE), + .get_member_id = tsto_envelope_get_member_id, + .get_member_name = tsto_envelope_get_member_name, + .set_member = tsto_envelope_set_member +}; + +enum testsuite_object_envelope_field { + TESTSUITE_OBJECT_ENVELOPE_FROM, + TESTSUITE_OBJECT_ENVELOPE_TO, + TESTSUITE_OBJECT_ENVELOPE_ORIG_TO, + TESTSUITE_OBJECT_ENVELOPE_AUTH_USER +}; + +static bool tsto_message_set_member +(const struct sieve_runtime_env *renv, int id, string_t *value) +{ + if ( id != -1 ) return FALSE; + + testsuite_message_set_string(renv, value); + + return TRUE; +} + +static int tsto_envelope_get_member_id(const char *identifier) +{ + if ( strcasecmp(identifier, "from") == 0 ) + return TESTSUITE_OBJECT_ENVELOPE_FROM; + if ( strcasecmp(identifier, "to") == 0 ) + return TESTSUITE_OBJECT_ENVELOPE_TO; + if ( strcasecmp(identifier, "orig_to") == 0 ) + return TESTSUITE_OBJECT_ENVELOPE_ORIG_TO; + if ( strcasecmp(identifier, "auth") == 0 ) + return TESTSUITE_OBJECT_ENVELOPE_AUTH_USER; + + return -1; +} + +static const char *tsto_envelope_get_member_name(int id) +{ + switch ( id ) { + case TESTSUITE_OBJECT_ENVELOPE_FROM: + return "from"; + case TESTSUITE_OBJECT_ENVELOPE_TO: + return "to"; + case TESTSUITE_OBJECT_ENVELOPE_ORIG_TO: + return "orig_to"; + case TESTSUITE_OBJECT_ENVELOPE_AUTH_USER: + return "auth"; + } + + return NULL; +} + +static bool tsto_envelope_set_member +(const struct sieve_runtime_env *renv, int id, string_t *value) +{ + switch ( id ) { + case TESTSUITE_OBJECT_ENVELOPE_FROM: + testsuite_envelope_set_sender(renv, str_c(value)); + return TRUE; + case TESTSUITE_OBJECT_ENVELOPE_TO: + testsuite_envelope_set_recipient(renv, str_c(value)); + return TRUE; + case TESTSUITE_OBJECT_ENVELOPE_ORIG_TO: + testsuite_envelope_set_orig_recipient(renv, str_c(value)); + return TRUE; + case TESTSUITE_OBJECT_ENVELOPE_AUTH_USER: + testsuite_envelope_set_auth_user(renv, str_c(value)); + return TRUE; + } + + return FALSE; +} diff --git a/pigeonhole/src/testsuite/testsuite-objects.h b/pigeonhole/src/testsuite/testsuite-objects.h new file mode 100644 index 0000000..0aa6f4f --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-objects.h @@ -0,0 +1,83 @@ +#ifndef TESTSUITE_OBJECTS_H +#define TESTSUITE_OBJECTS_H + +#include "sieve-common.h" +#include "sieve-objects.h" + +#include "testsuite-common.h" + +/* + * Testsuite object operand + */ + +struct testsuite_object_operand_interface { + struct sieve_extension_objects testsuite_objects; +}; + +extern const struct sieve_operand_class testsuite_object_oprclass; + +/* + * Testsuite object access + */ + +struct testsuite_object_def { + struct sieve_object_def obj_def; + + int (*get_member_id)(const char *identifier); + const char *(*get_member_name)(int id); + + bool (*set_member) + (const struct sieve_runtime_env *renv, int id, string_t *value); + string_t *(*get_member) + (const struct sieve_runtime_env *renv, int id); +}; + +struct testsuite_object { + struct sieve_object object; + + const struct testsuite_object_def *def; +}; + +/* + * Testsuite object registration + */ + +void testsuite_register_core_objects + (struct testsuite_validator_context *ctx); +void testsuite_object_register + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + const struct testsuite_object_def *tobj_def); + +/* + * Testsuite object argument + */ + +bool testsuite_object_argument_activate + (struct sieve_validator *valdtr, struct sieve_ast_argument *arg, + struct sieve_command *cmd); + +/* + * Testsuite object code + */ + +bool testsuite_object_read + (struct sieve_binary_block *sblock, sieve_size_t *address, + struct testsuite_object *tobj); +bool testsuite_object_read_member + (struct sieve_binary_block *sblock, sieve_size_t *address, + struct testsuite_object *tobj, int *member_id_r); + +bool testsuite_object_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); + +const char *testsuite_object_member_name + (const struct testsuite_object *object, int member_id); + +/* + * Testsuite core objects + */ + +extern const struct testsuite_object_def message_testsuite_object; +extern const struct testsuite_object_def envelope_testsuite_object; + +#endif diff --git a/pigeonhole/src/testsuite/testsuite-result.c b/pigeonhole/src/testsuite/testsuite-result.c new file mode 100644 index 0000000..51be3ff --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-result.c @@ -0,0 +1,206 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "ostream.h" +#include "str.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-stringlist.h" +#include "sieve-actions.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "testsuite-common.h" +#include "testsuite-log.h" +#include "testsuite-message.h" +#include "testsuite-mailstore.h" + +#include "testsuite-result.h" + +struct sieve_execute_env testsuite_execute_env; + +static pool_t testsuite_execute_pool = NULL; +static struct sieve_result *_testsuite_result = NULL; +static struct sieve_result_execution *_testsuite_rexec = NULL; + +void testsuite_result_init(void) +{ + struct sieve_instance *svinst = testsuite_sieve_instance; + + testsuite_execute_pool = pool_alloconly_create("sieve execution", 4096); + + sieve_execute_init(&testsuite_execute_env, testsuite_sieve_instance, + testsuite_execute_pool, &testsuite_msgdata, + testsuite_scriptenv, 0); + + _testsuite_result = sieve_result_create(svinst, testsuite_execute_pool, + &testsuite_execute_env); +} + +void testsuite_result_deinit(void) +{ + sieve_result_execution_destroy(&_testsuite_rexec); + if (_testsuite_result != NULL) + sieve_result_unref(&_testsuite_result); + sieve_execute_deinit(&testsuite_execute_env); + pool_unref(&testsuite_execute_pool); +} + +void testsuite_result_reset(const struct sieve_runtime_env *renv) +{ + struct sieve_instance *svinst = testsuite_sieve_instance; + + if (_testsuite_result != NULL) { + sieve_result_execution_destroy(&_testsuite_rexec); + sieve_result_unref(&_testsuite_result); + pool_unref(&testsuite_execute_pool); + } + + testsuite_message_flush(); + testsuite_mailstore_flush(); + i_zero(testsuite_execute_env.exec_status); + + testsuite_execute_pool = pool_alloconly_create("sieve execution", 4096); + _testsuite_result = sieve_result_create(svinst, testsuite_execute_pool, + &testsuite_execute_env); + sieve_interpreter_set_result(renv->interp, _testsuite_result); +} + +struct sieve_result *testsuite_result_get(void) +{ + return _testsuite_result; +} + +struct sieve_result_iterate_context *testsuite_result_iterate_init(void) +{ + if (_testsuite_result == NULL) + return NULL; + + return sieve_result_iterate_init(_testsuite_result); +} + +bool testsuite_result_execute(const struct sieve_runtime_env *renv) +{ + int ret; + + if (_testsuite_result == NULL) { + sieve_runtime_error(renv, NULL, "testsuite: " + "trying to execute result, " + "but no result evaluated yet"); + return FALSE; + } + + testsuite_log_clear_messages(); + + if (_testsuite_rexec == NULL) { + _testsuite_rexec = sieve_result_execution_create( + _testsuite_result, testsuite_execute_pool); + } + + /* Execute the result */ + ret = sieve_result_execute(_testsuite_rexec, SIEVE_EXEC_OK, TRUE, + testsuite_log_ehandler, NULL); + + return (ret > 0); +} + +void testsuite_result_print(const struct sieve_runtime_env *renv) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct ostream *out; + + out = o_stream_create_fd(1, 0); + o_stream_set_no_error_handling(out, TRUE); + + o_stream_nsend_str(out, "\n--"); + sieve_result_print(_testsuite_result, eenv->scriptenv, out, NULL); + o_stream_nsend_str(out, "--\n\n"); + + o_stream_destroy(&out); +} + +/* + * Result stringlist + */ + +/* Forward declarations */ + +static int +testsuite_result_stringlist_next_item(struct sieve_stringlist *_strlist, + string_t **str_r); +static void +testsuite_result_stringlist_reset(struct sieve_stringlist *_strlist); + +/* Stringlist object */ + +struct testsuite_result_stringlist { + struct sieve_stringlist strlist; + + struct sieve_result_iterate_context *result_iter; + int pos, index; +}; + +struct sieve_stringlist * +testsuite_result_stringlist_create(const struct sieve_runtime_env *renv, + int index) +{ + struct testsuite_result_stringlist *strlist; + + strlist = t_new(struct testsuite_result_stringlist, 1); + strlist->strlist.runenv = renv; + strlist->strlist.exec_status = SIEVE_EXEC_OK; + strlist->strlist.next_item = testsuite_result_stringlist_next_item; + strlist->strlist.reset = testsuite_result_stringlist_reset; + + strlist->result_iter = testsuite_result_iterate_init(); + strlist->index = index; + strlist->pos = 0; + + return &strlist->strlist; +} + +static int +testsuite_result_stringlist_next_item(struct sieve_stringlist *_strlist, + string_t **str_r) +{ + struct testsuite_result_stringlist *strlist = + (struct testsuite_result_stringlist *)_strlist; + const struct sieve_action *action; + const char *act_name; + bool keep; + + *str_r = NULL; + + if (strlist->index > 0 && strlist->pos > 0) + return 0; + + do { + if ((action = sieve_result_iterate_next(strlist->result_iter, + &keep)) == NULL) + return 0; + + strlist->pos++; + } while (strlist->pos < strlist->index); + + if (keep) + act_name = "keep"; + else { + act_name = ((action == NULL || action->def == NULL || + action->def->name == NULL) ? + "" : action->def->name); + } + + *str_r = t_str_new_const(act_name, strlen(act_name)); + return 1; +} + +static void testsuite_result_stringlist_reset(struct sieve_stringlist *_strlist) +{ + struct testsuite_result_stringlist *strlist = + (struct testsuite_result_stringlist *)_strlist; + + strlist->result_iter = testsuite_result_iterate_init(); + strlist->pos = 0; +} diff --git a/pigeonhole/src/testsuite/testsuite-result.h b/pigeonhole/src/testsuite/testsuite-result.h new file mode 100644 index 0000000..3e232d2 --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-result.h @@ -0,0 +1,25 @@ +#ifndef TESTSUITE_RESULT_H +#define TESTSUITE_RESULT_H + +#include "sieve-execute.h" + +extern struct sieve_execute_env testsuite_execute_env; + +void testsuite_result_init(void); +void testsuite_result_deinit(void); + +void testsuite_result_reset(const struct sieve_runtime_env *renv); + +struct sieve_result *testsuite_result_get(void); + +struct sieve_result_iterate_context *testsuite_result_iterate_init(void); + +bool testsuite_result_execute(const struct sieve_runtime_env *renv); + +void testsuite_result_print(const struct sieve_runtime_env *renv ATTR_UNUSED); + +struct sieve_stringlist * +testsuite_result_stringlist_create(const struct sieve_runtime_env *renv, + int index); + +#endif diff --git a/pigeonhole/src/testsuite/testsuite-script.c b/pigeonhole/src/testsuite/testsuite-script.c new file mode 100644 index 0000000..b6edd9b --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-script.c @@ -0,0 +1,256 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve.h" +#include "sieve-common.h" +#include "sieve-script.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-runtime-trace.h" +#include "sieve-result.h" + +#include "testsuite-common.h" +#include "testsuite-settings.h" +#include "testsuite-log.h" +#include "testsuite-smtp.h" +#include "testsuite-result.h" + +#include "testsuite-script.h" + +/* + * Tested script environment + */ + +void testsuite_script_init(void) +{ +} + +void testsuite_script_deinit(void) +{ +} + +static struct sieve_binary * +_testsuite_script_compile(const struct sieve_runtime_env *renv, + const char *script) +{ + struct sieve_instance *svinst = testsuite_sieve_instance; + struct sieve_binary *sbin; + const char *script_path; + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "compile script `%s'", script); + + script_path = sieve_file_script_get_dirpath(renv->script); + if (script_path == NULL) + return NULL; + + script_path = t_strconcat(script_path, "/", script, NULL); + if ((sbin = sieve_compile(svinst, script_path, NULL, + testsuite_log_ehandler, 0, NULL)) == NULL) + return NULL; + + return sbin; +} + +bool testsuite_script_compile(const struct sieve_runtime_env *renv, + const char *script) +{ + struct testsuite_interpreter_context *ictx = + testsuite_interpreter_context_get(renv->interp, testsuite_ext); + struct sieve_binary *sbin; + + i_assert(ictx != NULL); + testsuite_log_clear_messages(); + + if ((sbin = _testsuite_script_compile(renv, script)) == NULL) + return FALSE; + + sieve_binary_unref(&ictx->compiled_script); + + ictx->compiled_script = sbin; + return TRUE; +} + +bool testsuite_script_is_subtest(const struct sieve_runtime_env *renv) +{ + struct testsuite_interpreter_context *ictx = + testsuite_interpreter_context_get(renv->interp, testsuite_ext); + + i_assert(ictx != NULL); + if (ictx->compiled_script == NULL) + return FALSE; + + return (sieve_binary_extension_get_index(ictx->compiled_script, + testsuite_ext) >= 0); +} + +bool testsuite_script_run(const struct sieve_runtime_env *renv) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_script_env *senv = eenv->scriptenv; + struct testsuite_interpreter_context *ictx = + testsuite_interpreter_context_get(renv->interp, testsuite_ext); + struct sieve_script_env scriptenv; + struct sieve_exec_status exec_status; + struct sieve_result *result; + struct sieve_interpreter *interp; + pool_t pool; + struct sieve_execute_env exec_env; + const char *error; + int ret; + + i_assert(ictx != NULL); + + if (ictx->compiled_script == NULL) { + sieve_runtime_error(renv, NULL, "testsuite: " + "trying to run script, but no script compiled yet"); + return FALSE; + } + + testsuite_log_clear_messages(); + + i_zero(&exec_status); + + /* Compose script execution environment */ + if (sieve_script_env_init(&scriptenv, senv->user, &error) < 0) { + sieve_runtime_error(renv, NULL, "testsuite: " + "failed to initialize script execution: %s", error); + return FALSE; + } + scriptenv.default_mailbox = "INBOX"; + scriptenv.smtp_start = testsuite_smtp_start; + scriptenv.smtp_add_rcpt = testsuite_smtp_add_rcpt; + scriptenv.smtp_send = testsuite_smtp_send; + scriptenv.smtp_abort = testsuite_smtp_abort; + scriptenv.smtp_finish = testsuite_smtp_finish; + scriptenv.duplicate_mark = NULL; + scriptenv.duplicate_check = NULL; + scriptenv.trace_log = eenv->scriptenv->trace_log; + scriptenv.trace_config = eenv->scriptenv->trace_config; + + result = testsuite_result_get(); + + pool = pool_alloconly_create("sieve execution", 4096); + sieve_execute_init(&exec_env, eenv->svinst, pool, eenv->msgdata, + &scriptenv, eenv->flags); + pool_unref(&pool); + + /* Execute the script */ + interp = sieve_interpreter_create(ictx->compiled_script, NULL, + &exec_env, testsuite_log_ehandler); + + if (interp == NULL) { + sieve_execute_deinit(&exec_env); + return FALSE; + } + + ret = sieve_interpreter_run(interp, result); + sieve_interpreter_free(&interp); + + sieve_execute_finish(&exec_env, ret); + sieve_execute_deinit(&exec_env); + + return (ret > 0 || + sieve_binary_extension_get_index(ictx->compiled_script, + testsuite_ext) >= 0); +} + +struct sieve_binary * +testsuite_script_get_binary(const struct sieve_runtime_env *renv) +{ + struct testsuite_interpreter_context *ictx = + testsuite_interpreter_context_get(renv->interp, testsuite_ext); + + i_assert(ictx != NULL); + return ictx->compiled_script; +} + +void testsuite_script_set_binary(const struct sieve_runtime_env *renv, + struct sieve_binary *sbin) +{ + struct testsuite_interpreter_context *ictx = + testsuite_interpreter_context_get(renv->interp, testsuite_ext); + + i_assert(ictx != NULL); + + sieve_binary_unref(&ictx->compiled_script); + + ictx->compiled_script = sbin; + sieve_binary_ref(sbin); +} + +/* + * Multiscript + */ + +bool testsuite_script_multiscript(const struct sieve_runtime_env *renv, + ARRAY_TYPE (const_string) *scriptfiles) +{ + struct sieve_instance *svinst = testsuite_sieve_instance; + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_script_env *senv = eenv->scriptenv; + struct sieve_script_env scriptenv; + struct sieve_exec_status exec_status; + struct sieve_multiscript *mscript; + const char *const *scripts; + const char *error; + unsigned int count, i; + bool more = TRUE; + bool result = TRUE; + + testsuite_log_clear_messages(); + + /* Compose script execution environment */ + if (sieve_script_env_init(&scriptenv, senv->user, &error) < 0) { + sieve_runtime_error(renv, NULL, + "testsuite: failed to initialize script execution: %s", + error); + return FALSE; + } + scriptenv.default_mailbox = "INBOX"; + scriptenv.smtp_start = testsuite_smtp_start; + scriptenv.smtp_add_rcpt = testsuite_smtp_add_rcpt; + scriptenv.smtp_send = testsuite_smtp_send; + scriptenv.smtp_abort = testsuite_smtp_abort; + scriptenv.smtp_finish = testsuite_smtp_finish; + scriptenv.duplicate_mark = NULL; + scriptenv.duplicate_check = NULL; + scriptenv.trace_log = eenv->scriptenv->trace_log; + scriptenv.trace_config = eenv->scriptenv->trace_config; + scriptenv.exec_status = &exec_status; + + /* Start execution */ + + mscript = sieve_multiscript_start_execute(svinst, eenv->msgdata, + &scriptenv); + + /* Execute scripts before main script */ + + scripts = array_get(scriptfiles, &count); + for (i = 0; i < count && more; i++) { + struct sieve_binary *sbin = NULL; + const char *script = scripts[i]; + + /* Open */ + if ((sbin = _testsuite_script_compile(renv, script)) == NULL) { + result = FALSE; + break; + } + + /* Execute */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "run script `%s'", script); + + more = sieve_multiscript_run(mscript, sbin, + testsuite_log_ehandler, + testsuite_log_ehandler, 0); + + sieve_close(&sbin); + } + + return (sieve_multiscript_finish(&mscript, testsuite_log_ehandler, + 0, SIEVE_EXEC_OK) > 0 && result); +} diff --git a/pigeonhole/src/testsuite/testsuite-script.h b/pigeonhole/src/testsuite/testsuite-script.h new file mode 100644 index 0000000..547fdfc --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-script.h @@ -0,0 +1,22 @@ +#ifndef TESTSUITE_SCRIPT_H +#define TESTSUITE_SCRIPT_H + +#include "sieve-common.h" + +void testsuite_script_init(void); +void testsuite_script_deinit(void); + +bool testsuite_script_is_subtest(const struct sieve_runtime_env *renv); + +bool testsuite_script_compile(const struct sieve_runtime_env *renv, + const char *script); +bool testsuite_script_run(const struct sieve_runtime_env *renv); +bool testsuite_script_multiscript(const struct sieve_runtime_env *renv, + ARRAY_TYPE (const_string) *scriptfiles); + +struct sieve_binary * +testsuite_script_get_binary(const struct sieve_runtime_env *renv); +void testsuite_script_set_binary(const struct sieve_runtime_env *renv, + struct sieve_binary *sbin); + +#endif diff --git a/pigeonhole/src/testsuite/testsuite-settings.c b/pigeonhole/src/testsuite/testsuite-settings.c new file mode 100644 index 0000000..9d3c872 --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-settings.c @@ -0,0 +1,96 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "hash.h" +#include "imem.h" +#include "strfuncs.h" +#include "mail-user.h" + +#include "sieve-common.h" + +#include "testsuite-common.h" +#include "testsuite-mailstore.h" +#include "testsuite-settings.h" + +struct testsuite_setting { + char *identifier; + char *value; +}; + +static HASH_TABLE(const char *, struct testsuite_setting *) settings; + +static const char *testsuite_setting_get + (void *context, const char *identifier); + +void testsuite_settings_init(void) +{ + hash_table_create(&settings, default_pool, 0, str_hash, strcmp); + + sieve_tool_set_setting_callback(sieve_tool, testsuite_setting_get, NULL); +} + +void testsuite_settings_deinit(void) +{ + struct hash_iterate_context *itx = + hash_table_iterate_init(settings); + const char *key; + struct testsuite_setting *setting; + + while ( hash_table_iterate(itx, settings, &key, &setting) ) { + i_free(setting->identifier); + i_free(setting->value); + i_free(setting); + } + + hash_table_iterate_deinit(&itx); + + hash_table_destroy(&settings); +} + +static const char *testsuite_setting_get +(void *context ATTR_UNUSED, const char *identifier) +{ + struct testsuite_setting *setting; + struct mail_user *user; + + setting = hash_table_lookup(settings, identifier); + if ( setting != NULL ) + return setting->value; + + user = testsuite_mailstore_get_user(); + if ( user == NULL ) + return NULL; + return mail_user_plugin_getenv(user, identifier); +} + +void testsuite_setting_set(const char *identifier, const char *value) +{ + struct testsuite_setting *setting = + hash_table_lookup(settings, identifier); + + if ( setting != NULL ) { + i_free(setting->value); + setting->value = i_strdup(value); + } else { + setting = i_new(struct testsuite_setting, 1); + setting->identifier = i_strdup(identifier); + setting->value = i_strdup(value); + + hash_table_insert(settings, identifier, setting); + } +} + +void testsuite_setting_unset(const char *identifier) +{ + struct testsuite_setting *setting = + hash_table_lookup(settings, identifier); + + if ( setting != NULL ) { + i_free(setting->identifier); + i_free(setting->value); + i_free(setting); + + hash_table_remove(settings, identifier); + } +} diff --git a/pigeonhole/src/testsuite/testsuite-settings.h b/pigeonhole/src/testsuite/testsuite-settings.h new file mode 100644 index 0000000..b84e620 --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-settings.h @@ -0,0 +1,12 @@ +#ifndef TESTSUITE_SETTINGS_H +#define TESTSUITE_SETTINGS_H + +#include "sieve-common.h" + +void testsuite_settings_init(void); +void testsuite_settings_deinit(void); + +void testsuite_setting_set(const char *identifier, const char *value); +void testsuite_setting_unset(const char *identifier); + +#endif diff --git a/pigeonhole/src/testsuite/testsuite-smtp.c b/pigeonhole/src/testsuite/testsuite-smtp.c new file mode 100644 index 0000000..0eb40ac --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-smtp.c @@ -0,0 +1,176 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "ostream.h" +#include "unlink-directory.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-interpreter.h" + +#include "testsuite-message.h" +#include "testsuite-common.h" +#include "testsuite-smtp.h" + +#include <unistd.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> + +struct testsuite_smtp_message { + const struct smtp_address *envelope_from, *envelope_to; + const char *file; +}; + +static pool_t testsuite_smtp_pool; +static const char *testsuite_smtp_tmp; +static ARRAY(struct testsuite_smtp_message) testsuite_smtp_messages; + +/* + * Initialize + */ + +void testsuite_smtp_init(void) +{ + pool_t pool; + + testsuite_smtp_pool = pool = pool_alloconly_create("testsuite_smtp", 8192); + + testsuite_smtp_tmp = p_strconcat + (pool, testsuite_tmp_dir_get(), "/smtp", NULL); + + if ( mkdir(testsuite_smtp_tmp, 0700) < 0 ) { + i_fatal("failed to create temporary directory '%s': %m.", + testsuite_smtp_tmp); + } + + p_array_init(&testsuite_smtp_messages, pool, 16); +} + +void testsuite_smtp_deinit(void) +{ + const char *error; + + if ( unlink_directory(testsuite_smtp_tmp, UNLINK_DIRECTORY_FLAG_RMDIR, &error) < 0 ) + i_warning("failed to remove temporary directory '%s': %s.", + testsuite_smtp_tmp, error); + + pool_unref(&testsuite_smtp_pool); +} + +void testsuite_smtp_reset(void) +{ + testsuite_smtp_deinit(); + testsuite_smtp_init(); +} + +/* + * Simulated SMTP out + */ + +struct testsuite_smtp { + char *msg_file; + struct smtp_address *mail_from; + struct ostream *output; +}; + +void *testsuite_smtp_start +(const struct sieve_script_env *senv ATTR_UNUSED, + const struct smtp_address *mail_from) +{ + struct testsuite_smtp *smtp; + unsigned int smtp_count = array_count(&testsuite_smtp_messages); + int fd; + + smtp = i_new(struct testsuite_smtp, 1); + + smtp->msg_file = i_strdup_printf("%s/%d.eml", testsuite_smtp_tmp, smtp_count); + smtp->mail_from = smtp_address_clone(default_pool, mail_from); + + if ( (fd=open(smtp->msg_file, O_WRONLY | O_CREAT, 0600)) < 0 ) { + i_fatal("failed create tmp file for SMTP simulation: open(%s) failed: %m", + smtp->msg_file); + } + + smtp->output = o_stream_create_fd_autoclose(&fd, (size_t)-1); + + return (void *) smtp; +} + +void testsuite_smtp_add_rcpt +(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle, const struct smtp_address *rcpt_to) +{ + struct testsuite_smtp *smtp = (struct testsuite_smtp *) handle; + struct testsuite_smtp_message *msg; + + msg = array_append_space(&testsuite_smtp_messages); + + msg->file = p_strdup(testsuite_smtp_pool, smtp->msg_file); + msg->envelope_from = smtp_address_clone(testsuite_smtp_pool, smtp->mail_from); + msg->envelope_to = smtp_address_clone(testsuite_smtp_pool, rcpt_to); +} + +struct ostream *testsuite_smtp_send +(const struct sieve_script_env *senv ATTR_UNUSED, void *handle) +{ + struct testsuite_smtp *smtp = (struct testsuite_smtp *) handle; + + return smtp->output; +} + +void testsuite_smtp_abort +(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle) +{ + struct testsuite_smtp *smtp = (struct testsuite_smtp *) handle; + + o_stream_ignore_last_errors(smtp->output); + o_stream_unref(&smtp->output); + i_unlink(smtp->msg_file); + i_free(smtp->msg_file); + i_free(smtp->mail_from); + i_free(smtp); +} + +int testsuite_smtp_finish +(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle, const char **error_r ATTR_UNUSED) +{ + struct testsuite_smtp *smtp = (struct testsuite_smtp *) handle; + int ret = 1; + + if (o_stream_finish(smtp->output) < 0) { + i_error("write(%s) failed: %s", smtp->msg_file, + o_stream_get_error(smtp->output)); + ret = -1; + } + o_stream_unref(&smtp->output); + i_free(smtp->msg_file); + i_free(smtp->mail_from); + i_free(smtp); + return ret; +} + +/* + * Access + */ + +bool testsuite_smtp_get +(const struct sieve_runtime_env *renv, unsigned int index) +{ + const struct testsuite_smtp_message *smtp_msg; + + if ( index >= array_count(&testsuite_smtp_messages) ) + return FALSE; + + smtp_msg = array_idx(&testsuite_smtp_messages, index); + + testsuite_message_set_file(renv, smtp_msg->file); + testsuite_envelope_set_sender_address(renv, smtp_msg->envelope_from); + testsuite_envelope_set_recipient_address(renv, smtp_msg->envelope_to); + + return TRUE; +} diff --git a/pigeonhole/src/testsuite/testsuite-smtp.h b/pigeonhole/src/testsuite/testsuite-smtp.h new file mode 100644 index 0000000..0b120b2 --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-smtp.h @@ -0,0 +1,35 @@ +#ifndef TESTSUITE_SMTP_H +#define TESTSUITE_SMTP_H + +void testsuite_smtp_init(void); +void testsuite_smtp_deinit(void); +void testsuite_smtp_reset(void); + +/* + * Simulated SMTP out + */ + +void *testsuite_smtp_start + (const struct sieve_script_env *senv ATTR_UNUSED, + const struct smtp_address *mail_from); +void testsuite_smtp_add_rcpt + (const struct sieve_script_env *senv ATTR_UNUSED, + void *handle, const struct smtp_address *rcpt_to); +struct ostream *testsuite_smtp_send + (const struct sieve_script_env *senv ATTR_UNUSED, + void *handle); +void testsuite_smtp_abort + (const struct sieve_script_env *senv ATTR_UNUSED, + void *handle); +int testsuite_smtp_finish + (const struct sieve_script_env *senv ATTR_UNUSED, + void *handle, const char **error_r); + +/* + * Access + */ + +bool testsuite_smtp_get + (const struct sieve_runtime_env *renv, unsigned int index); + +#endif diff --git a/pigeonhole/src/testsuite/testsuite-substitutions.c b/pigeonhole/src/testsuite/testsuite-substitutions.c new file mode 100644 index 0000000..b165587 --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-substitutions.c @@ -0,0 +1,253 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve.h" +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-binary.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "testsuite-common.h" +#include "testsuite-substitutions.h" + +/* + * Forward declarations + */ + +void testsuite_opr_substitution_emit + (struct sieve_binary_block *sblock, const struct testsuite_substitution *tsub, + const char *param); + +/* + * Testsuite substitutions + */ + +/* FIXME: make this extendible */ + +enum { + TESTSUITE_SUBSTITUTION_FILE, +}; + +static const struct testsuite_substitution_def testsuite_file_substitution; + +static const struct testsuite_substitution_def *substitutions[] = { + &testsuite_file_substitution, +}; + +static const unsigned int substitutions_count = N_ELEMENTS(substitutions); + +static inline const struct testsuite_substitution_def * +testsuite_substitution_get +(unsigned int code) +{ + if ( code >= substitutions_count ) + return NULL; + + return substitutions[code]; +} + +static const struct testsuite_substitution *testsuite_substitution_create +(struct sieve_ast *ast, const char *identifier) +{ + unsigned int i; + + for ( i = 0; i < substitutions_count; i++ ) { + if ( strcasecmp(substitutions[i]->obj_def.identifier, identifier) == 0 ) { + const struct testsuite_substitution_def *tsub_def = substitutions[i]; + struct testsuite_substitution *tsub; + + tsub = p_new(sieve_ast_pool(ast), struct testsuite_substitution, 1); + tsub->object.def = &tsub_def->obj_def; + tsub->object.ext = testsuite_ext; + tsub->def = tsub_def; + + return tsub; + } + } + + return NULL; +} + +/* + * Substitution argument + */ + +static bool arg_testsuite_substitution_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *context); + +struct _testsuite_substitution_context { + const struct testsuite_substitution *tsub; + const char *param; +}; + +const struct sieve_argument_def testsuite_substitution_argument = { + .identifier = "@testsuite-substitution", + .generate = arg_testsuite_substitution_generate +}; + +struct sieve_ast_argument *testsuite_substitution_argument_create +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_ast *ast, + unsigned int source_line, const char *substitution, const char *param) +{ + const struct testsuite_substitution *tsub; + struct _testsuite_substitution_context *tsctx; + struct sieve_ast_argument *arg; + pool_t pool; + + tsub = testsuite_substitution_create(ast, substitution); + if ( tsub == NULL ) + return NULL; + + arg = sieve_ast_argument_create(ast, source_line); + arg->type = SAAT_STRING; + + pool = sieve_ast_pool(ast); + tsctx = p_new(pool, struct _testsuite_substitution_context, 1); + tsctx->tsub = tsub; + tsctx->param = p_strdup(pool, param); + + arg->argument = sieve_argument_create + (ast, &testsuite_substitution_argument, testsuite_ext, 0); + arg->argument->data = (void *) tsctx; + + return arg; +} + +static bool arg_testsuite_substitution_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *context ATTR_UNUSED) +{ + struct _testsuite_substitution_context *tsctx = + (struct _testsuite_substitution_context *) arg->argument->data; + + testsuite_opr_substitution_emit(cgenv->sblock, tsctx->tsub, tsctx->param); + + return TRUE; +} + +/* + * Substitution operand + */ + +static bool opr_substitution_dump + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); +static int opr_substitution_read_value + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str); + +const struct sieve_opr_string_interface testsuite_substitution_interface = { + opr_substitution_dump, + opr_substitution_read_value +}; + +const struct sieve_operand_def testsuite_substitution_operand = { + .name = "test-substitution", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERAND_SUBSTITUTION, + .class = &string_class, + .interface = &testsuite_substitution_interface +}; + +void testsuite_opr_substitution_emit +(struct sieve_binary_block *sblock, const struct testsuite_substitution *tsub, + const char *param) +{ + /* Default variable storage */ + (void) sieve_operand_emit + (sblock, testsuite_ext, &testsuite_substitution_operand); + (void) sieve_binary_emit_unsigned(sblock, tsub->object.def->code); + (void) sieve_binary_emit_cstring(sblock, param); +} + +static bool opr_substitution_dump +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) +{ + unsigned int code = 0; + const struct testsuite_substitution_def *tsub; + string_t *param; + + if ( !sieve_binary_read_unsigned(denv->sblock, address, &code) ) + return FALSE; + + tsub = testsuite_substitution_get(code); + if ( tsub == NULL ) + return FALSE; + + if ( !sieve_binary_read_string(denv->sblock, address, ¶m) ) + return FALSE; + + if ( oprnd->field_name != NULL ) + sieve_code_dumpf(denv, "%s: TEST_SUBS %%{%s:%s}", + oprnd->field_name, tsub->obj_def.identifier, str_c(param)); + else + sieve_code_dumpf(denv, "TEST_SUBS %%{%s:%s}", + tsub->obj_def.identifier, str_c(param)); + return TRUE; +} + +static int opr_substitution_read_value +(const struct sieve_runtime_env *renv, + const struct sieve_operand *oprnd ATTR_UNUSED, sieve_size_t *address, + string_t **str_r) +{ + const struct testsuite_substitution_def *tsub; + unsigned int code = 0; + string_t *param; + + if ( !sieve_binary_read_unsigned(renv->sblock, address, &code) ) + return SIEVE_EXEC_BIN_CORRUPT; + + tsub = testsuite_substitution_get(code); + if ( tsub == NULL ) + return SIEVE_EXEC_FAILURE; + + /* Parameter str can be NULL if we are requested to only skip and not + * actually read the argument. + */ + if ( str_r == NULL ) { + if ( !sieve_binary_read_string(renv->sblock, address, NULL) ) + return SIEVE_EXEC_BIN_CORRUPT; + + return SIEVE_EXEC_OK; + } + + if ( !sieve_binary_read_string(renv->sblock, address, ¶m) ) + return SIEVE_EXEC_BIN_CORRUPT; + + if ( !tsub->get_value(str_c(param), str_r) ) + return SIEVE_EXEC_FAILURE; + + return SIEVE_EXEC_OK; +} + +/* + * Testsuite substitution definitions + */ + +static bool testsuite_file_substitution_get_value + (const char *param, string_t **result); + +static const struct testsuite_substitution_def +testsuite_file_substitution = { + SIEVE_OBJECT("file", + &testsuite_substitution_operand, + TESTSUITE_SUBSTITUTION_FILE), + .get_value = testsuite_file_substitution_get_value +}; + +static bool testsuite_file_substitution_get_value +(const char *param, string_t **result) +{ + *result = t_str_new(256); + + str_printfa(*result, "[FILE: %s]", param); + return TRUE; +} + diff --git a/pigeonhole/src/testsuite/testsuite-substitutions.h b/pigeonhole/src/testsuite/testsuite-substitutions.h new file mode 100644 index 0000000..8b256d0 --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-substitutions.h @@ -0,0 +1,23 @@ +#ifndef TESTSUITE_SUBSTITUTIONS_H +#define TESTSUITE_SUBSTITUTIONS_H + +#include "sieve-common.h" +#include "sieve-objects.h" + +struct testsuite_substitution_def { + struct sieve_object_def obj_def; + + bool (*get_value)(const char *param, string_t **result); +}; + +struct testsuite_substitution { + struct sieve_object object; + + const struct testsuite_substitution_def *def; +}; + +struct sieve_ast_argument *testsuite_substitution_argument_create + (struct sieve_validator *valdtr, struct sieve_ast *ast, + unsigned int source_line, const char *substitution, const char *param); + +#endif diff --git a/pigeonhole/src/testsuite/testsuite-variables.c b/pigeonhole/src/testsuite/testsuite-variables.c new file mode 100644 index 0000000..f644393 --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-variables.c @@ -0,0 +1,183 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-ast.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "testsuite-common.h" +#include "testsuite-variables.h" + +/* + * + */ + +static const struct sieve_extension *testsuite_ext_variables = NULL; + +/* + * + */ + +bool testsuite_varnamespace_validate + (struct sieve_validator *valdtr, const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg, struct sieve_command *cmd, + ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, + bool assignment); +bool testsuite_varnamespace_generate + (const struct sieve_codegen_env *cgenv, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg, struct sieve_command *cmd, void *var_data); +bool testsuite_varnamespace_dump_variable + (const struct sieve_dumptime_env *denv, + const struct sieve_variables_namespace *nspc, + const struct sieve_operand *oprnd, sieve_size_t *address); +int testsuite_varnamespace_read_variable + (const struct sieve_runtime_env *renv, + const struct sieve_variables_namespace *nspc, + const struct sieve_operand *oprnd, sieve_size_t *address, string_t **str_r); + +static const struct sieve_variables_namespace_def testsuite_namespace = { + SIEVE_OBJECT("tst", &testsuite_namespace_operand, 0), + testsuite_varnamespace_validate, + testsuite_varnamespace_generate, + testsuite_varnamespace_dump_variable, + testsuite_varnamespace_read_variable +}; + +bool testsuite_varnamespace_validate +(struct sieve_validator *valdtr, + const struct sieve_variables_namespace *nspc ATTR_UNUSED, + struct sieve_ast_argument *arg, struct sieve_command *cmd ATTR_UNUSED, + ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, + bool assignment) +{ + struct sieve_ast *ast = arg->ast; + const struct sieve_variable_name *name_element; + const char *variable; + + /* Check variable name */ + + if ( array_count(var_name) != 2 ) { + sieve_argument_validate_error(valdtr, arg, + "testsuite: invalid variable name within testsuite namespace: " + "encountered sub-namespace"); + return FALSE; + } + + name_element = array_idx(var_name, 1); + if ( name_element->num_variable >= 0 ) { + sieve_argument_validate_error(valdtr, arg, + "testsuite: invalid variable name within testsuite namespace 'tst.%d': " + "encountered numeric variable name", name_element->num_variable); + return FALSE; + } + + variable = str_c(name_element->identifier); + + if ( assignment ) { + sieve_argument_validate_error(valdtr, arg, + "testsuite: cannot assign to testsuite variable 'tst.%s'", variable); + return FALSE; + } + + *var_data = (void *) p_strdup(sieve_ast_pool(ast), variable); + + return TRUE; +} + +bool testsuite_varnamespace_generate +(const struct sieve_codegen_env *cgenv, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg ATTR_UNUSED, + struct sieve_command *cmd ATTR_UNUSED, void *var_data) +{ + const struct sieve_extension *this_ext = SIEVE_OBJECT_EXTENSION(nspc); + const char *variable = (const char *) var_data; + + if ( this_ext == NULL ) + return FALSE; + + sieve_variables_opr_namespace_variable_emit + (cgenv->sblock, testsuite_ext_variables, this_ext, &testsuite_namespace); + sieve_binary_emit_cstring(cgenv->sblock, variable); + + return TRUE; +} + +bool testsuite_varnamespace_dump_variable +(const struct sieve_dumptime_env *denv, + const struct sieve_variables_namespace *nspc ATTR_UNUSED, + const struct sieve_operand *oprnd, sieve_size_t *address) +{ + string_t *var_name; + + if ( !sieve_binary_read_string(denv->sblock, address, &var_name) ) + return FALSE; + + if ( oprnd->field_name != NULL ) + sieve_code_dumpf(denv, "%s: VAR ${tst.%s}", + oprnd->field_name, str_c(var_name)); + else + sieve_code_dumpf(denv, "VAR ${tst.%s}", + str_c(var_name)); + + return TRUE; +} + +int testsuite_varnamespace_read_variable +(const struct sieve_runtime_env *renv, + const struct sieve_variables_namespace *nspc ATTR_UNUSED, + const struct sieve_operand *oprnd, sieve_size_t *address, + string_t **str_r) +{ + string_t *var_name; + + if ( !sieve_binary_read_string(renv->sblock, address, &var_name) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "testsuite variable operand corrupt: invalid name"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( str_r != NULL ) { + if ( strcmp(str_c(var_name), "path") == 0 ) + *str_r = t_str_new_const(testsuite_test_path, strlen(testsuite_test_path)); + else + *str_r = NULL; + } + return SIEVE_EXEC_OK; +} + + +/* + * Namespace registration + */ + +static const struct sieve_extension_objects testsuite_namespaces = + SIEVE_VARIABLES_DEFINE_NAMESPACE(testsuite_namespace); + +const struct sieve_operand_def testsuite_namespace_operand = { + .name = "testsuite-namespace", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERAND_NAMESPACE, + .class = &sieve_variables_namespace_operand_class, + .interface = &testsuite_namespaces +}; + +void testsuite_variables_init +(const struct sieve_extension *this_ext, struct sieve_validator *valdtr) +{ + testsuite_ext_variables = sieve_ext_variables_get_extension(this_ext->svinst); + + sieve_variables_namespace_register + (testsuite_ext_variables, valdtr, this_ext, &testsuite_namespace); +} diff --git a/pigeonhole/src/testsuite/testsuite-variables.h b/pigeonhole/src/testsuite/testsuite-variables.h new file mode 100644 index 0000000..60f6b18 --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-variables.h @@ -0,0 +1,11 @@ +#ifndef TESTSUITE_VARIABLES_H +#define TESTSUITE_VARIABLES_H + +extern const struct sieve_operand_def testsuite_namespace_operand; + +void testsuite_variables_init + (const struct sieve_extension *this_ext, struct sieve_validator *valdtr); + +#endif + + diff --git a/pigeonhole/src/testsuite/testsuite.c b/pigeonhole/src/testsuite/testsuite.c new file mode 100644 index 0000000..2a6b82e --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite.c @@ -0,0 +1,256 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "lib-signals.h" +#include "ioloop.h" +#include "env-util.h" +#include "ostream.h" +#include "hostpid.h" +#include "path-util.h" + +#include "sieve.h" +#include "sieve-extensions.h" +#include "sieve-script.h" +#include "sieve-binary.h" +#include "sieve-result.h" +#include "sieve-interpreter.h" + +#include "sieve-tool.h" + +#include "testsuite-common.h" +#include "testsuite-log.h" +#include "testsuite-settings.h" +#include "testsuite-result.h" +#include "testsuite-message.h" +#include "testsuite-smtp.h" +#include "testsuite-mailstore.h" + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <pwd.h> +#include <sysexits.h> + +const struct sieve_script_env *testsuite_scriptenv; + +/* + * Configuration + */ + +#define DEFAULT_SENDMAIL_PATH "/usr/lib/sendmail" + +/* + * Testsuite execution + */ + +static void print_help(void) +{ + printf( +"Usage: testsuite [-D] [-E] [-F] [-d <dump-filename>]\n" +" [-t <trace-filename>] [-T <trace-option>]\n" +" [-P <plugin>] [-x <extensions>]\n" +" <scriptfile>\n" + ); +} + +static int +testsuite_run(struct sieve_binary *sbin, struct sieve_error_handler *ehandler) +{ + struct sieve_interpreter *interp; + struct sieve_result *result; + int ret = 0; + + /* Create the interpreter */ + interp = sieve_interpreter_create(sbin, NULL, &testsuite_execute_env, + ehandler); + if (interp == NULL) + return SIEVE_EXEC_BIN_CORRUPT; + + /* Run the interpreter */ + result = testsuite_result_get(); + ret = sieve_interpreter_run(interp, result); + + /* Free the interpreter */ + sieve_interpreter_free(&interp); + + return ret; +} + +int main(int argc, char **argv) +{ + struct sieve_instance *svinst; + const char *scriptfile, *dumpfile, *tracefile; + struct sieve_trace_config trace_config; + struct sieve_binary *sbin; + const char *sieve_dir, *cwd, *error; + bool log_stdout = FALSE, expect_failure = FALSE; + int ret, c; + + sieve_tool = sieve_tool_init("testsuite", &argc, &argv, + "d:t:T:EFDP:", TRUE); + + /* Parse arguments */ + dumpfile = tracefile = NULL; + i_zero(&trace_config); + trace_config.level = SIEVE_TRLVL_ACTIONS; + while ((c = sieve_tool_getopt(sieve_tool)) > 0) { + switch (c) { + case 'd': + /* destination address */ + dumpfile = optarg; + break; + case 't': + /* trace file */ + tracefile = optarg; + break; + case 'T': + sieve_tool_parse_trace_option(&trace_config, optarg); + break; + case 'E': + log_stdout = TRUE; + break; + case 'F': + expect_failure = TRUE; + break; + default: + print_help(); + i_fatal_status(EX_USAGE, "Unknown argument: %c", c); + break; + } + } + + if (optind < argc) { + scriptfile = t_strdup(argv[optind++]); + } else { + print_help(); + i_fatal_status(EX_USAGE, "Missing <scriptfile> argument"); + } + + if (optind != argc) { + print_help(); + i_fatal_status(EX_USAGE, "Unknown argument: %s", argv[optind]); + } + + // FIXME: very very ugly + master_service_parse_option( + master_service, 'o', + "postmaster_address=postmaster@example.com"); + + /* Initialize mail user */ + if (t_get_working_dir(&cwd, &error) < 0) + i_fatal("Failed to get working directory: %s", error); + sieve_tool_set_homedir(sieve_tool, cwd); + + /* Initialize settings environment */ + testsuite_settings_init(); + + /* Currently needed for include (FIXME) */ + sieve_dir = strrchr(scriptfile, '/'); + if (sieve_dir == NULL) + sieve_dir = "./"; + else + sieve_dir = t_strdup_until(scriptfile, sieve_dir+1); + + testsuite_setting_set("sieve_dir", + t_strconcat(sieve_dir, "included", NULL)); + testsuite_setting_set("sieve_global_dir", + t_strconcat(sieve_dir, "included-global", NULL)); + + /* Finish testsuite initialization */ + svinst = sieve_tool_init_finish(sieve_tool, FALSE, FALSE); + testsuite_init(svinst, sieve_dir, log_stdout); + + printf("Test case: %s:\n\n", scriptfile); + + /* Compile sieve script */ + if ((sbin = sieve_compile(svinst, scriptfile, NULL, + testsuite_log_main_ehandler, + 0, NULL)) != NULL) { + struct sieve_trace_log *trace_log = NULL; + struct sieve_exec_status exec_status; + struct sieve_script_env scriptenv; + + /* Dump script */ + sieve_tool_dump_binary_to(sbin, dumpfile, FALSE); + + if (tracefile != NULL) { + (void)sieve_trace_log_create( + svinst, (strcmp(tracefile, "-") == 0 ? + NULL : tracefile), &trace_log); + } + + testsuite_mailstore_init(); + testsuite_message_init(); + + if (sieve_script_env_init(&scriptenv, + testsuite_mailstore_get_user(), + &error) < 0) { + i_fatal("Failed to initialize script execution: %s", + error); + } + + i_zero(&exec_status); + + scriptenv.default_mailbox = "INBOX"; + scriptenv.smtp_start = testsuite_smtp_start; + scriptenv.smtp_add_rcpt = testsuite_smtp_add_rcpt; + scriptenv.smtp_send = testsuite_smtp_send; + scriptenv.smtp_abort = testsuite_smtp_abort; + scriptenv.smtp_finish = testsuite_smtp_finish; + scriptenv.trace_log = trace_log; + scriptenv.trace_config = trace_config; + scriptenv.exec_status = &exec_status; + + testsuite_scriptenv = &scriptenv; + + testsuite_result_init(); + + /* Run the test */ + ret = testsuite_run(sbin, testsuite_log_main_ehandler); + + switch (ret) { + case SIEVE_EXEC_OK: + break; + case SIEVE_EXEC_FAILURE: + case SIEVE_EXEC_KEEP_FAILED: + case SIEVE_EXEC_TEMP_FAILURE: + testsuite_testcase_fail( + "test script execution aborted due to error"); + break; + case SIEVE_EXEC_BIN_CORRUPT: + testsuite_testcase_fail( + "compiled test script binary is corrupt"); + break; + case SIEVE_EXEC_RESOURCE_LIMIT: + testsuite_testcase_fail( + "resource limit exceeded"); + break; + } + + sieve_close(&sbin); + + /* De-initialize message environment */ + testsuite_result_deinit(); + testsuite_message_deinit(); + testsuite_mailstore_deinit(); + + if (trace_log != NULL) + sieve_trace_log_free(&trace_log); + + testsuite_scriptenv = NULL; + } else { + testsuite_testcase_fail("failed to compile testcase script"); + } + + /* De-initialize testsuite */ + testsuite_deinit(); + testsuite_settings_deinit(); + + sieve_tool_deinit(&sieve_tool); + + if (!testsuite_testcase_result(expect_failure)) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} diff --git a/pigeonhole/src/testsuite/tst-test-error.c b/pigeonhole/src/testsuite/tst-test-error.c new file mode 100644 index 0000000..f2f2eb9 --- /dev/null +++ b/pigeonhole/src/testsuite/tst-test-error.c @@ -0,0 +1,273 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-script.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "testsuite-common.h" +#include "testsuite-log.h" + +/* + * Test_error command + * + * Syntax: + * test [MATCH-TYPE] [COMPARATOR] [:index number] <key-list: string-list> + */ + +static bool tst_test_error_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool tst_test_error_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool tst_test_error_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def tst_test_error = { + .identifier = "test_error", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_test_error_registered, + .validate = tst_test_error_validate, + .generate = tst_test_error_generate +}; + +/* + * Operation + */ + +static bool tst_test_error_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_test_error_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def test_error_operation = { + .mnemonic = "TEST_ERROR", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_ERROR, + .dump = tst_test_error_operation_dump, + .execute = tst_test_error_operation_execute +}; + +/* + * Tagged arguments + */ + +/* NOTE: This will be merged with the date-index extension when it is + * implemented. + */ + +static bool tst_test_error_validate_index_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +static const struct sieve_argument_def test_error_index_tag = { + .identifier = "index", + .validate = tst_test_error_validate_index_tag +}; + +enum tst_test_error_optional { + OPT_INDEX = SIEVE_MATCH_OPT_LAST, +}; + + +/* + * Argument implementation + */ + +static bool tst_test_error_validate_index_tag +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :index number + */ + if ( !sieve_validate_tag_parameter + (valdtr, cmd, tag, *arg, NULL, 0, SAAT_NUMBER, FALSE) ) { + return FALSE; + } + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + return TRUE; +} + + +/* + * Command registration + */ + +static bool tst_test_error_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &test_error_index_tag, OPT_INDEX); + + return TRUE; +} + +/* + * Validation + */ + +static bool tst_test_error_validate +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_octet_comparator); + struct sieve_match_type mcht_default = + SIEVE_COMPARATOR_DEFAULT(is_match_type); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "key list", 2, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate + (valdtr, tst, arg, &mcht_default, &cmp_default); +} + +/* + * Code generation + */ + +static bool tst_test_error_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *tst) +{ + sieve_operation_emit(cgenv->sblock, tst->ext, &test_error_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool tst_test_error_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "TEST_ERROR:"); + sieve_code_descend(denv); + + /* Handle any optional arguments */ + for (;;) { + int opt; + + if ( (opt=sieve_match_opr_optional_dump(denv, address, &opt_code)) + < 0 ) + return FALSE; + + if ( opt == 0 ) break; + + if ( opt_code == OPT_INDEX ) { + if ( !sieve_opr_number_dump(denv, address, "index") ) + return FALSE; + } else { + return FALSE; + } + } + + return sieve_opr_stringlist_dump(denv, address, "key list"); +} + +/* + * Intepretation + */ + +static int tst_test_error_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + int opt_code = 0; + struct sieve_comparator cmp = SIEVE_COMPARATOR_DEFAULT(i_octet_comparator); + struct sieve_match_type mcht = SIEVE_COMPARATOR_DEFAULT(is_match_type); + struct sieve_stringlist *value_list, *key_list; + int index = -1; + int match, ret; + + /* + * Read operands + */ + + /* Read optional operands */ + for (;;) { + sieve_number_t number; + int opt; + + if ( (opt=sieve_match_opr_optional_read + (renv, address, &opt_code, &ret, &cmp, &mcht)) < 0 ) + return ret; + + if ( opt == 0 ) break; + + if ( opt_code == OPT_INDEX ) { + if ( (ret=sieve_opr_number_read(renv, address, "index", &number)) <= 0 ) + return ret; + index = (int) number; + } else { + sieve_runtime_trace_error(renv, "invalid optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + } + + /* Read key-list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "key_list", &key_list)) + <= 0 ) + return ret; + + /* + * Perform operation + */ + + if ( index > 0 ) + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "testsuite: test_error test; match error message [index=%d]", index); + else + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "testsuite: test_error test; match error messages"); + + /* Create value stringlist */ + value_list = testsuite_log_stringlist_create(renv, index); + + /* Perform match */ + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} + + + + diff --git a/pigeonhole/src/testsuite/tst-test-multiscript.c b/pigeonhole/src/testsuite/tst-test-multiscript.c new file mode 100644 index 0000000..b4b2a0e --- /dev/null +++ b/pigeonhole/src/testsuite/tst-test-multiscript.c @@ -0,0 +1,155 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-script.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-dump.h" +#include "sieve.h" + +#include "testsuite-common.h" +#include "testsuite-script.h" + +/* + * Test_multiscript command + * + * Syntax: + * test_multiscript <scripts: string-list> + */ + +static bool tst_test_multiscript_validate + (struct sieve_validator *validator, struct sieve_command *cmd); +static bool tst_test_multiscript_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *tst); + +const struct sieve_command_def tst_test_multiscript = { + .identifier = "test_multiscript", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = tst_test_multiscript_validate, + .generate = tst_test_multiscript_generate, +}; + +/* + * Operation + */ + +static bool tst_test_multiscript_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_test_multiscript_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def test_multiscript_operation = { + .mnemonic = "TEST_MULTISCRIPT", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_MULTISCRIPT, + .dump = tst_test_multiscript_operation_dump, + .execute = tst_test_multiscript_operation_execute +}; + +/* + * Validation + */ + +static bool tst_test_multiscript_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "scripts", 1, SAAT_STRING_LIST) ) { + return FALSE; + } + + return sieve_validator_argument_activate(valdtr, tst, arg, FALSE); +} + +/* + * Code generation + */ + +static bool tst_test_multiscript_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *tst) +{ + sieve_operation_emit(cgenv->sblock, tst->ext, &test_multiscript_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool tst_test_multiscript_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "TEST_MULTISCRIPT:"); + sieve_code_descend(denv); + + if ( !sieve_opr_stringlist_dump(denv, address, "scripts") ) + return FALSE; + + return TRUE; +} + +/* + * Intepretation + */ + +static int tst_test_multiscript_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_stringlist *scripts_list; + string_t *script_name; + ARRAY_TYPE (const_string) scriptfiles; + bool result = TRUE; + int ret; + + /* + * Read operands + */ + + if ( (ret=sieve_opr_stringlist_read(renv, address, "scripts", &scripts_list)) + <= 0 ) + return ret; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "testsuite: test_multiscript test"); + sieve_runtime_trace_descend(renv); + + t_array_init(&scriptfiles, 16); + + script_name = NULL; + while ( result && + (ret=sieve_stringlist_next_item(scripts_list, &script_name)) > 0 ) { + const char *script = t_strdup(str_c(script_name)); + + array_append(&scriptfiles, &script, 1); + } + + result = result && (ret >= 0) && + testsuite_script_multiscript(renv, &scriptfiles); + + /* Set result */ + sieve_interpreter_set_test_result(renv->interp, result); + + return SIEVE_EXEC_OK; +} + + + + diff --git a/pigeonhole/src/testsuite/tst-test-result-action.c b/pigeonhole/src/testsuite/tst-test-result-action.c new file mode 100644 index 0000000..75d4a2f --- /dev/null +++ b/pigeonhole/src/testsuite/tst-test-result-action.c @@ -0,0 +1,268 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-script.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-result.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "testsuite-common.h" +#include "testsuite-result.h" + +/* + * test_result_action command + * + * Syntax: + * test_result_action [MATCH-TYPE] [COMPARATOR] [:index number] + * <key-list: string-list> + */ + +static bool tst_test_result_action_registered + (struct sieve_validator *validator, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool tst_test_result_action_validate + (struct sieve_validator *validator, struct sieve_command *cmd); +static bool tst_test_result_action_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def tst_test_result_action = { + .identifier = "test_result_action", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_test_result_action_registered, + .validate = tst_test_result_action_validate, + .generate = tst_test_result_action_generate +}; + +/* + * Operation + */ + +static bool tst_test_result_action_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_test_result_action_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def test_result_action_operation = { + .mnemonic = "TEST_RESULT_ACTION", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_RESULT_ACTION, + .dump = tst_test_result_action_operation_dump, + .execute = tst_test_result_action_operation_execute +}; + +/* + * Tagged arguments + */ + +/* FIXME: merge this with the test_error version of this tag */ + +static bool tst_test_result_action_validate_index_tag + (struct sieve_validator *validator, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +static const struct sieve_argument_def test_result_action_index_tag = { + .identifier = "index", + .validate = tst_test_result_action_validate_index_tag +}; + +enum tst_test_result_action_optional { + OPT_INDEX = SIEVE_MATCH_OPT_LAST, +}; + +/* + * Argument implementation + */ + +static bool tst_test_result_action_validate_index_tag +(struct sieve_validator *validator, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :index number + */ + if ( !sieve_validate_tag_parameter + (validator, cmd, tag, *arg, NULL, 0, SAAT_NUMBER, FALSE) ) { + return FALSE; + } + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + return TRUE; +} + + +/* + * Command registration + */ + +static bool tst_test_result_action_registered +(struct sieve_validator *validator, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag(validator, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(validator, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + + sieve_validator_register_tag + (validator, cmd_reg, ext, &test_result_action_index_tag, OPT_INDEX); + + return TRUE; +} + +/* + * Validation + */ + +static bool tst_test_result_action_validate +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_octet_comparator); + struct sieve_match_type mcht_default = + SIEVE_COMPARATOR_DEFAULT(is_match_type); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "key list", 2, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate + (valdtr, tst, arg, &mcht_default, &cmp_default); +} + +/* + * Code generation + */ + +static bool tst_test_result_action_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *tst) +{ + sieve_operation_emit(cgenv->sblock, tst->ext, &test_result_action_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool tst_test_result_action_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "TEST_RESULT_ACTION:"); + sieve_code_descend(denv); + + /* Handle any optional arguments */ + for (;;) { + int opt; + + if ( (opt=sieve_match_opr_optional_dump(denv, address, &opt_code)) + < 0 ) + return FALSE; + + if ( opt == 0 ) break; + + if ( opt_code == OPT_INDEX ) { + if ( !sieve_opr_number_dump(denv, address, "index") ) + return FALSE; + } else { + return FALSE; + } + } + + return sieve_opr_stringlist_dump(denv, address, "key list"); +} + +/* + * Intepretation + */ + +static int tst_test_result_action_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + int opt_code = 0; + struct sieve_comparator cmp = SIEVE_COMPARATOR_DEFAULT(i_octet_comparator); + struct sieve_match_type mcht = SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + struct sieve_stringlist *value_list, *key_list; + int index = 0; + int match, ret; + + /* + * Read operands + */ + + /* Read optional operands */ + for (;;) { + sieve_number_t number; + int opt; + + if ( (opt=sieve_match_opr_optional_read + (renv, address, &opt_code, &ret, &cmp, &mcht)) < 0 ) + return ret; + + if ( opt == 0 ) break; + + if ( opt_code == OPT_INDEX ) { + if ( (ret=sieve_opr_number_read(renv, address, "index", &number)) <= 0 ) + return ret; + index = (int) number; + } else { + sieve_runtime_trace_error(renv, "invalid optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + } + + /* Read key-list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "testsuite: test_result_action test; match result name (index: %d)", index); + + /* Create value stringlist */ + value_list = testsuite_result_stringlist_create(renv, index); + + /* Perform match */ + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} + + + diff --git a/pigeonhole/src/testsuite/tst-test-result-execute.c b/pigeonhole/src/testsuite/tst-test-result-execute.c new file mode 100644 index 0000000..1b9a7ee --- /dev/null +++ b/pigeonhole/src/testsuite/tst-test-result-execute.c @@ -0,0 +1,96 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-script.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-dump.h" +#include "sieve.h" + +#include "testsuite-common.h" +#include "testsuite-result.h" + +/* + * Test_result_execute command + * + * Syntax: + * test_result_execute + */ + +static bool tst_test_result_execute_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + +const struct sieve_command_def tst_test_result_execute = { + .identifier = "test_result_execute", + .type = SCT_TEST, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .generate = tst_test_result_execute_generate +}; + +/* + * Operation + */ + +static int tst_test_result_execute_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def test_result_execute_operation = { + .mnemonic = "TEST_RESULT_EXECUTE", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_RESULT_EXECUTE, + .execute = tst_test_result_execute_operation_execute +}; + +/* + * Code generation + */ + +static bool tst_test_result_execute_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *tst) +{ + sieve_operation_emit(cgenv->sblock, tst->ext, &test_result_execute_operation); + + return TRUE; +} + +/* + * Intepretation + */ + +static int tst_test_result_execute_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED) +{ + bool result = TRUE; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "testsuite: test_result_execute test"); + + result = testsuite_result_execute(renv); + + if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_TESTS) ) { + sieve_runtime_trace_descend(renv); + sieve_runtime_trace(renv, 0, "execution of result %s", + ( result ? "succeeded" : "failed" )); + } + + /* Set result */ + sieve_interpreter_set_test_result(renv->interp, result); + + return SIEVE_EXEC_OK; +} + + + + diff --git a/pigeonhole/src/testsuite/tst-test-script-compile.c b/pigeonhole/src/testsuite/tst-test-script-compile.c new file mode 100644 index 0000000..c053486 --- /dev/null +++ b/pigeonhole/src/testsuite/tst-test-script-compile.c @@ -0,0 +1,144 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-script.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-dump.h" +#include "sieve.h" + +#include "testsuite-common.h" +#include "testsuite-script.h" + +/* + * Test_script_compile command + * + * Syntax: + * test_script_compile <scriptpath: string> + */ + +static bool tst_test_script_compile_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool tst_test_script_compile_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + +const struct sieve_command_def tst_test_script_compile = { + .identifier = "test_script_compile", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = tst_test_script_compile_validate, + .generate = tst_test_script_compile_generate +}; + +/* + * Operation + */ + +static bool tst_test_script_compile_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_test_script_compile_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def test_script_compile_operation = { + .mnemonic = "TEST_SCRIPT_COMPILE", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_SCRIPT_COMPILE, + .dump = tst_test_script_compile_operation_dump, + .execute = tst_test_script_compile_operation_execute +}; + +/* + * Validation + */ + +static bool tst_test_script_compile_validate +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "script", 1, SAAT_STRING) ) { + return FALSE; + } + + return sieve_validator_argument_activate(valdtr, tst, arg, FALSE); +} + +/* + * Code generation + */ + +static bool tst_test_script_compile_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *tst) +{ + sieve_operation_emit(cgenv->sblock, tst->ext, &test_script_compile_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool tst_test_script_compile_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "TEST_SCRIPT_COMPILE:"); + sieve_code_descend(denv); + + if ( !sieve_opr_string_dump(denv, address, "script-name") ) + return FALSE; + + return TRUE; +} + +/* + * Intepretation + */ + +static int tst_test_script_compile_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + string_t *script_name; + bool result = TRUE; + int ret; + + /* + * Read operands + */ + + if ( (ret=sieve_opr_string_read(renv, address, "script-name", &script_name)) + <= 0 ) + return ret; + + /* + * Perform operation + */ + + if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_TESTS) ) { + sieve_runtime_trace(renv, 0, "testsuite: test_script_compile test"); + sieve_runtime_trace_descend(renv); + } + + /* Attempt script compile */ + + result = testsuite_script_compile(renv, str_c(script_name)); + + /* Set result */ + sieve_interpreter_set_test_result(renv->interp, result); + + return SIEVE_EXEC_OK; +} + + + + diff --git a/pigeonhole/src/testsuite/tst-test-script-run.c b/pigeonhole/src/testsuite/tst-test-script-run.c new file mode 100644 index 0000000..214a5c6 --- /dev/null +++ b/pigeonhole/src/testsuite/tst-test-script-run.c @@ -0,0 +1,198 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-script.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-dump.h" +#include "sieve.h" + +#include "testsuite-common.h" +#include "testsuite-script.h" +#include "testsuite-result.h" + +/* + * Test_script_run command + * + * Syntax: + * test_script_run + */ + +static bool tst_test_script_run_registered +(struct sieve_validator *validator, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool tst_test_script_run_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + +const struct sieve_command_def tst_test_script_run = { + .identifier = "test_script_run", + .type = SCT_TEST, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_test_script_run_registered, + .generate = tst_test_script_run_generate +}; + +/* + * Operation + */ + +static bool tst_test_script_run_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_test_script_run_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def test_script_run_operation = { + .mnemonic = "TEST_SCRIPT_RUN", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERATION_TEST_SCRIPT_RUN, + .dump = tst_test_script_run_operation_dump, + .execute = tst_test_script_run_operation_execute +}; + +/* + * Tagged arguments + */ + +/* Codes for optional arguments */ + +enum cmd_vacation_optional { + OPT_END, + OPT_APPEND_RESULT +}; + +/* Tags */ + +static const struct sieve_argument_def append_result_tag = { + .identifier = "append_result" +}; + +static bool tst_test_script_run_registered +(struct sieve_validator *validator, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag + (validator, cmd_reg, ext, &append_result_tag, OPT_APPEND_RESULT); + + return TRUE; +} + + +/* + * Code generation + */ + +static bool tst_test_script_run_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *tst) +{ + sieve_operation_emit(cgenv->sblock, tst->ext, &test_script_run_operation); + + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool tst_test_script_run_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "TEST_SCRIPT_RUN"); + sieve_code_descend(denv); + + /* Dump optional operands */ + for (;;) { + int opt; + + if ( (opt=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_APPEND_RESULT: + sieve_code_dumpf(denv, "append_result"); + break; + default: + return FALSE; + } + } + + return TRUE; +} + + +/* + * Intepretation + */ + +static int tst_test_script_run_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + bool append_result = FALSE; + int opt_code = 0; + bool result = TRUE; + + /* + * Read operands + */ + + /* Optional operands */ + for (;;) { + int opt; + + if ( (opt=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_APPEND_RESULT: + append_result = TRUE; + break; + default: + sieve_runtime_trace_error(renv, + "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + } + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "testsuite: run compiled script [append_result=%s]", + ( append_result ? "yes" : "no" )); + + /* Reset result object */ + if ( !append_result ) + testsuite_result_reset(renv); + + /* Run script */ + result = testsuite_script_run(renv); + + if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_TESTS) ) { + sieve_runtime_trace_descend(renv); + sieve_runtime_trace(renv, 0, "execution of script %s", + ( result ? "succeeded" : "failed" )); + } + + /* Indicate test status */ + sieve_interpreter_set_test_result(renv->interp, result); + + return SIEVE_EXEC_OK; +} + + + + diff --git a/pigeonhole/stamp.h.in b/pigeonhole/stamp.h.in new file mode 100644 index 0000000..4bd8276 --- /dev/null +++ b/pigeonhole/stamp.h.in @@ -0,0 +1 @@ +// empty file diff --git a/pigeonhole/tests/comparators/i-ascii-casemap.svtest b/pigeonhole/tests/comparators/i-ascii-casemap.svtest new file mode 100644 index 0000000..0891f3e --- /dev/null +++ b/pigeonhole/tests/comparators/i-ascii-casemap.svtest @@ -0,0 +1,39 @@ +require "vnd.dovecot.testsuite"; + +test_set "message" text: +From: stephan@example.org +Cc: frop@example.com +To: test@dovecot.example.net +X-A: This is a TEST header +Subject: Test Message + +Test! +. +; + +test "i;ascii-casemap :contains (1)" { + if not header :contains :comparator "i;ascii-casemap" "X-A" "TEST" { + test_fail "should have matched"; + } +} + +test "i;ascii-casemap :contains (2)" { + if not header :contains :comparator "i;ascii-casemap" "X-A" "test" { + test_fail "should have matched"; + } +} + +test "i;ascii-casemap :matches (1)" { + if not header :matches :comparator "i;ascii-casemap" "X-A" "This*TEST*r" { + test_fail "should have matched"; + } +} + +test "i;ascii-casemap :matches (2)" { + if not header :matches :comparator "i;ascii-casemap" "X-A" "ThIs*tEsT*R" { + test_fail "should have matched"; + } +} + + + diff --git a/pigeonhole/tests/comparators/i-octet.svtest b/pigeonhole/tests/comparators/i-octet.svtest new file mode 100644 index 0000000..b6041bc --- /dev/null +++ b/pigeonhole/tests/comparators/i-octet.svtest @@ -0,0 +1,37 @@ +require "vnd.dovecot.testsuite"; + +test_set "message" text: +From: stephan@example.org +Cc: frop@example.com +To: test@dovecot.example.net +X-A: This is a TEST header +Subject: Test Message + +Test! +. +; + +test "i;octet :contains" { + if not header :contains :comparator "i;octet" "X-A" "TEST" { + test_fail "should have matched"; + } +} + +test "i;octet not :contains" { + if header :contains :comparator "i;octet" "X-A" "test" { + test_fail "should not have matched"; + } +} + +test "i;octet :matches" { + if not header :matches :comparator "i;octet" "X-A" "This*TEST*r" { + test_fail "should have matched"; + } +} + +test "i;octet not :matches" { + if header :matches :comparator "i;octet" "X-A" "ThIs*tEsT*R" { + test_fail "should not have matched"; + } +} + diff --git a/pigeonhole/tests/compile/compile.svtest b/pigeonhole/tests/compile/compile.svtest new file mode 100644 index 0000000..7abda7f --- /dev/null +++ b/pigeonhole/tests/compile/compile.svtest @@ -0,0 +1,16 @@ +require "vnd.dovecot.testsuite"; + +# Just test whether valid scripts will compile without problems + +test "Trivial" { + if not test_script_compile "trivial.sieve" { + test_fail "could not compile"; + } +} + +test "Redirect" { + if not test_script_compile "redirect.sieve" { + test_fail "could not compile"; + } +} + diff --git a/pigeonhole/tests/compile/errors.svtest b/pigeonhole/tests/compile/errors.svtest new file mode 100644 index 0000000..f17ea3f --- /dev/null +++ b/pigeonhole/tests/compile/errors.svtest @@ -0,0 +1,395 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +/* + * Errors triggered in the compiled scripts are pretty reduntant over the + * tested commands, but we want to be thorough. + */ + +/* + * Lexer errors + */ + +test "Lexer errors (FIXME: count only)" { + if test_script_compile "errors/lexer.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "9" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Parser errors + */ + +test "Parser errors (FIXME: count only)" { + if test_script_compile "errors/parser.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "9" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Header test + */ + +test "Header errors" { + if test_script_compile "errors/header.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "10" { + test_fail "wrong number of errors reported"; + } + + if not test_error :index 1 :matches + "unknown * ':all' for * header test *" { + test_fail "error 1 is invalid"; + } + + if not test_error :index 2 :matches + "*header test * string list * 1 (header names), but * number *" { + test_fail "error 2 is invalid"; + } + + if not test_error :index 3 :matches + "*header test * string list * 2 (key list), * number *" { + test_fail "error 3 is invalid"; + } + + if not test_error :index 4 :matches + "unknown tagged argument ':tag' for the header test *" { + test_fail "error 4 is invalid"; + } + + if not test_error :index 5 :matches + "* header test requires 2 *, but 1 *" { + test_fail "error 5 is invalid"; + } + + if not test_error :index 6 :matches + "* header test requires 2 *, but 0 *" { + test_fail "error 6 is invalid"; + } + + if not test_error :index 7 :matches + "*header test accepts no sub-tests* specified*" { + test_fail "error 7 is invalid"; + } + + if not test_error :index 8 :matches + "* use test 'header' * command*" { + test_fail "error 8 is invalid"; + } + + if not test_error :index 9 :matches + "* use test 'header' * command*" { + test_fail "error 9 is invalid"; + } + + if test_error :index 4 :contains "radish" { + test_fail "error test matched nonsense"; + } +} + +/* + * Address test + */ + + +test "Address errors" { + if test_script_compile "errors/address.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "9" { + test_fail "wrong number of errors reported"; + } + + if not test_error :index 1 :matches + "*unknown * ':nonsense' * address test*" { + test_fail "error 1 is invalid"; + } + + if not test_error :index 2 :matches + "*address test expects *string list * 1 (header list),* number * found*" { + test_fail "error 2 is invalid"; + } + + if not test_error :index 3 :matches + "*address test expects *string list * 2 (key list),* number * found*" { + test_fail "error 3 is invalid"; + } + + if not test_error :index 4 :matches + "*unexpected *':is' * address test*" { + test_fail "error 4 is invalid"; + } + + if not test_error :index 5 :matches + "*address test * 2 positional arg*, but 1*" { + test_fail "error 5 is invalid"; + } + + if not test_error :index 6 :matches + "*address test * 2 positional arg*, but 0*" { + test_fail "error 6 is invalid"; + } + + if not test_error :index 7 :matches + "*'frop' *not allowed *address test*" { + test_fail "error 7 is invalid"; + } + + if not test_error :index 8 :matches + "*'frop' *not allowed *address test*" { + test_fail "error 8 is invalid"; + } + + if test_error :index 23 :contains "radish" { + test_fail "error test matched nonsense"; + } +} + +/* + * If command + */ + +test "If errors (FIXME: count only)" { + if test_script_compile "errors/if.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "12" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Require command + */ + +test "Require errors (FIXME: count only)" { + if test_script_compile "errors/require.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "15" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Size test + */ + +test "Size errors (FIXME: count only)" { + if test_script_compile "errors/size.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "7" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Envelope test + */ + +test "Envelope errors (FIXME: count only)" { + if test_script_compile "errors/envelope.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Stop command + */ + +test "Stop errors (FIXME: count only)" { + if test_script_compile "errors/stop.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "9" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Keep command + */ + +test "Keep errors (FIXME: count only)" { + if test_script_compile "errors/keep.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Fileinto command + */ + +test "Fileinto errors (FIXME: count only)" { + if test_script_compile "errors/fileinto.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "10" { + test_fail "wrong number of errors reported"; + } +} + +/* + * COMPARATOR errors + */ + +test "COMPARATOR errors (FIXME: count only)" { + if test_script_compile "errors/comparator.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "6" { + test_fail "wrong number of errors reported"; + } +} + +/* + * ADDRESS-PART errors + */ + +test "ADDRESS-PART errors (FIXME: count only)" { + if test_script_compile "errors/address-part.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "wrong number of errors reported"; + } +} + +/* + * MATCH-TYPE errors + */ + +test "MATCH-TYPE errors (FIXME: count only)" { + if test_script_compile "errors/match-type.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "2" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Encoded-character errors + */ + +test "Encoded-character errors (FIXME: count only)" { + if test_script_compile "errors/encoded-character.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Outgoing address errors + */ + +test "Outgoing address errors (FIXME: count only)" { + if test_script_compile "errors/out-address.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "16" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Tagged argument errors + */ + +test "Tagged argument errors (FIXME: count only)" { + if test_script_compile "errors/tag.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Typos + */ + +test "Typos" { + if test_script_compile "errors/typos.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "6" { + test_fail "wrong number of errors reported"; + } + + if not test_error :index 1 :matches + "missing semicolon * fileinto *" { + test_fail "error 1 is invalid"; + } + + if not test_error :index 2 :matches + "*fileinto command * no *tests* specified*" { + test_fail "error 2 is invalid"; + } + + if not test_error :index 3 :matches + "missing semicolon * fileinto *" { + test_fail "error 3 is invalid"; + } + + if not test_error :index 4 :matches + "*address test requires 2 * 0 * specified" { + test_fail "error 4 is invalid"; + } + + if not test_error :index 5 :matches + "missing colon *matches* tag * address test" { + test_fail "error 5 is invalid"; + } +} + + +/* + * Unsupported language features + */ + +test "Unsupported language features (FIXME: count only)" { + if test_script_compile "errors/unsupported.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "wrong number of errors reported"; + } +} diff --git a/pigeonhole/tests/compile/errors/address-part.sieve b/pigeonhole/tests/compile/errors/address-part.sieve new file mode 100644 index 0000000..1d10cbf --- /dev/null +++ b/pigeonhole/tests/compile/errors/address-part.sieve @@ -0,0 +1,17 @@ +/* + * Address part errors + * + * Total errors: 2 (+1 = 3) + */ + +# Duplicate address part (1) +if address :all :comparator "i;octet" :domain "from" "STEPHAN" { + + # Duplicate address part (2) + if address :domain :localpart :comparator "i;octet" "from" "friep.example.com" { + keep; + } + + stop; +} + diff --git a/pigeonhole/tests/compile/errors/address.sieve b/pigeonhole/tests/compile/errors/address.sieve new file mode 100644 index 0000000..f7d3b26 --- /dev/null +++ b/pigeonhole/tests/compile/errors/address.sieve @@ -0,0 +1,71 @@ +require "comparator-i;ascii-numeric"; + +/* + * Address test errors + * + * Total count: 8 (+1 = 9) + */ + +/* + * Command structure + */ + +# Invalid tag +if address :nonsense :comparator "i;ascii-casemap" :localpart "From" "nico" { + discard; +} + +# Invalid first argument +if address :is :comparator "i;ascii-numeric" :localpart 45 "nico" { + discard; +} + +# Invalid second argument +if address :is :comparator "i;ascii-numeric" :localpart "From" 45 { + discard; +} + +# Invalid second argument +if address :comparator "i;ascii-numeric" :localpart "From" :is { + discard; +} + +# Missing second argument +if address :is :comparator "i;ascii-numeric" :localpart "From" { + discard; +} + +# Missing arguments +if address :is :comparator "i;ascii-numeric" :localpart { + discard; +} + +# Not an error +if address :localpart :is :comparator "i;ascii-casemap" "from" ["frop", "frop"] { + discard; +} + +/* + * Specified headers must contain addresses + */ + +# Invalid header +if address :is "frop" "frml" { + keep; +} + +# Not an error +if address :is "reply-to" "frml" { + keep; +} + +# Invalid header (#2) +if address :is ["to", "frop"] "frml" { + keep; +} + +# Not an error +if address :is ["to", "reply-to"] "frml" { + keep; +} + diff --git a/pigeonhole/tests/compile/errors/comparator.sieve b/pigeonhole/tests/compile/errors/comparator.sieve new file mode 100644 index 0000000..368b56b --- /dev/null +++ b/pigeonhole/tests/compile/errors/comparator.sieve @@ -0,0 +1,21 @@ +/* + * Address part errors + * + * Total errors: 5 (+1 = 6) + */ + +# 1: No argument +if address :comparator { } + +# 2: Number argument +if address :comparator 1 "from" "frop" { } + +# 3: String list argument +if address :comparator ["a", "b"] "from" "frop" { } + +# 4: Unknown tag +if address :comparator :frop "from" "frop" { } + +# 5: Known tag +if address :comparator :all "from" "frop" { } + diff --git a/pigeonhole/tests/compile/errors/encoded-character.sieve b/pigeonhole/tests/compile/errors/encoded-character.sieve new file mode 100644 index 0000000..04d9de4 --- /dev/null +++ b/pigeonhole/tests/compile/errors/encoded-character.sieve @@ -0,0 +1,23 @@ +/* + * Encoded-character errors + * + * Total errors: 2 (+1 = 3) + */ + +require "encoded-character"; +require "fileinto"; + +# Invalid unicode character (1) +fileinto "INBOX.${unicode:200000}"; + +# Not an error +fileinto "INBOX.${unicode:200000"; + +# Invalid unicode character (2) +fileinto "INBOX.${Unicode:DF01}"; + +# Not an error +fileinto "INBOX.${Unicode:DF01"; + + + diff --git a/pigeonhole/tests/compile/errors/envelope.sieve b/pigeonhole/tests/compile/errors/envelope.sieve new file mode 100644 index 0000000..9639846 --- /dev/null +++ b/pigeonhole/tests/compile/errors/envelope.sieve @@ -0,0 +1,23 @@ +/* + * Envelope test errors + * + * Total errors: 2 (+1 = 3) + */ + +require "envelope"; + +# Not an error +if envelope :is "to" "frop@example.org" { +} + +# Unknown envelope part (1) +if envelope :is "frop" "frop@example.org" { +} + +# Not an error +if envelope :is ["to","from"] "frop@example.org" { +} + +# Unknown envelope part (2) +if envelope :is ["to","frop"] "frop@example.org" { +} diff --git a/pigeonhole/tests/compile/errors/fileinto.sieve b/pigeonhole/tests/compile/errors/fileinto.sieve new file mode 100644 index 0000000..0598557 --- /dev/null +++ b/pigeonhole/tests/compile/errors/fileinto.sieve @@ -0,0 +1,38 @@ +require "fileinto"; +require "encoded-character"; + +/* + * Fileinto errors + * + * Total erors: 9 (+1 = 10) + */ + +# Missing string argument +fileinto; + +# Spurious test +fileinto true; + +# Spurious test +fileinto "Frop" true; + +# Spurious number argument +fileinto 33; + +# Spurious tag argument +fileinto :frop; + +# Spurious additional string argument +fileinto "Frop" "Friep"; + +# Spurious additional number argument +fileinto "Frop" 123; + +# Spurious additional tag argument +fileinto "Frop" :frop; + +# Bad mailbox name +fileinto "${hex:ff}rop"; + +# Not an error +fileinto "Frop"; diff --git a/pigeonhole/tests/compile/errors/header.sieve b/pigeonhole/tests/compile/errors/header.sieve new file mode 100644 index 0000000..1c87f94 --- /dev/null +++ b/pigeonhole/tests/compile/errors/header.sieve @@ -0,0 +1,57 @@ +require "comparator-i;ascii-numeric"; + +/* + * Compile errors for the header test + * + * Total errors: 9 (+1 validation failed msg = 10) + */ + +# Unknown tagged argument +if header :all :comparator "i;ascii-casemap" "From" "nico" { + keep; +} + +# Wrong first argument +if header :is :comparator "i;ascii-numeric" 45 "nico" { + keep; +} + +# Wrong second argument +if header :is :comparator "i;ascii-numeric" "From" 45 { + discard; +} + +# Wrong second argument +if header :is :comparator "i;ascii-numeric" "From" :tag { + stop; +} + +# Missing second argument +if header :is :comparator "i;ascii-numeric" "From" { + stop; +} + +# Missing arguments +if header :is :comparator "i;ascii-numeric" { + keep; +} + +# Not an error +if header :is :comparator "i;ascii-casemap" "frop" ["frop", "frop"] { + discard; +} + +# Spurious sub-test +if header "frop" "frop" true { + discard; +} + +# Test used as command with block +header "frop" "frop" { + discard; +} + +# Test used as command +header "frop" "frop"; + + diff --git a/pigeonhole/tests/compile/errors/if.sieve b/pigeonhole/tests/compile/errors/if.sieve new file mode 100644 index 0000000..6a8537b --- /dev/null +++ b/pigeonhole/tests/compile/errors/if.sieve @@ -0,0 +1,78 @@ +/* + * If command errors + * + * Total errors: 11 (+1 = 12) + */ + +# Spurious argument +if "frop" true {} + +# Spurious argument +elsif "frop" true {} + +# Spurious string list +if [ "false", "false", "false" ] false { + stop; +} + +# No block +if true; + +# No test +if { + keep; +} + +# Spurious test list +if ( false, false, true ) { + keep; +} + +stop; + +# If-less else +else { + keep; +} + +# Not an error +if true { + keep; +} + +stop; + +# If-less if structure (should produce only one error) +elsif true { + keep; +} +elsif true { + keep; +} +else { +} + +# Elsif after else +if true { + keep; +} else { + stop; +} elsif true { + stop; +} + +# If used as test +if if true { +} + +# Else if instead of elsif + +if true { + stop; +} else if false { + keep; +} + + + + diff --git a/pigeonhole/tests/compile/errors/keep.sieve b/pigeonhole/tests/compile/errors/keep.sieve new file mode 100644 index 0000000..7b3397c --- /dev/null +++ b/pigeonhole/tests/compile/errors/keep.sieve @@ -0,0 +1,14 @@ +/* + * Keep errors + * + * Total erors: 2 (+1 = 3) + */ + +# Spurious string argument +keep "frop"; + +# Spurious test +keep true; + +# Not an error +keep; diff --git a/pigeonhole/tests/compile/errors/lexer.sieve b/pigeonhole/tests/compile/errors/lexer.sieve new file mode 100644 index 0000000..9675db1 --- /dev/null +++ b/pigeonhole/tests/compile/errors/lexer.sieve @@ -0,0 +1,68 @@ +/* + * Lexer tests + * + * Total errors: 8 (+1 = 9) + */ + +/* + * Number limits + */ + +# 1: Number too large +if size :under 18446744073709551617 { + stop; +} + +# 2: Number too large +if size :under 18446744073709551616 { + stop; +} + +# 3: Number too large +if size :over 180143985094819840k { + stop; +} + +# 4: Number too large +if size :over 1006622342342296M { + stop; +} + +# 5: Number too large +if size :over 34359738368G { + stop; +} + +# 6: Number far too large +if size :over 49834598293485814273947921734981723971293741923 { + stop; +} + +# Not an error +if size :under 18446744073709551615 { + stop; +} + +# Not an error +if size :under 18446744073709551614 { + stop; +} + +# Not an error +if size :under 800G { + stop; +} + +/* + * Identifier limits + */ + +# 7: Identifier too long +if this_is_a_rediculously_long_test_name { + stop; +} + +# 8: Identifier way too long +if test :this_is_an_even_more_rediculously_long_tagged_argument_name { + stop; +} diff --git a/pigeonhole/tests/compile/errors/match-type.sieve b/pigeonhole/tests/compile/errors/match-type.sieve new file mode 100644 index 0000000..d8e1681 --- /dev/null +++ b/pigeonhole/tests/compile/errors/match-type.sieve @@ -0,0 +1,7 @@ +require "comparator-i;ascii-numeric"; + +if header :contains :comparator "i;ascii-numeric" "from" "friep.example.com" { + keep; +} + +keep; diff --git a/pigeonhole/tests/compile/errors/out-address.sieve b/pigeonhole/tests/compile/errors/out-address.sieve new file mode 100644 index 0000000..3e39599 --- /dev/null +++ b/pigeonhole/tests/compile/errors/out-address.sieve @@ -0,0 +1,33 @@ +require "vacation"; + +# Error + +redirect "@wrong.example.com"; +redirect "error"; +redirect "error@"; +redirect "Stephan Bosch error@example.org"; +redirect "Stephan Bosch <error@example.org"; +redirect " more error @ example.com "; +redirect "@"; +redirect "<>"; +redirect "Error <"; +redirect "Error <stephan"; +redirect "Error <stephan@"; +redirect "stephan@example.org,tss@example.net"; +redirect "stephan@example.org,%&^&!!~"; +redirect "rüdiger@example.com"; + +vacation :from "Error" "Ik ben er niet."; + +# Ok + +redirect "Ok Good <stephan@example.org>"; +redirect "ok@example.com"; +redirect " more @ example.com "; + +redirect ".japanese@example.com"; +redirect "japanese.@example.com"; +redirect "japanese...localpart@example.com"; +redirect "..japanese...localpart..@example.com"; + +vacation :from "good@voorbeeld.nl.example.com" "Ik ben weg!"; diff --git a/pigeonhole/tests/compile/errors/parser.sieve b/pigeonhole/tests/compile/errors/parser.sieve new file mode 100644 index 0000000..26a1e53 --- /dev/null +++ b/pigeonhole/tests/compile/errors/parser.sieve @@ -0,0 +1,78 @@ +/* + * Parser errors + * + * Total errors: 8 (+1 = 9) + */ + +# Too many arguments (1) +frop :this "is" "a" 2 :long "argument" "list" :and :it :should "fail" :during "parsing" :but "it" "should" "be" + "recoverable" "." :this "is" "a" 2 :long "argument" "list" :and :it :should "fail" :during "parsing" :but + "it" "should" "be" "recoverable" { + stop; +} + +# Garbage argument (2) +friep $$$; + +# Deep block nesting (1) +if true { if true { if true { if true { if true { if true { if true { if true { + if true { if true { if true { if true { if true { if true { if true { if true { + if true { if true { if true { if true { if true { if true { if true { if true { + if true { if true { if true { if true { if true { if true { if true { if true { + if true { if true { if true { if true { if true { if true { if true { if true { + stop; + } } } } } } } } + } } } } } } } } + } } } } } } } } + } } } } } } } } +} } } } } } } } + +# Deepest block and too deep test (list) nesting (1) +if true { if true { if true { if true { if true { if true { if true { if true { + if true { if true { if true { if true { if true { if true { if true { if true { + if true { if true { if true { if true { if true { if true { if true { if true { + if true { if true { if true { if true { if true { if true { + if + anyof ( anyof ( anyof ( anyof ( anyof ( anyof ( anyof ( anyof ( + anyof ( anyof ( anyof ( anyof ( anyof ( anyof ( anyof ( anyof ( + anyof ( anyof ( anyof ( anyof ( anyof ( anyof ( anyof ( anyof ( + anyof ( anyof ( anyof ( anyof ( anyof ( anyof ( anyof ( anyof ( + anyof ( anyof ( anyof ( anyof ( anyof ( anyof ( anyof ( anyof ( + true + )))))))) + )))))))) + )))))))) + )))))))) + )))))))) + { + stop; + } + } } } } } } + } } } } } } } } + } } } } } } } } +} } } } } } } } + +# Deepest block and too deep test nesting (1) +if true { if true { if true { if true { if true { if true { if true { if true { + if true { if true { if true { if true { if true { if true { if true { if true { + if true { if true { if true { if true { if true { if true { if true { if true { + if true { if true { if true { if true { if true { if true { + if + not not not not not not not not + not not not not not not not not + not not not not not not not not + not not not not not not not not + not not not not not not not not false + { + stop; + } + } } } } } } + } } } } } } } } + } } } } } } } } +} } } } } } } } + + +# Garbage command; test wether previous errors were resolved (2) +frop $$$$; + + diff --git a/pigeonhole/tests/compile/errors/require.sieve b/pigeonhole/tests/compile/errors/require.sieve new file mode 100644 index 0000000..ecbd7a2 --- /dev/null +++ b/pigeonhole/tests/compile/errors/require.sieve @@ -0,0 +1,42 @@ +/* + * Require errors + * + * Total errors: 11 (+1 = 12) + */ + +# Not an error +require "fileinto"; + +# Missing argument +require; + +# Too many arguments +require "fileinto" "vacation"; + +# Invalid argument +require 45; + +# Invalid extensions (3 errors) +require ["_frop", "_friep", "_frml"]; + +# Core commands required +require ["redirect", "keep", "discard"]; + +# Invalid arguments +require "dovecot.test" true; + +# Invalid extension +require "_frop"; + +# Spurious command block +require "fileinto" { + keep; +} + +# Nested require +if true { + require "relional"; +} + +# Require after other command than require +require "copy"; diff --git a/pigeonhole/tests/compile/errors/size.sieve b/pigeonhole/tests/compile/errors/size.sieve new file mode 100644 index 0000000..14dbee5 --- /dev/null +++ b/pigeonhole/tests/compile/errors/size.sieve @@ -0,0 +1,47 @@ +/* + * Size test errors + * + * Total errors: 6 (+1 = 7) + */ + +# Used as command (1) +size :under 23; + +# Missing argument (2) +if size { +} + +# Missing :over/:under (3) +if size 45 { + discard; +} + +# No error +if size :over 34K { + stop; +} + +# No error +if size :under 34M { + stop; +} + +# Conflicting tags (4) +if size :under :over 34 { + keep; +} + +# Duplicate tags (5) +if size :over :over 45M { + stop; +} + +# Wrong argument order (6) +if size 34M :over { + stop; +} + +# No error; but worthy of a warning +if size :under 0 { + stop; +} diff --git a/pigeonhole/tests/compile/errors/stop.sieve b/pigeonhole/tests/compile/errors/stop.sieve new file mode 100644 index 0000000..75a3d76 --- /dev/null +++ b/pigeonhole/tests/compile/errors/stop.sieve @@ -0,0 +1,33 @@ +/* + * Stop command errors + * + * Total errors: 7 (+1 = 8) + */ + +# Spurious string argument +stop "frop"; + +# Spurious number argument +stop 13; + +# Spurious string list argument +stop [ "frop", "frop" ]; + +# Spurious test +stop true; + +# Spurious test list +stop ( true, false ); + +# Spurious command block +stop { + keep; +} + +# Spurious argument and test +stop "frop" true { + stop; +} + +# Not an error +stop; diff --git a/pigeonhole/tests/compile/errors/tag.sieve b/pigeonhole/tests/compile/errors/tag.sieve new file mode 100644 index 0000000..7fa65e9 --- /dev/null +++ b/pigeonhole/tests/compile/errors/tag.sieve @@ -0,0 +1,16 @@ +/* + * Tag errors + * + * Total errors: 2 (+1 = 3) + */ + +# Unknown tag (1) +if envelope :isnot :comparator "i;ascii-casemap" :localpart "From" "nico" { + discard; +} + +# Spurious tag (1) +if true :comparator "i;ascii-numeric" { + keep; +} + diff --git a/pigeonhole/tests/compile/errors/typos.sieve b/pigeonhole/tests/compile/errors/typos.sieve new file mode 100644 index 0000000..3d65b26 --- /dev/null +++ b/pigeonhole/tests/compile/errors/typos.sieve @@ -0,0 +1,29 @@ +/* + * This test is primarily meant to check the compiler's handling of typos + * at various locations. + */ + +require "fileinto"; + +/* + * Missing semicolon + */ + +fileinto "frop" +keep; + +/* Other situations */ + +fileinto "frup" +true; + +fileinto "friep" +snot; + +/* + * Forgot tag colon + */ + +if address matches "from" "*frop*" { + stop; +} diff --git a/pigeonhole/tests/compile/errors/unsupported.sieve b/pigeonhole/tests/compile/errors/unsupported.sieve new file mode 100644 index 0000000..9943f7b --- /dev/null +++ b/pigeonhole/tests/compile/errors/unsupported.sieve @@ -0,0 +1,30 @@ +/* + * Handling of unsupported language features. + * + * Total errors: 3 (+1 = 4) + */ + +require "variables"; +require "include"; +require "regex"; + +/* + * Unsupported use of variables + */ + +/* Comparator argument */ + +set "comp" "i;ascii-numeric"; + +if address :comparator "${comp}" "from" "stephan@example.org" { + stop; +} + +/* Included script */ + +set "script" "blacklist"; + +include "${blacklist}"; + + + diff --git a/pigeonhole/tests/compile/recover.svtest b/pigeonhole/tests/compile/recover.svtest new file mode 100644 index 0000000..9c24c11 --- /dev/null +++ b/pigeonhole/tests/compile/recover.svtest @@ -0,0 +1,50 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +/* + * Test parser's recover capability + */ + +/* + * Commands + */ + +/* Missing semicolon */ + +test "Missing semicolons" { + if test_script_compile "recover/commands-semicolon.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "wrong number of errors reported"; + } +} + +/* End of block recovery*/ + +test "Missing semicolon at end of block" { + if test_script_compile "recover/commands-endblock.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "4" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Tests + */ + +test "Spurious comma at end of test list" { + if test_script_compile "recover/tests-endcomma.sieve" { + test_fail "compile should have failed."; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "wrong number of errors reported"; + } +} diff --git a/pigeonhole/tests/compile/recover/commands-endblock.sieve b/pigeonhole/tests/compile/recover/commands-endblock.sieve new file mode 100644 index 0000000..c06e218 --- /dev/null +++ b/pigeonhole/tests/compile/recover/commands-endblock.sieve @@ -0,0 +1,27 @@ +if true { + if true { + # Missing semicolon + keep + } +} + +if true { + # Erroneous syntax + keep, + keep +} + +if true { + if anyof(true,true,false) { + keep; + } +} + +if true { + if anyof(true,true,false) { + keep; + # Missing semicolon + discard + } +} + diff --git a/pigeonhole/tests/compile/recover/commands-semicolon.sieve b/pigeonhole/tests/compile/recover/commands-semicolon.sieve new file mode 100644 index 0000000..effb389 --- /dev/null +++ b/pigeonhole/tests/compile/recover/commands-semicolon.sieve @@ -0,0 +1,16 @@ + +keep; + +discard; + +# Missing semicolon +keep + +redirect "frop@nl.example.com"; + +discard; + +# Missing semicolon +keep + +redirect "frml@nl.example.com"; diff --git a/pigeonhole/tests/compile/recover/tests-endcomma.sieve b/pigeonhole/tests/compile/recover/tests-endcomma.sieve new file mode 100644 index 0000000..54c93ec --- /dev/null +++ b/pigeonhole/tests/compile/recover/tests-endcomma.sieve @@ -0,0 +1,17 @@ +if true { + if true { + # Spurious comma + if anyof(true,true,true,) { + } + } +} + +if true { + if anyof(true,true) { + # Spurious comma + if anyof(true,true,true,) { + if anyof(true,true,true) { + } + } + } +} diff --git a/pigeonhole/tests/compile/redirect.sieve b/pigeonhole/tests/compile/redirect.sieve new file mode 100644 index 0000000..fb9f23d --- /dev/null +++ b/pigeonhole/tests/compile/redirect.sieve @@ -0,0 +1,23 @@ +# Test various white space occurrences +redirect "stephan@example.org"; +redirect " stephan@example.org"; +redirect "stephan @example.org"; +redirect "stephan@ example.org"; +redirect "stephan@example.org "; +redirect " stephan @ example.org "; +redirect "Stephan Bosch<stephan@example.org>"; +redirect " Stephan Bosch<stephan@example.org>"; +redirect "Stephan Bosch <stephan@example.org>"; +redirect "Stephan Bosch< stephan@example.org>"; +redirect "Stephan Bosch<stephan @example.org>"; +redirect "Stephan Bosch<stephan@ example.org>"; +redirect "Stephan Bosch<stephan@example.org >"; +redirect "Stephan Bosch<stephan@example.org> "; +redirect " Stephan Bosch < stephan @ example.org > "; + +# Test address syntax +redirect "\"Stephan Bosch\"@example.org"; +redirect "Stephan.Bosch@eXamPle.oRg"; +redirect "Stephan.Bosch@example.org"; +redirect "Stephan Bosch <stephan@example.org>"; + diff --git a/pigeonhole/tests/compile/trivial.sieve b/pigeonhole/tests/compile/trivial.sieve new file mode 100644 index 0000000..a3dcbc1 --- /dev/null +++ b/pigeonhole/tests/compile/trivial.sieve @@ -0,0 +1,17 @@ +# Commands must be case-insensitive +keep; +Keep; +KEEP; +discard; +DisCaRD; + +# Tags must be case-insensitive +if size :UNDER 34 { +} + +if header :Is "from" "tukker@example.com" { +} + +# Numbers must be case-insensitive +if anyof( size :UNDER 34m, size :oVeR 50M ) { +} diff --git a/pigeonhole/tests/compile/warnings.svtest b/pigeonhole/tests/compile/warnings.svtest new file mode 100644 index 0000000..8261551 --- /dev/null +++ b/pigeonhole/tests/compile/warnings.svtest @@ -0,0 +1,8 @@ +require "vnd.dovecot.testsuite"; + +test "EOF Warnings" { + if not test_script_compile "warnings/eof.sieve" { + test_fail "compile should have succeeded."; + } +} + diff --git a/pigeonhole/tests/compile/warnings/eof.sieve b/pigeonhole/tests/compile/warnings/eof.sieve new file mode 100644 index 0000000..cf906dc --- /dev/null +++ b/pigeonhole/tests/compile/warnings/eof.sieve @@ -0,0 +1,2 @@ +keep; +# Final comment without newline diff --git a/pigeonhole/tests/compile/warnings/invalid-headers.sieve b/pigeonhole/tests/compile/warnings/invalid-headers.sieve new file mode 100644 index 0000000..a6b12a8 --- /dev/null +++ b/pigeonhole/tests/compile/warnings/invalid-headers.sieve @@ -0,0 +1,14 @@ +# Header test +if header "from:" "frop@example.org" { + stop; +} + +# Address test +if address "from:" "frop@example.org" { + stop; +} + +# Exists test +if exists "from:" { + stop; +} diff --git a/pigeonhole/tests/control-if.svtest b/pigeonhole/tests/control-if.svtest new file mode 100644 index 0000000..e11de64 --- /dev/null +++ b/pigeonhole/tests/control-if.svtest @@ -0,0 +1,292 @@ +require "vnd.dovecot.testsuite"; + +/* + * ## RFC 5228, Section 3.1. Control if (page 21) ## + */ + +test_set "message" text: +From: stephan@example.org +To: test@dovecot.example.net +Cc: friep@example.com +Subject: Test + +Test! +. +; + +/* + * Basic functionality + */ + +/* "The semantics are similar to those of any of the many other + * programming languages these control structures appear in. When the + * interpreter sees an "if", it evaluates the test associated with it. + * If the test is true, it executes the block associated with it. + * + * If the test of the "if" is false, it evaluates the test of the first + * "elsif" (if any). If the test of "elsif" is true, it runs the + * elsif's block. An elsif may be followed by an elsif, in which case, + * the interpreter repeats this process until it runs out of elsifs. + * + * When the interpreter runs out of elsifs, there may be an "else" case. + * If there is, and none of the if or elsif tests were true, the + * interpreter runs the else's block. + * + * This provides a way of performing exactly one of the blocks in the + * chain. + * " + */ + +/* + * TEST: Basic functionality: if true/false + */ + +test "Basic functionality: if true/false" { + /* Static */ + if true { + /* Correct */ + } else { + test_fail "executed wrong alternative for static true"; + } + + if false { + test_fail "executed wrong alternative for static false"; + } else { + /* Correct */ + } + + /* Dynamic */ + if exists "to" { + /* Correct */ + } else { + test_fail "executed wrong alternative for dynamic true"; + } + + if exists "flierp" { + test_fail "executed wrong alternative for dynamic false"; + } else { + /* Correct */ + } +} + +/* + * TEST: Basic functionality: if not true/false + */ + +test "Basic functionality: if not true/false" { + /* Static */ + if not true { + test_fail "executed wrong alternative for static not true"; + } else { + /* Correct */ + } + + if not false { + /* Correct */ + } else { + test_fail "executed wrong alternative for static not false"; + } + + /* Dynamic */ + if not exists "to" { + test_fail "executed wrong alternative for dynamic not true"; + } else { + /* Correct */ + } + + if not exists "flierp" { + /* Correct */ + } else { + test_fail "executed wrong alternative for dynamic not false"; + } +} + +/* + * TEST: Basic functionality: elseif true/false + */ + +test "Basic functionality: elseif true/false" { + /* Static */ + if true { + /* Correct */ + } elsif true { + test_fail "executed wrong alternative for static true-true (elsif)"; + } else { + test_fail "executed wrong alternative for static true-true (else)"; + } + + if true { + /* Correct */ + } elsif false { + test_fail "executed wrong alternative for static true-false (elsif)"; + } else { + test_fail "executed wrong alternative for static true-false (else)"; + } + + if false { + test_fail "executed wrong alternative for static false-true (if)"; + } elsif true { + /* Correct */ + } else { + test_fail "executed wrong alternative for static false-false (else)"; + } + + if false { + test_fail "executed wrong alternative for static false-false (if)"; + } elsif false { + test_fail "executed wrong alternative for static false-false (elsif)"; + } else { + /* Correct */ + } + + /* Dynamic */ + if address :is "from" "stephan@example.org" { + /* Correct */ + } elsif address :contains "from" "stephan" { + test_fail "executed wrong alternative for dynamic true-true (elsif)"; + } else { + test_fail "executed wrong alternative for dynamic true-true (else)"; + } + + if address :is "from" "stephan@example.org" { + /* Correct */ + } elsif address :is "from" "frop@example.com" { + test_fail "executed wrong alternative for dynamic true-false (elsif)"; + } else { + test_fail "executed wrong alternative for dynamic true-false (else)"; + } + + if address :is "from" "tss@example.net" { + test_fail "executed wrong alternative for dynamic false-true (if)"; + } elsif address :is "from" "stephan@example.org" { + /* Correct */ + } else { + test_fail "executed wrong alternative for dynamic false-true(else)"; + } + + if address :is "from" "tss@example.net" { + test_fail "executed wrong alternative for dynamic false-false (if)"; + } elsif address :is "to" "stephan@example.org" { + test_fail "executed wrong alternative for dynamic false-false (elsif)"; + } else { + /* Correct */ + } + + /* Static/Dynamic */ + + if true { + /* Correct */ + } elsif address :contains "from" "stephan" { + test_fail "executed wrong alternative for first-static true-true (elsif)"; + } else { + test_fail "executed wrong alternative for first-static true-true (else)"; + } + + if address :is "from" "stephan@example.org" { + /* Correct */ + } elsif true { + test_fail "executed wrong alternative for second-static true-true (elsif)"; + } else { + test_fail "executed wrong alternative for second-static true-true (else)"; + } + + if true { + /* Correct */ + } elsif address :is "from" "frop@example.com" { + test_fail "executed wrong alternative for first-static true-false (elsif)"; + } else { + test_fail "executed wrong alternative for first-static true-false (else)"; + } + + if address :is "from" "stephan@example.org" { + /* Correct */ + } elsif false { + test_fail "executed wrong alternative for second-static true-false (elsif)"; + } else { + test_fail "executed wrong alternative for second-static true-false (else)"; + } + + if false { + test_fail "executed wrong alternative for first-static false-true (if)"; + } elsif address :is "from" "stephan@example.org" { + /* Correct */ + } else { + test_fail "executed wrong alternative for first-static false-true(else)"; + } + + if address :is "from" "tss@example.net" { + test_fail "executed wrong alternative for second-static false-true (if)"; + } elsif true { + /* Correct */ + } else { + test_fail "executed wrong alternative for second-static false-true(else)"; + } + + if false { + test_fail "executed wrong alternative for first-static false-false (if)"; + } elsif address :is "to" "stephan@example.org" { + test_fail "executed wrong alternative for first-static false-false (elsif)"; + } else { + /* Correct */ + } + + if address :is "from" "tss@example.net" { + test_fail "executed wrong alternative for second-static false-false (if)"; + } elsif false { + test_fail "executed wrong alternative for second-static false-false (elsif)"; + } else { + /* Correct */ + } +} + +/* + * TEST: Basic functionality: nesting + */ + +test "Basic functionality: nesting" { + /* Static */ + if true { + if true { + if false { + test_fail "chose wrong static outcome: true->true->false"; + } else { + /* Correct */ + } + } else { + test_fail "chose wrong static outcome: true->false"; + } + } elsif true { + if false { + test_fail "chose wrong static outcome: false->true->false"; + } elsif true { + test_fail "chose wrong static outcome: false->true->true"; + } + } else { + test_fail "chose wrong static outcome: false->false"; + } + + /* Dynamic */ + + if exists "to" { + if exists "from" { + if exists "friep" { + test_fail "chose wrong dynamic outcome: true->true->false"; + } else { + /* Correct */ + } + } else { + test_fail "chose wrong dynamic outcome: true->false"; + } + } elsif exists "cc" { + if exists "frop" { + test_fail "chose wrong dynamic outcome: false->true->false"; + } elsif exists "from" { + test_fail "chose wrong dynamic outcome: false->true->true"; + } + } else { + test_fail "chose wrong dynamic outcome: false->false"; + } +} + + + diff --git a/pigeonhole/tests/control-stop.svtest b/pigeonhole/tests/control-stop.svtest new file mode 100644 index 0000000..b49199d --- /dev/null +++ b/pigeonhole/tests/control-stop.svtest @@ -0,0 +1,29 @@ +require "vnd.dovecot.testsuite"; + +/* + * ## RFC 5228, Section 3.3. Control stop (page 22) ## + */ + +/* + * TEST: End processing + */ + +/* "The "stop" action ends all processing. + * " + */ + +test "End processing" { + stop; + + test_fail "continued after stop"; +} + +/* + * TEST: Implicit keep + */ + +/* "If the implicit keep has not been cancelled, then it is taken. + * " + */ + +/* FIXME */ diff --git a/pigeonhole/tests/deprecated/imapflags/errors.svtest b/pigeonhole/tests/deprecated/imapflags/errors.svtest new file mode 100644 index 0000000..a9d9cde --- /dev/null +++ b/pigeonhole/tests/deprecated/imapflags/errors.svtest @@ -0,0 +1,24 @@ +require "vnd.dovecot.testsuite"; + +require "comparator-i;ascii-numeric"; +require "relational"; + +test "Deprecated imapflags extension used with imap4flags" { + if test_script_compile "errors/conflict.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "2" { + test_fail "wrong number of errors reported"; + } +} + +test "Deprecated imapflags extension used with imap4flags (ihave)" { + if test_script_compile "errors/conflict-ihave.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "wrong number of errors reported"; + } +} diff --git a/pigeonhole/tests/deprecated/imapflags/errors/conflict-ihave.sieve b/pigeonhole/tests/deprecated/imapflags/errors/conflict-ihave.sieve new file mode 100644 index 0000000..e924923 --- /dev/null +++ b/pigeonhole/tests/deprecated/imapflags/errors/conflict-ihave.sieve @@ -0,0 +1,6 @@ +require "imap4flags"; +require "ihave"; + +if ihave "imapflags" { + addflags "Frop"; +} diff --git a/pigeonhole/tests/deprecated/imapflags/errors/conflict.sieve b/pigeonhole/tests/deprecated/imapflags/errors/conflict.sieve new file mode 100644 index 0000000..1b18a42 --- /dev/null +++ b/pigeonhole/tests/deprecated/imapflags/errors/conflict.sieve @@ -0,0 +1,4 @@ +require "imapflags"; +require "imap4flags"; + +addflag "\\flagged"; diff --git a/pigeonhole/tests/deprecated/imapflags/execute.svtest b/pigeonhole/tests/deprecated/imapflags/execute.svtest new file mode 100644 index 0000000..ea6657b --- /dev/null +++ b/pigeonhole/tests/deprecated/imapflags/execute.svtest @@ -0,0 +1,92 @@ +require "vnd.dovecot.testsuite"; +require "fileinto"; +require "imap4flags"; +require "relational"; +require "comparator-i;ascii-numeric"; +require "mailbox"; + +test_set "message" text: +From: Henry von Flockenstoffen <henry@example.com> +To: Dieter von Ausburg <dieter@example.com> +Subject: Test message. + +Test message. +. +; + +test "Mark / Unmark" { + if not test_script_compile "execute/mark.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script execute failed"; + } + + if not test_result_execute { + test_fail "failed to execute first result"; + } + + test_result_reset; + + test_message :folder "Marked" 0; + + if not hasflag "\\flagged" { + test_fail "message not marked"; + } + + test_result_reset; + + test_message :folder "Unmarked" 0; + + if hasflag "\\flagged" { + test_fail "message not unmarked"; + } +} + +test_result_reset; +test "Setflag / Addflag / Removeflag" { + if not test_script_compile "execute/flags.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script execute failed"; + } + + if not test_result_execute { + test_fail "failed to execute first result"; + } + + test_result_reset; + + test_message :folder "Set" 0; + + if not hasflag "\\draft" { + test_fail "flag not set"; + } + + test_result_reset; + + test_message :folder "Add" 0; + + if not hasflag "\\draft" { + test_fail "flag not retained"; + } + + if not hasflag "\\flagged" { + test_fail "flag not added"; + } + + test_result_reset; + + test_message :folder "Remove" 0; + + if not hasflag "\\flagged" { + test_fail "flag not retained"; + } + + if hasflag "\\draft" { + test_fail "flag not removed"; + } +} diff --git a/pigeonhole/tests/deprecated/imapflags/execute/flags.sieve b/pigeonhole/tests/deprecated/imapflags/execute/flags.sieve new file mode 100644 index 0000000..ba68b44 --- /dev/null +++ b/pigeonhole/tests/deprecated/imapflags/execute/flags.sieve @@ -0,0 +1,12 @@ +require "imapflags"; +require "fileinto"; +require "mailbox"; + +setflag "\\draft"; +fileinto :create "Set"; + +addflag "\\flagged"; +fileinto :create "Add"; + +removeflag "\\draft"; +fileinto :create "Remove"; diff --git a/pigeonhole/tests/deprecated/imapflags/execute/mark.sieve b/pigeonhole/tests/deprecated/imapflags/execute/mark.sieve new file mode 100644 index 0000000..3216ca4 --- /dev/null +++ b/pigeonhole/tests/deprecated/imapflags/execute/mark.sieve @@ -0,0 +1,11 @@ +require "imapflags"; +require "fileinto"; +require "mailbox"; + +mark; + +fileinto :create "Marked"; + +unmark; + +fileinto :create "Unmarked"; diff --git a/pigeonhole/tests/deprecated/notify/basic.svtest b/pigeonhole/tests/deprecated/notify/basic.svtest new file mode 100644 index 0000000..974f8ca --- /dev/null +++ b/pigeonhole/tests/deprecated/notify/basic.svtest @@ -0,0 +1,59 @@ +require "vnd.dovecot.testsuite"; +require "notify"; +require "body"; + +test "Execute" { + /* Test to catch runtime segfaults */ + notify + :message "This is probably very important" + :low + :method "mailto" + :options ["stephan@example.com", "stephan@example.org"]; + + if not test_result_execute { + test_fail "Execute failed"; + } +} + +test_result_reset; + +test_set "message" text: +To: user@example.com +From: stephan@example.org +Subject: Mail + +Test! +. +; + +test "Substitutions" { + notify + :message "$from$: $subject$" + :options "stephan@example.com"; + if not test_result_execute { + test_fail "Execute failed"; + } + test_message :smtp 0; + if not body :contains "stephan@example.org: Mail" { + test_fail "Substitution failed"; + } +} + +test_result_reset; + +test_set "message" text: +To: user@example.com + +Test! +. +; + +test "Empty substitutions" { + notify + :message "$from$: $subject$" + :options "stephan@example.com"; + if not test_result_execute { + test_fail "Execute failed"; + } +} + diff --git a/pigeonhole/tests/deprecated/notify/denotify.svtest b/pigeonhole/tests/deprecated/notify/denotify.svtest new file mode 100644 index 0000000..9f752e1 --- /dev/null +++ b/pigeonhole/tests/deprecated/notify/denotify.svtest @@ -0,0 +1,279 @@ +require "vnd.dovecot.testsuite"; +require "notify"; +require "envelope"; + +/* + * Denotify all + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test "Denotify All" { + notify :options "timo@example.com"; + notify :options "stephan@dovecot.example.net"; + notify :options "postmaster@frop.example.org"; + denotify; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + if test_message :smtp 0 { + test_fail "no notifications should have been sent"; + } +} + +/* + * Denotify First + */ + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test "Denotify ID First" { + /* #1 */ + notify :options "timo@example.com" :id "aap"; + + /* #2 */ + notify :options "stephan@dovecot.example.net" :id "noot"; + + /* #3 */ + notify :options "postmaster@frop.example.org" :id "mies"; + + denotify :is "aap"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + if not test_message :smtp 0 { + test_fail "two notifications should have been sent (#2 missing)"; + } + + if not envelope "to" "stephan@dovecot.example.net" { + test_fail "message #2 unexpectedly missing from output"; + } + + if not test_message :smtp 1 { + test_fail "two notifications should have been sent (#3 missing)"; + } + + if not envelope "to" "postmaster@frop.example.org" { + test_fail "message #3 unexpectedly missing from output"; + } + + if test_message :smtp 2 { + test_fail "too many notifications sent"; + } +} + +/* + * Denotify Middle + */ + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test "Denotify ID Middle" { + /* #1 */ + notify :options "timo@example.com" :id "aap"; + + /* #2 */ + notify :options "stephan@dovecot.example.net" :id "noot"; + + /* #3 */ + notify :options "postmaster@frop.example.org" :id "mies"; + + denotify :is "noot"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + if not test_message :smtp 0 { + test_fail "two notifications should have been sent (#1 missing)"; + } + + if not envelope "to" "timo@example.com" { + test_fail "message #1 unexpectedly missing from output"; + } + + if not test_message :smtp 1 { + test_fail "two notifications should have been sent (#3 missing)"; + } + + if not envelope "to" "postmaster@frop.example.org" { + test_fail "message #3 unexpectedly missing from output"; + } + + if test_message :smtp 2 { + test_fail "too many notifications sent"; + } +} + +/* + * Denotify Last + */ + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test "Denotify ID Last" { + /* #1 */ + notify :options "timo@example.com" :id "aap"; + + /* #2 */ + notify :options "stephan@dovecot.example.net" :id "noot"; + + /* #3 */ + notify :options "postmaster@frop.example.org" :id "mies"; + + denotify :is "mies"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + if not test_message :smtp 0 { + test_fail "two notifications should have been sent (#1 missing)"; + } + + if not envelope "to" "timo@example.com" { + test_fail "message #1 unexpectedly missing from output"; + } + + if not test_message :smtp 1 { + test_fail "two notifications should have been sent (#2 missing)"; + } + + if not envelope "to" "stephan@dovecot.example.net" { + test_fail "message #2 unexpectedly missing from output"; + } + + if test_message :smtp 2 { + test_fail "too many notifications sent"; + } +} + + +/* + * Denotify Matching + */ + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test "Denotify Matching" { + /* #1 */ + notify :options "timo@example.com" :id "frop"; + + /* #2 */ + notify :options "stephan@dovecot.example.net" :id "noot"; + + /* #3 */ + notify :options "postmaster@frop.example.org" :id "friep"; + + denotify :matches "fr*"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + if not test_message :smtp 0 { + test_fail "one notification should have been sent"; + } + + if not envelope "to" "stephan@dovecot.example.net" { + test_fail "message #2 unexpectedly missing from output"; + } + + if test_message :smtp 1 { + test_fail "too many notifications sent"; + } +} + + +/* + * Denotify Matching + */ + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test "Denotify Matching Importance" { + /* #1 */ + notify :options "timo@example.com" :id "frop" :low; + + /* #2 */ + notify :options "stephan@dovecot.example.net" :id "frml" :high; + + /* #3 */ + notify :options "postmaster@frop.example.org" :id "friep" :low; + + denotify :matches "fr*" :low; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + if not test_message :smtp 0 { + test_fail "one notification should have been sent"; + } + + if not envelope "to" "stephan@dovecot.example.net" { + test_fail "message #2 unexpectedly missing from output"; + } + + if test_message :smtp 1 { + test_fail "too many notifications sent"; + } +} + + diff --git a/pigeonhole/tests/deprecated/notify/errors.svtest b/pigeonhole/tests/deprecated/notify/errors.svtest new file mode 100644 index 0000000..549cb6b --- /dev/null +++ b/pigeonhole/tests/deprecated/notify/errors.svtest @@ -0,0 +1,33 @@ +require "vnd.dovecot.testsuite"; +require "comparator-i;ascii-numeric"; +require "relational"; + +test "Invalid :options argument (FIXME: count only)" { + if test_script_compile "errors/options.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "wrong number of errors reported"; + } +} + +test "Deprecated notify extension used with enotify" { + if test_script_compile "errors/conflict.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "wrong number of errors reported"; + } +} + +test "Deprecated notify extension used with enotify (ihave)" { + if test_script_compile "errors/conflict-ihave.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "wrong number of errors reported"; + } +} diff --git a/pigeonhole/tests/deprecated/notify/errors/conflict-ihave.sieve b/pigeonhole/tests/deprecated/notify/errors/conflict-ihave.sieve new file mode 100644 index 0000000..9686f03 --- /dev/null +++ b/pigeonhole/tests/deprecated/notify/errors/conflict-ihave.sieve @@ -0,0 +1,8 @@ +require "enotify"; +require "ihave"; + +# 1: Conflict +if ihave "notify" { + # 2: Syntax wrong for enotify (and not skipped in compile) + notify :options "frop@frop.example.org"; +} diff --git a/pigeonhole/tests/deprecated/notify/errors/conflict.sieve b/pigeonhole/tests/deprecated/notify/errors/conflict.sieve new file mode 100644 index 0000000..46a6283 --- /dev/null +++ b/pigeonhole/tests/deprecated/notify/errors/conflict.sieve @@ -0,0 +1,4 @@ +require "enotify"; +require "notify"; + +notify :options "frop@frop.example.org"; diff --git a/pigeonhole/tests/deprecated/notify/errors/options.sieve b/pigeonhole/tests/deprecated/notify/errors/options.sieve new file mode 100644 index 0000000..c86fea0 --- /dev/null +++ b/pigeonhole/tests/deprecated/notify/errors/options.sieve @@ -0,0 +1,11 @@ +require "notify"; + +# 1: empty option +notify :options ""; + +# 2: invalid address syntax +notify :options "frop#frop.example.org"; + +# Valid +notify :options "frop@frop.example.org"; + diff --git a/pigeonhole/tests/deprecated/notify/execute.svtest b/pigeonhole/tests/deprecated/notify/execute.svtest new file mode 100644 index 0000000..90fde47 --- /dev/null +++ b/pigeonhole/tests/deprecated/notify/execute.svtest @@ -0,0 +1,25 @@ +require "vnd.dovecot.testsuite"; +require "relational"; + + +/* + * Execution testing (currently just meant to trigger any segfaults) + */ + +test "Duplicate recipients" { + if not test_script_compile "execute/duplicates.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script execute failed"; + } + + if test_result_action :count "ne" "2" { + test_fail "second notify action was discarded entirely"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } +} diff --git a/pigeonhole/tests/deprecated/notify/execute/duplicates.sieve b/pigeonhole/tests/deprecated/notify/execute/duplicates.sieve new file mode 100644 index 0000000..ef3fa5f --- /dev/null +++ b/pigeonhole/tests/deprecated/notify/execute/duplicates.sieve @@ -0,0 +1,4 @@ +require "notify"; + +notify :message "Incoming stupidity." :options ["stephan@example.org", "stephan@friep.example.com", "idiot@example.org"]; +notify :message "There it is." :options ["tss@example.net", "stephan@example.org", "idiot@example.org", "nico@frop.example.org", "stephan@friep.example.com"]; diff --git a/pigeonhole/tests/deprecated/notify/mailto.svtest b/pigeonhole/tests/deprecated/notify/mailto.svtest new file mode 100644 index 0000000..1724339 --- /dev/null +++ b/pigeonhole/tests/deprecated/notify/mailto.svtest @@ -0,0 +1,317 @@ +require "vnd.dovecot.testsuite"; + +require "notify"; +require "body"; +require "relational"; +require "comparator-i;ascii-numeric"; + +/* + * Simple test + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test "Simple" { + notify :method "mailto" :options "stephan@example.org"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not header :matches "Auto-Submitted" "auto-generated*" { + test_fail "auto-submitted header set inappropriately"; + } + + if not exists "X-Sieve" { + test_fail "x-sieve header missing from outgoing message"; + } +} + +/* + * Multiple recipients + */ + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test "Multiple recipients" { + notify :options ["timo@example.com","stephan@dovecot.example.net","postmaster@frop.example.org"]; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not address :is "to" "timo@example.com" { + test_fail "first To address missing"; + } + + test_message :smtp 1; + + if not address :is "to" "stephan@dovecot.example.net" { + test_fail "second To address missing"; + } + + if not header :matches "Auto-Submitted" "auto-generated*" { + test_fail "auto-submitted header not found for second message"; + } + + test_message :smtp 2; + + if not address :is "to" "postmaster@frop.example.org" { + test_fail "third To address missing"; + } + + if not header :matches "Auto-Submitted" "auto-generated*" { + test_fail "auto-submitted header not found for third message"; + } + + if not address :count "eq" :comparator "i;ascii-numeric" "to" "3" { + test_fail "wrong number of recipients in To header"; + } + + if not address :count "eq" :comparator "i;ascii-numeric" "cc" "0" { + test_fail "too many recipients in Cc header"; + } +} + +/* + * Duplicate recipients + */ + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test "Duplicate recipients" { + notify :options ["timo@example.com", "stephan@dovecot.example.net", "stephan@dovecot.example.net"]; + notify :options ["timo@example.com", "stephan@example.org"]; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 2; + + if address "To" "stephan@dovecot.example.net" { + test_fail "duplicate recipient not removed from first message"; + } + + if address "To" "timo@example.com" { + test_fail "duplicate recipient not removed from second message"; + } +} + +/* + * Notifying on automated messages + */ + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Auto-submitted: auto-notify +Subject: Frop! + +Klutsefluts. +. +; + +test "Notifying on automated messages" { + notify :options "stephan@example.org"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + if test_message :smtp 0 { + test_fail "notified of auto-submitted message"; + } +} + +test_result_reset; + +test_set "message" text: +To: nico@frop.example.org +From: stephan@example.org +Subject: Test + +Test. Test +Frop! +. +; + +test "Body; Singular Message" { + notify :low :id "frop" :options "stephan@example.org" + :message text: +Received interesting message: + +$text$ + +You have been notified. +. +; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not body :raw :contains "Received interesting message" { + test_fail "notification has no heading"; + } + + if not body :raw :contains "You have been notified" { + test_fail "notification has no footer"; + } + + if not allof( + body :raw :contains "Test. Test", + body :raw :contains "Frop" ) { + test_fail "notification has no original message"; + } +} + +test_result_reset; + +test_set "message" text: +To: nico@frop.example.org +From: stephan@example.org +Subject: Test + +Test. Test +Frop! +. +; + +test "Body; $text[maxsize]$" { + notify :low :id "frop" :options "sirius@example.org" + :message text: +Received interesting message: + +$text[5]$ + +You have been notified. +. +; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not body :raw :contains "Received interesting message" { + test_fail "notification has no heading"; + } + + if not body :raw :contains "You have been notified" { + test_fail "notification has no footer"; + } + + if anyof( + body :raw :contains "Test. Test", + body :raw :contains "Frop" ) { + test_fail "original message in notification is not truncated"; + } + + if not body :raw :contains "Test." { + test_fail "notification does not contain the required message"; + } +} + +test_result_reset; + +test_set "message" text: +From: Whomever <whoever@example.com> +To: Someone <someone@example.com> +Date: Sat, 10 Oct 2009 00:30:04 +0200 +Subject: whatever +Content-Type: multipart/mixed; boundary=outer + +This is a multi-part message in MIME format. + +--outer +Content-Type: multipart/alternative; boundary=inner + +This is a nested multi-part message in MIME format. + +--inner +Content-Type: application/sieve; charset="us-ascii" + +keep; + +--inner +Content-Type: text/plain; charset="us-ascii" + +Friep! + +--inner-- + +This is the end of the inner MIME multipart. + +--outer +Content-Type: message/rfc822 + +From: Someone Else +Subject: hello request + +Please say Hello + +--outer-- + +This is the end of the outer MIME multipart. +. +; + +test "Body; Multipart Message" { + notify :low :id "frop" :options "stephan@example.org" + :message text: +Received interesting message: + +$text$ + +You have been notified. +. +; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not body :raw :contains "Friep!" { + test_fail "notification has incorrect content"; + } +} + + + diff --git a/pigeonhole/tests/execute/actions.svtest b/pigeonhole/tests/execute/actions.svtest new file mode 100644 index 0000000..3f517fa --- /dev/null +++ b/pigeonhole/tests/execute/actions.svtest @@ -0,0 +1,80 @@ +require "vnd.dovecot.testsuite"; +require "relational"; +require "comparator-i;ascii-numeric"; + +test_set "message" text: +To: nico@frop.example.org +From: stephan@example.org +Subject: Test + +Test. +. +; + +test_mailbox_create "INBOX.VB"; +test_mailbox_create "INBOX.backup"; + +test "Fileinto" { + if not test_script_compile "actions/fileinto.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script run failed"; + } + + if not test_result_action :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "wrong number of actions in result"; + } + + if not test_result_action :index 1 "store" { + test_fail "first action is not 'store'"; + } + + if not test_result_action :index 2 "store" { + test_fail "second action is not 'store'"; + } + + if not test_result_action :index 3 "keep" { + test_fail "third action is not 'keep'"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } +} + +test "Redirect" { + if not test_script_compile "actions/redirect.sieve" { + test_fail "compile failed"; + } + + if not test_script_run { + test_fail "execute failed"; + } + + if not test_result_action :count "eq" :comparator "i;ascii-numeric" "4" { + test_fail "wrong number of actions in result"; + } + + if not test_result_action :index 1 "redirect" { + test_fail "first action is not 'redirect'"; + } + + if not test_result_action :index 2 "keep" { + test_fail "second action is not 'keep'"; + } + + if not test_result_action :index 3 "redirect" { + test_fail "third action is not 'redirect'"; + } + + if not test_result_action :index 4 "redirect" { + test_fail "fourth action is not 'redirect'"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } +} + diff --git a/pigeonhole/tests/execute/actions/fileinto.sieve b/pigeonhole/tests/execute/actions/fileinto.sieve new file mode 100644 index 0000000..e9c133b --- /dev/null +++ b/pigeonhole/tests/execute/actions/fileinto.sieve @@ -0,0 +1,17 @@ +require "fileinto"; + +/* Three store actions */ + +if address :contains "to" "frop.example" { + /* #1 */ + fileinto "INBOX.VB"; +} + +/* #2 */ +fileinto "INBOX.backup"; + +/* #3 */ +keep; + +/* Duplicate of keep */ +fileinto "INBOX"; diff --git a/pigeonhole/tests/execute/actions/redirect.sieve b/pigeonhole/tests/execute/actions/redirect.sieve new file mode 100644 index 0000000..7adc23e --- /dev/null +++ b/pigeonhole/tests/execute/actions/redirect.sieve @@ -0,0 +1,17 @@ +if address :contains "to" "frop.example" { + /* #1 */ + redirect "stephan@example.com"; + + /* #2 */ + keep; +} + +/* #3 */ +redirect "stephan@example.org"; + +/* #4 */ +redirect "nico@example.nl"; + +/* Duplicates */ +redirect "Stephan Bosch <stephan@example.com>"; +keep; diff --git a/pigeonhole/tests/execute/address-normalize.svtest b/pigeonhole/tests/execute/address-normalize.svtest new file mode 100644 index 0000000..e826bde --- /dev/null +++ b/pigeonhole/tests/execute/address-normalize.svtest @@ -0,0 +1,46 @@ +require "vnd.dovecot.testsuite"; +require "envelope"; + +test_set "message" text: +From: tss@example.net +To: stephan@example.org +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "timo@example.net"; +test_set "envelope.to" "\"sirius\"@example.org"; + +/* + * Mail address normalization - redirect + */ + +test "Mail address normalization - redirect" { + redirect "\"S[r]us\"@example.net"; + redirect "\"Sirius\"@example.net"; + redirect "\"Stephan Bosch\" <\"S.Bosch\"@example.net>"; + + if not test_result_execute { + test_fail "failed to execute redirect"; + } + + test_message :smtp 0; + + if not envelope :is "to" "\"S[r]us\"@example.net" { + test_fail "envelope recipient incorrect"; + } + + test_message :smtp 1; + + if not envelope :is "to" "Sirius@example.net" { + test_fail "envelope recipient incorrect"; + } + + test_message :smtp 2; + + if not envelope :is "to" "S.Bosch@example.net" { + test_fail "envelope recipient incorrect"; + } +} diff --git a/pigeonhole/tests/execute/errors-cpu-limit.svtest b/pigeonhole/tests/execute/errors-cpu-limit.svtest new file mode 100644 index 0000000..4a045bc --- /dev/null +++ b/pigeonhole/tests/execute/errors-cpu-limit.svtest @@ -0,0 +1,363 @@ +require "vnd.dovecot.testsuite"; + +test_config_set "sieve_max_cpu_time" "2"; +test_config_reload; + +test_set "message" text: +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary= + +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +. +; + +test "CPU limit" { + if not test_script_compile "errors/cpu-limit.sieve" { + test_fail "script compile failed"; + } + + if test_script_run { + test_fail "script execute should have failed"; + } +} + diff --git a/pigeonhole/tests/execute/errors.svtest b/pigeonhole/tests/execute/errors.svtest new file mode 100644 index 0000000..45bc39c --- /dev/null +++ b/pigeonhole/tests/execute/errors.svtest @@ -0,0 +1,152 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; +require "fileinto"; + +test "Action conflicts: reject <-> fileinto" { + if not test_script_compile "errors/conflict-reject-fileinto.sieve" { + test_fail "compile failed"; + } + + if test_script_run { + test_fail "execution should have failed"; + } + + if test_error :count "gt" :comparator "i;ascii-numeric" "1" { + test_fail "too many runtime errors reported"; + } +} + +test "Action conflicts: reject <-> keep" { + if not test_script_compile "errors/conflict-reject-keep.sieve" { + test_fail "compile failed"; + } + + if test_script_run { + test_fail "execution should have failed"; + } + + if test_error :count "gt" :comparator "i;ascii-numeric" "1" { + test_fail "too many runtime errors reported"; + } +} + +test "Action conflicts: reject <-> redirect" { + if not test_script_compile "errors/conflict-reject-redirect.sieve" { + test_fail "compile failed"; + } + + if test_script_run { + test_fail "execution should have failed"; + } + + if test_error :count "gt" :comparator "i;ascii-numeric" "1" { + test_fail "too many runtime errors reported"; + } +} + +test "Action limit" { + if not test_script_compile "errors/actions-limit.sieve" { + test_fail "compile failed"; + } + + if test_script_run { + test_fail "execution should have failed"; + } + + if test_error :count "gt" :comparator "i;ascii-numeric" "1" { + test_fail "too many runtime errors reported"; + } + + if not test_error :index 1 :contains "total number of actions exceeds policy limit"{ + test_fail "unexpected error reported"; + } +} + +test "Redirect limit" { + if not test_script_compile "errors/redirect-limit.sieve" { + test_fail "compile failed"; + } + + if test_script_run { + test_fail "execution should have failed"; + } + + if test_error :count "gt" :comparator "i;ascii-numeric" "1" { + test_fail "too many runtime errors reported"; + } + + if not test_error :index 1 :contains "number of redirect actions exceeds policy limit"{ + test_fail "unexpected error reported"; + } +} + +test "Fileinto missing folder" { + if not test_script_compile "errors/fileinto.sieve" { + test_fail "compile failed"; + } + + test_mailbox_create "INBOX"; + + if not test_script_run { + test_fail "execution failed"; + } + + if test_result_execute { + test_fail "execution of result should have failed"; + } + + if test_error :count "gt" :comparator "i;ascii-numeric" "1" { + test_fail "too many runtime errors reported"; + } + + if not allof ( + test_error :index 1 :contains "failed to store into mailbox", + test_error :index 1 :contains "exist", + test_error :index 1 :contains "FROP") { + test_fail "unexpected error reported"; + } +} + +test "Fileinto invalid folder name" { + if not test_script_compile "errors/fileinto-invalid-name.sieve" { + test_fail "compile failed"; + } + + if not test_script_run { + test_fail "execution failed"; + } + + if test_result_execute { + test_fail "execution of result should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "1" { + test_fail "wrong number of runtime errors reported"; + } + + if not allof ( + test_error :index 1 :contains "failed to store into mailbox", + test_error :index 1 :contains "name") { + test_fail "unexpected error reported"; + } +} + +test "Fileinto bad UTF-8 in folder name" { + if not test_script_compile "errors/fileinto-bad-utf8.sieve" { + test_fail "compile failed"; + } + + if test_script_run { + test_fail "execution should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "1" { + test_fail "wrong number of runtime errors reported"; + } + + if not test_error :index 1 :contains "invalid folder name" { + test_fail "unexpected error reported"; + } +} diff --git a/pigeonhole/tests/execute/errors/action-duplicates.sieve b/pigeonhole/tests/execute/errors/action-duplicates.sieve new file mode 100644 index 0000000..6d5370d --- /dev/null +++ b/pigeonhole/tests/execute/errors/action-duplicates.sieve @@ -0,0 +1,4 @@ +require "reject"; + +reject "Message is not appreciated."; +reject "No, really, it is not appreciated."; diff --git a/pigeonhole/tests/execute/errors/actions-limit.sieve b/pigeonhole/tests/execute/errors/actions-limit.sieve new file mode 100644 index 0000000..3ae33a3 --- /dev/null +++ b/pigeonhole/tests/execute/errors/actions-limit.sieve @@ -0,0 +1,35 @@ +require "fileinto"; + +fileinto "box1"; +fileinto "box2"; +fileinto "box3"; +fileinto "box4"; +fileinto "box5"; +fileinto "box6"; +fileinto "box7"; +fileinto "box8"; +fileinto "box9"; +fileinto "box10"; +fileinto "box11"; +fileinto "box12"; +fileinto "box13"; +fileinto "box14"; +fileinto "box15"; +fileinto "box16"; +fileinto "box17"; +fileinto "box18"; +fileinto "box19"; +fileinto "box20"; +fileinto "box21"; +fileinto "box22"; +fileinto "box23"; +fileinto "box24"; +fileinto "box25"; +fileinto "box26"; +fileinto "box27"; +fileinto "box28"; +redirect "address1@example.com"; +redirect "address2@example.com"; +redirect "address3@example.com"; +redirect "address4@example.com"; +keep; diff --git a/pigeonhole/tests/execute/errors/conflict-reject-fileinto.sieve b/pigeonhole/tests/execute/errors/conflict-reject-fileinto.sieve new file mode 100644 index 0000000..85ef139 --- /dev/null +++ b/pigeonhole/tests/execute/errors/conflict-reject-fileinto.sieve @@ -0,0 +1,5 @@ +require "reject"; +require "fileinto"; + +reject "No nonsense in my mailbox."; +fileinto "Spam"; diff --git a/pigeonhole/tests/execute/errors/conflict-reject-keep.sieve b/pigeonhole/tests/execute/errors/conflict-reject-keep.sieve new file mode 100644 index 0000000..569a4ac --- /dev/null +++ b/pigeonhole/tests/execute/errors/conflict-reject-keep.sieve @@ -0,0 +1,4 @@ +require "reject"; + +reject "I am not interested in your nonsense."; +keep; diff --git a/pigeonhole/tests/execute/errors/conflict-reject-redirect.sieve b/pigeonhole/tests/execute/errors/conflict-reject-redirect.sieve new file mode 100644 index 0000000..d012269 --- /dev/null +++ b/pigeonhole/tests/execute/errors/conflict-reject-redirect.sieve @@ -0,0 +1,4 @@ +require "reject"; + +reject "I am not interested in your nonsense."; +redirect "frop@example.com"; diff --git a/pigeonhole/tests/execute/errors/cpu-limit.sieve b/pigeonhole/tests/execute/errors/cpu-limit.sieve new file mode 100644 index 0000000..8532a4b --- /dev/null +++ b/pigeonhole/tests/execute/errors/cpu-limit.sieve @@ -0,0 +1,145 @@ +require ["mime","foreverypart","fileinto", "variables", "regex"]; + +# Here we create an inefficient regex with long compilation time +set "my_exp" "^(((A)|(AB)|(ABC)|(ABCD)|(ABCDE)|(ABCDEF)|(ABCDEFG)|(ABCDEFGH)|(ABCDEFGHI)|(ABCDEFGHIJ)|(ABCDEFGHIJK)|(ABCDEFGHIJKL)|(ABCDEFGHIJKLM)|(ABCDEFGHIJKLMN)|(ABCDEFGHIJKLMNO)|(ABCDEFGHIJKLMNOP)|(ABCDEFGHIJKLMNOPQ)|(ABCDEFGHIJKLMNOPQR))?((B)|(BC)|(BCD)|(BCDE)|(BCDEF)|(BCDEFG)|(BCDEFGH)|(BCDEFGHI)|(BCDEFGHIJ)|(BCDEFGHIJK)|(BCDEFGHIJKL)|(BCDEFGHIJKLM)|(BCDEFGHIJKLMN)|(BCDEFGHIJKLMNO)|(BCDEFGHIJKLMNOP)|(BCDEFGHIJKLMNOPQ)|(BCDEFGHIJKLMNOPQR))?((C)|(CD)|(CDE)|(CDEF)|(CDEFG)|(CDEFGH)|(CDEFGHI)|(CDEFGHIJ)|(CDEFGHIJK)|(CDEFGHIJKL)|(CDEFGHIJKLM)|(CDEFGHIJKLMN)|(CDEFGHIJKLMNO)|(CDEFGHIJKLMNOP)|(CDEFGHIJKLMNOPQ)|(CDEFGHIJKLMNOPQR))?((D)|(DE)|(DEF)|(DEFG)|(DEFGH)|(DEFGHI)|(DEFGHIJ)|(DEFGHIJK)|(DEFGHIJKL)|(DEFGHIJKLM)|(DEFGHIJKLMN)|(DEFGHIJKLMNO)|(DEFGHIJKLMNOP)|(DEFGHIJKLMNOPQ)|(DEFGHIJKLMNOPQR))?((E)|(EF)|(EFG)|(EFGH)|(EFGHI)|(EFGHIJ)|(EFGHIJK)|(EFGHIJKL)|(EFGHIJKLM)|(EFGHIJKLMN)|(EFGHIJKLMNO)|(EFGHIJKLMNOP)|(EFGHIJKLMNOPQ)|(EFGHIJKLMNOPQR))?((F)|(FG)|(FGH)|(FGHI)|(FGHIJ)|(FGHIJK)|(FGHIJKL)|(FGHIJKLM)|(FGHIJKLMN)|(FGHIJKLMNO)|(FGHIJKLMNOP)|(FGHIJKLMNOPQ)|(FGHIJKLMNOPQR))?((G)|(GH)|(GHI)|(GHIJ)|(GHIJK)|(GHIJKL)|(GHIJKLM)|(GHIJKLMN)|(GHIJKLMNO)|(GHIJKLMNOP)|(GHIJKLMNOPQ)|(GHIJKLMNOPQR))?((H)|(HI)|(HIJ)|(HIJK)|(HIJKL)|(HIJKLM)|(HIJKLMN)|(HIJKLMNO)|(HIJKLMNOP)|(HIJKLMNOPQ)|(HIJKLMNOPQR))?((I)|(IJ)|(IJK)|(IJKL)|(IJKLM)|(IJKLMN)|(IJKLMNO)|(IJKLMNOP)|(IJKLMNOPQ)|(IJKLMNOPQR))?((J)|(JK)|(JKL)|(JKLM)|(JKLMN)|(JKLMNO)|(JKLMNOP)|(JKLMNOPQ)|(JKLMNOPQR))?((K)|(KL)|(KLM)|(KLMN)|(KLMNO)|(KLMNOP)|(KLMNOPQ)|(KLMNOPQR))?((L)|(LM)|(LMN)|(LMNO)|(LMNOP)|(LMNOPQ)|(LMNOPQR))?((M)|(MN)|(MNO)|(MNOP)|(MNOPQ)|(MNOPQR))?((N)|(NO)|(NOP)|(NOPQ)|(NOPQR))?((O)|(OP)|(OPQ)|(OPQR))?((P)|(PQ)|(PQR))?((Q)|(QR))?((R))?((R)|(RQ)|(RQP)|(RQPO)|(RQPON)|(RQPONM)|(RQPONML)|(RQPONMLK)|(RQPONMLKJ)|(RQPONMLKJI)|(RQPONMLKJIH)|(RQPONMLKJIHG)|(RQPONMLKJIHGF)|(RQPONMLKJIHGFE)|(RQPONMLKJIHGFED)|(RQPONMLKJIHGFEDC)|(RQPONMLKJIHGFEDCB)|(RQPONMLKJIHGFEDCBA))?((Q)|(QP)|(QPO)|(QPON)|(QPONM)|(QPONML)|(QPONMLK)|(QPONMLKJ)|(QPONMLKJI)|(QPONMLKJIH)|(QPONMLKJIHG)|(QPONMLKJIHGF)|(QPONMLKJIHGFE)|(QPONMLKJIHGFED)|(QPONMLKJIHGFEDC)|(QPONMLKJIHGFEDCB)|(QPONMLKJIHGFEDCBA))?((P)|(PO)|(PON)|(PONM)|(PONML)|(PONMLK)|(PONMLKJ)|(PONMLKJI)|(PONMLKJIH)|(PONMLKJIHG)|(PONMLKJIHGF)|(PONMLKJIHGFE)|(PONMLKJIHGFED)|(PONMLKJIHGFEDC)|(PONMLKJIHGFEDCB)|(PONMLKJIHGFEDCBA))?((O)|(ON)|(ONM)|(ONML)|(ONMLK)|(ONMLKJ)|(ONMLKJI)|(ONMLKJIH)|(ONMLKJIHG)|(ONMLKJIHGF)|(ONMLKJIHGFE)|(ONMLKJIHGFED)|(ONMLKJIHGFEDC)|(ONMLKJIHGFEDCB)|(ONMLKJIHGFEDCBA))?((N)|(NM)|(NML)|(NMLK)|(NMLKJ)|(NMLKJI)|(NMLKJIH)|(NMLKJIHG)|(NMLKJIHGF)|(NMLKJIHGFE)|(NMLKJIHGFED)|(NMLKJIHGFEDC)|(NMLKJIHGFEDCB)|(NMLKJIHGFEDCBA))?((M)|(ML)|(MLK)|(MLKJ)|(MLKJI)|(MLKJIH)|(MLKJIHG)|(MLKJIHGF)|(MLKJIHGFE)|(MLKJIHGFED)|(MLKJIHGFEDC)|(MLKJIHGFEDCB)|(MLKJIHGFEDCBA))?((L)|(LK)|(LKJ)|(LKJI)|(LKJIH)|(LKJIHG)|(LKJIHGF)|(LKJIHGFE)|(LKJIHGFED)|(LKJIHGFEDC)|(LKJIHGFEDCB)|(LKJIHGFEDCBA))?((K)|(KJ)|(KJI)|(KJIH)|(KJIHG)|(KJIHGF)|(KJIHGFE)|(KJIHGFED)|(KJIHGFEDC)|(KJIHGFEDCB)|(KJIHGFEDCBA))?((J)|(JI)|(JIH)|(JIHG)|(JIHGF)|(JIHGFE)|(JIHGFED)|(JIHGFEDC)|(JIHGFEDCB)|(JIHGFEDCBA))?((I)|(IH)|(IHG)|(IHGF)|(IHGFE)|(IHGFED)|(IHGFEDC)|(IHGFEDCB)|(IHGFEDCBA))?((H)|(HG)|(HGF)|(HGFE)|(HGFED)|(HGFEDC)|(HGFEDCB)|(HGFEDCBA))?((G)|(GF)|(GFE)|(GFED)|(GFEDC)|(GFEDCB)|(GFEDCBA))?((F)|(FE)|(FED)|(FEDC)|(FEDCB)|(FEDCBA))?((E)|(ED)|(EDC)|(EDCB)|(EDCBA))?((D)|(DC)|(DCB)|(DCBA))?((C)|(CB)|(CBA))?((B)|(BA))?((A))?)+$"; +set "a" "ABCDEFGHIJKLMNOPQR"; +set "b" "RQPONMLKJIHGFEDCBA"; +set "c" "${a}${b}${a}${b}${a}${b}${a}${b}"; +set "e" "${c}${c}${c}${c}${c}${c}${c}${c}"; +set "f" "${e}${e}${e}${e}${e}${e}${e}${e}"; + +# We create a string on which this regex will spend enough time (around 200 ms) +set "final" "${f}${f}${f}${f}${f}${f}${f}${f}${f}${f}${f}${f}${f}${f}@"; + +# We repeat the throttling process for every mime part +foreverypart { + # We use several if statements to multiply the cpu time consumed by one match + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } + if string :regex "${final}" "${my_exp}" { discard; } + if string :regex "${final}" "${my_exp}" { keep; } +} diff --git a/pigeonhole/tests/execute/errors/fileinto-bad-utf8.sieve b/pigeonhole/tests/execute/errors/fileinto-bad-utf8.sieve new file mode 100644 index 0000000..3e57c92 --- /dev/null +++ b/pigeonhole/tests/execute/errors/fileinto-bad-utf8.sieve @@ -0,0 +1,7 @@ +require "fileinto"; +require "variables"; +require "encoded-character"; + +set "mailbox" "${hex:ff}rop"; +fileinto "${mailbox}"; + diff --git a/pigeonhole/tests/execute/errors/fileinto-invalid-name.sieve b/pigeonhole/tests/execute/errors/fileinto-invalid-name.sieve new file mode 100644 index 0000000..871323e --- /dev/null +++ b/pigeonhole/tests/execute/errors/fileinto-invalid-name.sieve @@ -0,0 +1,5 @@ +require "fileinto"; +require "mailbox"; + +fileinto :create "foo//somedomain/org"; + diff --git a/pigeonhole/tests/execute/errors/fileinto.sieve b/pigeonhole/tests/execute/errors/fileinto.sieve new file mode 100644 index 0000000..185674c --- /dev/null +++ b/pigeonhole/tests/execute/errors/fileinto.sieve @@ -0,0 +1,3 @@ +require "fileinto"; + +fileinto "FROP"; diff --git a/pigeonhole/tests/execute/errors/redirect-limit.sieve b/pigeonhole/tests/execute/errors/redirect-limit.sieve new file mode 100644 index 0000000..86cfda0 --- /dev/null +++ b/pigeonhole/tests/execute/errors/redirect-limit.sieve @@ -0,0 +1,5 @@ +redirect "address1@example.com"; +redirect "address2@example.com"; +redirect "address3@example.com"; +redirect "address4@example.com"; +redirect "address5@example.com"; diff --git a/pigeonhole/tests/execute/examples.svtest b/pigeonhole/tests/execute/examples.svtest new file mode 100644 index 0000000..6143018 --- /dev/null +++ b/pigeonhole/tests/execute/examples.svtest @@ -0,0 +1,115 @@ +require "vnd.dovecot.testsuite"; + +/* Compile and execute all example scripts to trigger + * any Segfaults. No message is set and no results are checked. + */ + +test "Elvey example" { + if not test_script_compile "../../examples/elvey.sieve" { + test_fail "could not compile"; + } + + test_binary_save "elvey"; + test_binary_load "elvey"; + + if not test_script_run { } +} + +test "M. Johnson example" { + if not test_script_compile "../../examples/mjohnson.sieve" { + test_fail "could not compile"; + } + + test_binary_save "mjohnson"; + test_binary_load "mjohnson"; + + if not test_script_run { } +} + +test "RFC 3028 example" { + if not test_script_compile "../../examples/rfc3028.sieve" { + test_fail "could not compile"; + } + + test_binary_save "rfc3028"; + test_binary_load "rfc3028"; + + if not test_script_run { } +} + +test "Sieve examples" { + if not test_script_compile "../../examples/sieve_examples.sieve" { + test_fail "could not compile"; + } + + test_binary_save "sieve_examples"; + test_binary_load "sieve_examples"; + + if not test_script_run { } +} + +test "Vivil example" { + if not test_script_compile "../../examples/vivil.sieve" { + test_fail "could not compile"; + } + + test_binary_save "vivil"; + test_binary_load "vivil"; + + if not test_script_run { } +} + +test "Jerry example" { + if not test_script_compile "../../examples/jerry.sieve" { + test_fail "could not compile"; + } + + test_binary_save "jerry"; + test_binary_load "jerry"; + + if not test_script_run { } +} + +test "M. Klose example" { + if not test_script_compile "../../examples/mklose.sieve" { + test_fail "could not compile"; + } + + test_binary_save "mklose"; + test_binary_load "mklose"; + + if not test_script_run { } +} + +test "Sanjay example" { + if not test_script_compile "../../examples/sanjay.sieve" { + test_fail "could not compile"; + } + + test_binary_save "sanjay"; + test_binary_load "sanjay"; + + if not test_script_run { } +} + +test "Relational (RFC5231) example" { + if not test_script_compile "../../examples/relational.rfc5231.sieve" { + test_fail "could not compile"; + } + + test_binary_save "relational"; + test_binary_load "relational"; + + if not test_script_run { } +} + +test "Subaddress (RFC5233) example" { + if not test_script_compile "../../examples/subaddress.rfc5233.sieve" { + test_fail "could not compile"; + } + + test_binary_save "subaddress"; + test_binary_load "subaddress"; + + if not test_script_run { } +} diff --git a/pigeonhole/tests/execute/mailstore.svtest b/pigeonhole/tests/execute/mailstore.svtest new file mode 100644 index 0000000..d6cc220 --- /dev/null +++ b/pigeonhole/tests/execute/mailstore.svtest @@ -0,0 +1,84 @@ +require "vnd.dovecot.testsuite"; +require "fileinto"; +require "variables"; +require "mailbox"; + +set "message1" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: First message + +Frop +. +; + +set "message2" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Second message + +Frop +. +; + +set "message3" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Third message + +Frop +. +; + +test "Duplicates" { + test_set "message" "${message1}"; + + fileinto :create "Folder"; + fileinto :create "Folder"; + + if not test_result_execute { + test_fail "failed to execute first result"; + } + + test_result_reset; + + test_set "message" "${message2}"; + + fileinto :create "Folder"; + fileinto :create "Folder"; + + if not test_result_execute { + test_fail "failed to execute second result"; + } + + test_result_reset; + + test_set "message" "${message3}"; + + fileinto :create "Folder"; + fileinto :create "Folder"; + + if not test_result_execute { + test_fail "failed to execute third result"; + } + + test_message :folder "Folder" 0; + + if not header :is "subject" "First message" { + test_fail "first message incorrect"; + } + + test_message :folder "Folder" 1; + + if not header :is "subject" "Second message" { + test_fail "first message incorrect"; + } + + test_message :folder "Folder" 2; + + if not header :is "subject" "Third message" { + test_fail "first message incorrect"; + } +} + + diff --git a/pigeonhole/tests/execute/smtp.svtest b/pigeonhole/tests/execute/smtp.svtest new file mode 100644 index 0000000..2c7d2e6 --- /dev/null +++ b/pigeonhole/tests/execute/smtp.svtest @@ -0,0 +1,449 @@ +require "vnd.dovecot.testsuite"; +require "envelope"; + +test_set "message" text: +From: stephan@example.org +To: tss@example.net +Subject: Frop! + +Frop! +. +; +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "timo@example.net"; + +test "Redirect" { + redirect "cras@example.net"; + + if not test_result_execute { + test_fail "failed to execute redirect"; + } + + test_message :smtp 0; + + if not address :is "to" "tss@example.net" { + test_fail "to address incorrect (strange forward)"; + } + + if not address :is "from" "stephan@example.org" { + test_fail "from address incorrect (strange forward)"; + } + + if not envelope :is "to" "cras@example.net" { + test_fail "envelope recipient incorrect"; + } + + if not envelope :is "from" "sirius@example.org" { + test_fail "envelope sender incorrect"; + } + + if not header :contains "x-sieve-redirected-from" + "timo@example.net" { + test_fail "x-sieve-redirected-from header is incorrect"; + } +} + +test_result_reset; +test_set "message" text: +From: stephan@example.org +To: tss@example.net +Subject: Frop! + +Frop! +. +; +test_set "envelope.from" "<>"; +test_set "envelope.to" "timo@example.net"; + +test "Redirect from <>" { + redirect "cras@example.net"; + + if not test_result_execute { + test_fail "failed to execute redirect"; + } + + test_message :smtp 0; + + if envelope :is "from" "sirius@example.org" { + test_fail "envelope sender incorrect (not changed)"; + } + + if not envelope :is "from" "" { + test_fail "envelope sender incorrect"; + } + + if not header :contains "x-sieve-redirected-from" + "timo@example.net" { + test_fail "x-sieve-redirected-from header is incorrect"; + } +} + +test_result_reset; +test_set "message" text: +From: stephan@example.org +To: tss@example.net +Subject: Frop! + +Frop! +. +; +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "timo@example.net"; + +test_config_set "sieve_redirect_envelope_from" " recipient "; +test_config_reload; + +test "Redirect from [recipient]" { + redirect "cras@example.net"; + + if not test_result_execute { + test_fail "failed to execute redirect"; + } + + test_message :smtp 0; + + if envelope :is "from" "sirius@example.org" { + test_fail "envelope sender incorrect (not changed)"; + } + + if not envelope :is "from" "timo@example.net" { + test_fail "envelope sender incorrect"; + } + + if not header :contains "x-sieve-redirected-from" + "timo@example.net" { + test_fail "x-sieve-redirected-from header is incorrect"; + } +} + +test_result_reset; +test_set "message" text: +From: stephan@example.org +To: tss@example.net +Subject: Frop! + +Frop! +. +; +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "timo@example.net"; +test_set "envelope.orig_to" "tss@example.net"; + +test_config_set "sieve_redirect_envelope_from" "orig_recipient "; +test_config_reload; + +test "Redirect from [original recipient]" { + redirect "cras@example.net"; + + if not test_result_execute { + test_fail "failed to execute redirect"; + } + + test_message :smtp 0; + + if envelope :is "from" "sirius@example.org" { + test_fail "envelope sender incorrect (not changed)"; + } + + if not envelope :is "from" "tss@example.net" { + test_fail "envelope sender incorrect"; + } + + if not header :contains "x-sieve-redirected-from" + "timo@example.net" { + test_fail "x-sieve-redirected-from header is incorrect"; + } +} + +test_result_reset; +test_set "message" text: +From: stephan@example.org +To: tss@example.net +Subject: Frop! + +Frop! +. +; +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "timo@example.net"; +test_set "envelope.orig_to" "tss@example.net"; + +test_config_set "sieve_redirect_envelope_from" "<backscatter@example.net> "; +test_config_reload; + +test "Redirect from [<explicit>]" { + redirect "cras@example.net"; + + if not test_result_execute { + test_fail "failed to execute redirect"; + } + + test_message :smtp 0; + + if envelope :is "from" "sirius@example.org" { + test_fail "envelope sender incorrect (not changed)"; + } + + if not envelope :is "from" "backscatter@example.net" { + test_fail "envelope sender incorrect"; + } + + if not header :contains "x-sieve-redirected-from" + "timo@example.net" { + test_fail "x-sieve-redirected-from header is incorrect"; + } +} + +test_result_reset; +test_set "message" text: +From: stephan@example.org +To: tss@example.net +Subject: Frop! + +Frop! +. +; +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "timo@example.net"; + +test_config_set "sieve_redirect_envelope_from" "<>"; +test_config_reload; + +test "Redirect from [<>]" { + redirect "cras@example.net"; + + if not test_result_execute { + test_fail "failed to execute redirect"; + } + + test_message :smtp 0; + + if envelope :is "from" "sirius@example.org" { + test_fail "envelope sender incorrect (not changed)"; + } + + if not envelope :is "from" "" { + test_fail "envelope sender incorrect"; + } + + if not header :contains "x-sieve-redirected-from" + "timo@example.net" { + test_fail "x-sieve-redirected-from header is incorrect"; + } +} + +test_result_reset; +test_set "message" text: +From: stephan@example.org +To: tss@example.net +Subject: Frop! + +Frop! +. +; +test_set "envelope.from" "<>"; +test_set "envelope.to" "timo@example.net"; +test_set "envelope.orig_to" "tss@example.net"; + +test_config_set "sieve_redirect_envelope_from" "<backscatter@example.net>"; +test_config_reload; + +test "Redirect from <> with [<explicit>]" { + redirect "cras@example.net"; + + if not test_result_execute { + test_fail "failed to execute redirect"; + } + + test_message :smtp 0; + + if envelope :is "from" "backscatter@example.net" { + test_fail "envelope sender incorrect (erroneously changed)"; + } + + if not envelope :is "from" "" { + test_fail "envelope sender incorrect"; + } + + if not header :contains "x-sieve-redirected-from" + "timo@example.net" { + test_fail "x-sieve-redirected-from header is incorrect"; + } +} + +test_result_reset; +test_set "message" text: +From: stephan@example.org +To: tss@example.net +Subject: Frop! + +Frop! +. +; +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "timo@example.net"; +test_set "envelope.orig_to" "tss@example.net"; + +test_config_set "sieve_redirect_envelope_from" "user_email"; +test_config_reload; + +test "Redirect from [user email - fallback default]" { + redirect "cras@example.net"; + + if not test_result_execute { + test_fail "failed to execute redirect"; + } + + test_message :smtp 0; + + if not envelope :is "from" "timo@example.net" { + test_fail "envelope sender incorrect"; + } + + if not header :contains "x-sieve-redirected-from" + "timo@example.net" { + test_fail "x-sieve-redirected-from header is incorrect"; + } +} + +test_result_reset; +test_set "message" text: +From: stephan@example.org +To: tss@example.net +Subject: Frop! + +Frop! +. +; +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "timo@example.net"; +test_set "envelope.orig_to" "tss@example.net"; + +test_config_set "sieve_redirect_envelope_from" "user_email"; +test_config_set "sieve_user_email" "t.sirainen@example.net"; +test_config_reload; + +test "Redirect from [user email]" { + redirect "cras@example.net"; + + if not test_result_execute { + test_fail "failed to execute redirect"; + } + + test_message :smtp 0; + + if envelope :is "from" "sirius@example.org" { + test_fail "envelope sender incorrect (not changed)"; + } + + if not envelope :is "from" "t.sirainen@example.net" { + test_fail "envelope sender incorrect"; + } + + if not header :contains "x-sieve-redirected-from" + "t.sirainen@example.net" { + test_fail "x-sieve-redirected-from header is incorrect"; + } +} + +/* + * Redirect mail loop (sieve_user_email) + */ + +test_result_reset; +test_set "message" text: +X-Sieve-Redirected-From: t.sirainen@example.net +From: stephan@example.org +To: tss@example.net +Subject: Frop! + +Frop! +. +; +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "timo@example.net"; +test_set "envelope.orig_to" "tss@example.net"; + +test_config_set "sieve_redirect_envelope_from" "user_email"; +test_config_set "sieve_user_email" "t.sirainen@example.net"; +test_config_reload; + +test "Redirect mail loop (sieve_user_email)" { + redirect "cras@example.net"; + + if not test_result_execute { + test_fail "failed to execute redirect"; + } + + if test_message :smtp 0 { + test_fail "failed to recognize mail loop"; + } +} + +/* + * Redirect mail loop (final recipient) + */ + +test_result_reset; +test_set "message" text: +X-Sieve-Redirected-From: timo@example.net +From: stephan@example.org +To: tss@example.net +Subject: Frop! + +Frop! +. +; +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "timo@example.net"; +test_set "envelope.orig_to" "tss@example.net"; + +test_config_reload; + +test "Redirect mail loop (final recipient)" { + redirect "cras@example.net"; + + if not test_result_execute { + test_fail "failed to execute redirect"; + } + + if test_message :smtp 0 { + test_fail "failed to recognize mail loop"; + } +} + +/* + * Redirect mail loop (multiple headers) + */ + +test_result_reset; +test_set "message" text: +X-Sieve-Redirected-From: stephan@example.net +From: stephan@example.org +To: tss@example.net +Subject: Frop! +X-Sieve-Redirected-From: t.sirainen@example.net +X-Sieve-Redirected-From: t.sirainen@example.com + +Frop! +. +; +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "timo@example.net"; +test_set "envelope.orig_to" "tss@example.net"; + +test_config_set "sieve_redirect_envelope_from" "user_email"; +test_config_set "sieve_user_email" "t.sirainen@example.net"; +test_config_reload; + +test "Redirect mail loop (sieve_user_email)" { + redirect "cras@example.net"; + + if not test_result_execute { + test_fail "failed to execute redirect"; + } + + if test_message :smtp 0 { + test_fail "failed to recognize mail loop"; + } +} diff --git a/pigeonhole/tests/extensions/body/basic.svtest b/pigeonhole/tests/extensions/body/basic.svtest new file mode 100644 index 0000000..0b2bffc --- /dev/null +++ b/pigeonhole/tests/extensions/body/basic.svtest @@ -0,0 +1,97 @@ +require "vnd.dovecot.testsuite"; +require "relational"; +require "comparator-i;ascii-numeric"; + +require "body"; + +test_set "message" text: +From: stephan@example.org +To: tss@example.net +Subject: Test message. + +Test! + +. +; + +/* Empty line + * + * RFC 5173: + * 'The body test matches content in the body of an email message, that + * is, anything following the first empty line after the header. (The + * empty line itself, if present, is not considered to be part of the + * body.)' + */ +test "The empty line" { + + if not body :raw :is text: +Test! + +. + { + test_fail "invalid message body extracted (1)"; + } + + if body :raw :is text: + +Test! + +. + { + test_fail "invalid message body extracted (2)"; + } + + if body :raw :is "Test" + { + test_fail "body test matches nonsense (3)"; + } +} + +/* Default comparator and match type + * + * RFC 5173: + * 'The COMPARATOR and MATCH-TYPE keyword parameters are defined in + * [SIEVE]. As specified in Sections 2.7.1 and 2.7.3 of [SIEVE], the + * default COMPARATOR is "i;ascii-casemap" and the default MATCH-TYPE is + * ":is".' + */ + +test "Defaults" { + if anyof ( body :raw "Test", body :raw "*Test*" ) { + test_fail "default match type is not :is as is required"; + } + + if allof( not body :raw :contains "tesT", body :raw :contains "Test" ) { + test_fail "default comparator is not i;ascii-casemap as is required"; + } +} + +/* No body + * + * RFC 5173: + * 'If a message consists of a header only, not followed by an empty line, + * then that set is empty and all "body" tests return false, including + * those that test for an empty string. (This is similar to how the + * "header" test always fails when the named header fields aren't present.)' + */ + +test_set "message" text: +From: stephan@example.org +To: tss@example.net +Subject: No body is here! +. +; + +test "No body" { + if body :raw :contains "" { + test_fail "matched against non-existent body (:contains \"\")"; + } + + if body :raw :is "" { + test_fail "matched against non-existent body (:is \"\")"; + } + + if body :raw :matches "*" { + test_fail "matched against non-existent body (:matches \"*\")"; + } +} diff --git a/pigeonhole/tests/extensions/body/content.svtest b/pigeonhole/tests/extensions/body/content.svtest new file mode 100644 index 0000000..2eb3837 --- /dev/null +++ b/pigeonhole/tests/extensions/body/content.svtest @@ -0,0 +1,332 @@ +require "vnd.dovecot.testsuite"; +require "relational"; +require "comparator-i;ascii-numeric"; + +require "body"; + +/* + * + */ + +test_set "message" text: +From: justin@example.com +To: carl@example.nl +Subject: Frop +Content-Type: multipart/mixed; boundary=donkey + +This is a multi-part message in MIME format. + +--donkey +Content-Type: text/plain + +Plain Text + +--donkey +Content-Type: text/stupid + +Stupid Text + +--donkey +Content-Type: text/plain/stupid + +Plain Stupid Text + +--donkey-- +. +; + +/* + * RFC5173, Section 5.2: + * If an individual content type begins or ends with a '/' (slash) or + * contains multiple slashes, then it matches no content types. + * ... + */ + +test "Basic Match" { + if not body :content "text/plain" :matches "Plain Text*" { + test_fail "failed to match (1)"; + } + + if not body :content "text/plain" :contains "" { + test_fail "failed to match (2)"; + } + + if not body :content "text/stupid" :contains "" { + test_fail "failed to match (3)"; + } +} + +test "Begin Slash" { + if body :content "/plain" :contains "" { + test_fail "matched :content \"/plain\""; + } +} + +test "End Slash" { + if body :content "text/" :contains "" { + test_fail "matched :content \"text/\""; + } +} + +test "Double Slash" { + if body :content "text/plain/stupid" :contains "" { + test_fail "matched :content \"text/plain/stupid\""; + } +} + +/* + * + */ + +test_set "message" text: +From: justin@example.com +To: carl@example.nl +Subject: Frop +Content-Type: multipart/mixed; boundary=limit + +This is a multi-part message in MIME format. + +--limit +Content-Type: text/plain + +This is a text message. + +--limit +Content-Type: text/html + +<html><body>This is HTML</body></html> + +--limit +Content-Type: application/sieve + +keep; + +--limit-- +. +; + +/* RFC5173, Section 5.2: + * ... + * Otherwise, if it contains a slash, then it specifies a full + * <type>/<subtype> pair, and matches only that specific content type. + * If it is the empty string, all MIME content types are matched. + * Otherwise, it specifies a <type> only, and any subtype of that type + * matches it. + */ + +test "Full Content Type" { + if not body :content "text/plain" :matches "This is a text message.*" { + test_fail "failed to match text/plain content"; + } + + if body :content "text/plain" :matches "<html><body>This is HTML</body></html>*" { + test_fail "erroneously matched text/html content"; + } + + if not body :content "text/html" :matches "<html><body>This is HTML</body></html>*" { + test_fail "failed to match text/html content"; + } + + if body :content "text/html" :matches "This is a text message.*" { + test_fail "erroneously matched text/plain content"; + } + + if body :content "text/html" :matches "This is HTML*" { + test_fail "body :content test matched plain text"; + } +} + +test "Empty Content Type" { + if not body :content "" :matches "This is a text message.*" { + test_fail "failed to match text/plain content"; + } + + if not body :content "" :matches "<html><body>This is HTML</body></html>*" { + test_fail "failed to match text/html content"; + } + + if not body :content "" :matches "keep;*" { + test_fail "failed to match application/sieve content"; + } + + if body :content "" :matches "*blurdybloop*" { + test_fail "body :content \"\" test matches nonsense"; + } +} + +test "Main Content Type" { + if not body :content "text" :matches "This is a text message.*" { + test_fail "failed to match text/plain content"; + } + + if not body :content "text" :matches "<html><body>This is HTML</body></html>*" { + test_fail "failed to match text/html content"; + } + + if body :content "text" :matches "keep;*" { + test_fail "erroneously matched application/sieve content"; + } +} + +/* + * + */ + +test_set "message" text: +From: Whomever <whoever@example.com> +To: Someone <someone@example.com> +Date: Sat, 10 Oct 2009 00:30:04 +0200 +Subject: whatever +Content-Type: multipart/mixed; boundary=outer + +This is a multi-part message in MIME format. + +--outer +Content-Type: multipart/alternative; boundary=inner + +This is a nested multi-part message in MIME format. + +--inner +Content-Type: text/plain; charset="us-ascii" + +Hello + +--inner +Content-Type: text/html; charset="us-ascii" + +<html><body>Hello</body></html> + +--inner-- + +This is the end of the inner MIME multipart. + +--outer +Content-Type: message/rfc822 + +From: Someone Else +Subject: Hello, this is an elaborate request for you to finally say hello + already! + +Please say Hello + +--outer-- + +This is the end of the outer MIME multipart. +. +; + +/* RFC5173, Section 5.2: + * + * The search for MIME parts matching the :content specification is + * recursive and automatically descends into multipart and + * message/rfc822 MIME parts. All MIME parts with matching types are + * searched for the key strings. The test returns true if any + * combination of a searched MIME part and key-list argument match. + */ + +test "Nested Search" { + if not body :content "text/plain" :matches "Hello*" { + test_fail "failed to match text/plain content"; + } + + if body :content "text/plain" :matches "<html><body>Hello</body></html>*" { + test_fail "erroneously matched text/html content"; + } + + if not body :content "text/html" :matches "<html><body>Hello</body></html>*" { + test_fail "failed to match text/html content"; + } + + if body :content "text/html" :matches "Hello*" { + test_fail "erroneously matched text/plain content"; + } + + if not body :content "text" :contains "html" { + test_fail "failed match text content (1)"; + } + + if not body :content "text" :contains "hello" { + test_fail "failed match text content (2)"; + } + + if not body :content "text/plain" :contains "please say hello" { + test_fail "failed match nested message content as text/plain"; + } + + if not body :content "text" :contains "please say hello" { + test_fail "failed match nested message content as text/*"; + } + + if not body :content "text" :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "matched wrong number of \"text/*\" body parts"; + } +} + +/* RFC5173, Section 5.2: + * + * If the :content specification matches a multipart MIME part, only the + * prologue and epilogue sections of the part will be searched for the + * key strings, treating the entire prologue and the entire epilogue as + * separate strings; the contents of nested parts are only searched if + * their respective types match the :content specification. + * + */ + +test "Multipart Content" { + if not body :content "multipart" :contains + "This is a multi-part message in MIME format" { + test_fail "missed first multipart body part"; + } + + if not body :content "multipart" :contains + "This is a nested multi-part message in MIME format" { + test_fail "missed second multipart body part"; + } + + if not body :content "multipart" :contains + "This is the end of the inner MIME multipart" { + test_fail "missed third multipart body part"; + } + + if not body :content "multipart" :contains + "This is the end of the outer MIME multipart." { + test_fail "missed fourth multipart body part"; + } + + if body :content "multipart" :contains "--inner" { + test_fail "inner boundary is part of match"; + } + + if body :content "multipart" :contains "--outer" { + test_fail "outer boundary is part of match"; + } +} + +/* RFC5173, Section 5.2: + * + * If the :content specification matches a message/rfc822 MIME part, + * only the header of the nested message will be searched for the key + * strings, treating the header as a single string; the contents of the + * nested message body parts are only searched if their content type + * matches the :content specification. + */ + +test "Content-Type: message/rfc822" { + if not body :content "message/rfc822" :contains + "From: Someone Else" { + test_fail "missed raw message/rfc822 from header"; + } + + if not body :content "message/rfc822" :is text: +From: Someone Else +Subject: Hello, this is an elaborate request for you to finally say hello + already! +. + { + test_fail "header content does not match exactly"; + } +} + + + + diff --git a/pigeonhole/tests/extensions/body/errors.svtest b/pigeonhole/tests/extensions/body/errors.svtest new file mode 100644 index 0000000..8db5657 --- /dev/null +++ b/pigeonhole/tests/extensions/body/errors.svtest @@ -0,0 +1,19 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +/* + * Invalid syntax + */ + +test "Invalid Syntax" { + if test_script_compile "errors/syntax.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "12" { + test_fail "wrong number of errors reported"; + } +} + diff --git a/pigeonhole/tests/extensions/body/errors/syntax.sieve b/pigeonhole/tests/extensions/body/errors/syntax.sieve new file mode 100644 index 0000000..8adf0ef --- /dev/null +++ b/pigeonhole/tests/extensions/body/errors/syntax.sieve @@ -0,0 +1,38 @@ +require "body"; + +# 1: No key list +if body { } + +# 2: Number +if body 3 { } + +# OK: String +if body "frop" { } + +# 3: To many arguments +if body "frop" "friep" { } + +# 4: Unknown tag +if body :frop { } + +# 5: Unknown tag with valid key +if body :friep "frop" { } + +# 6: Content without argument +if body :content { } + +# 7: Content without key argument +if body :content "frop" { } + +# 8: Content with number argument +if body :content 3 "frop" { } + +# 9: Content with unknown tag +if body :content :frml "frop" { } + +# 10: Content with known tag +if body :content :contains "frop" { } + +# 11: Duplicate transform +if body :content "frop" :raw "frop" { } + diff --git a/pigeonhole/tests/extensions/body/match-values.svtest b/pigeonhole/tests/extensions/body/match-values.svtest new file mode 100644 index 0000000..55d5535 --- /dev/null +++ b/pigeonhole/tests/extensions/body/match-values.svtest @@ -0,0 +1,55 @@ +require "vnd.dovecot.testsuite"; + +require "body"; +require "variables"; + +test_set "message" text: +From: stephan@example.org +To: s.bosch@twente.example.net +Subject: Body test + +The big bad body test. +. +; + +# Test whether body test ignores match values +test "Match values disabled" { + if not body :raw :matches "The * bad * test*" { + test_fail "should have matched"; + } + + if anyof ( + string :is "${1}" "big", + string :is "${2}" "body", + not string :is "${0}" "", + not string :is "${1}" "", + not string :is "${2}" "") { + test_fail "match values not disabled"; + } +} + +test "Match values re-enabled" { + if not header :matches "from" "*@*" { + test_fail "should have matched"; + } + + if anyof ( + not string :is "${0}" "stephan@example.org", + not string :is "${1}" "stephan", + not string :is "${2}" "example.org" ) { + test_fail "match values not re-enabled properly."; + } +} + +test "Match values retained" { + if not body :raw :matches "The * bad * test*" { + test_fail "should have matched"; + } + + if anyof ( + not string :is "${0}" "stephan@example.org", + not string :is "${1}" "stephan", + not string :is "${2}" "example.org" ) { + test_fail "match values not retained after body test."; + } +} diff --git a/pigeonhole/tests/extensions/body/raw.svtest b/pigeonhole/tests/extensions/body/raw.svtest new file mode 100644 index 0000000..d3404b9 --- /dev/null +++ b/pigeonhole/tests/extensions/body/raw.svtest @@ -0,0 +1,85 @@ +require "vnd.dovecot.testsuite"; +require "body"; + +test_set "message" text: +From: Whomever <whoever@example.com> +To: Someone <someone@example.com> +Date: Sat, 10 Oct 2009 00:30:04 +0200 +Subject: whatever +Content-Type: multipart/mixed; boundary=outer + +This is a multi-part message in MIME format. + +--outer +Content-Type: multipart/alternative; boundary=inner + +This is a nested multi-part message in MIME format. + +--inner +Content-Type: text/plain; charset="us-ascii" + +Hello + +--inner +Content-Type: text/html; charset="us-ascii" + +<html><body>Hello</body></html> + +--inner-- + +This is the end of the inner MIME multipart. + +--outer +Content-Type: message/rfc822 + +From: Someone Else +Subject: hello request + +Please say Hello + +--outer-- + +This is the end of the outer MIME multipart. +. +; + +/* + * + * RFC 5173: + * The ":raw" transform matches against the entire undecoded body of a + * message as a single item. + * + * If the specified body-transform is ":raw", the [MIME] structure of + * the body is irrelevant. The implementation MUST NOT remove any + * transfer encoding from the message, MUST NOT refuse to filter + * messages with syntactic errors (unless the environment it is part of + * rejects them outright), and MUST treat multipart boundaries or the + * MIME headers of enclosed body parts as part of the content being + * matched against, instead of MIME structures to interpret. + */ + +test "Multipart Boundaries" { + if not body :raw :contains "--inner" { + test_fail "Raw body does not contain '--inner'"; + } + + if not body :raw :contains "--outer" { + test_fail "Raw body does not contain '--outer'"; + } +} + +test "Multipart Headers" { + if not body :raw :contains "boundary=inner" { + test_fail "Raw body does not contain 'boundary=inner'"; + } + + if not body :raw :contains "rfc822" { + test_fail "Raw body does not contain 'rfc822'"; + } +} + +test "Multipart Content" { + if not body :raw :contains "<html><body>Hello</body></html>" { + test_fail "Raw body does not contain '<html><body>Hello</body></html>'"; + } +} diff --git a/pigeonhole/tests/extensions/body/text.svtest b/pigeonhole/tests/extensions/body/text.svtest new file mode 100644 index 0000000..2dc6a03 --- /dev/null +++ b/pigeonhole/tests/extensions/body/text.svtest @@ -0,0 +1,225 @@ +require "vnd.dovecot.testsuite"; +require "relational"; +require "comparator-i;ascii-numeric"; + +require "body"; + +/* + * + */ + +test_set "message" text: +From: justin@example.com +To: carl@example.nl +Subject: Frop +Content-Type: multipart/mixed; boundary=donkey + +This is a multi-part message in MIME format. + +--donkey +Content-Type: text/plain + +Plain Text + +--donkey +Content-Type: text/stupid + +Stupid Text + +--donkey +Content-Type: text/plain/stupid + +Plain Stupid Text + +--donkey-- +. +; + +test "Basic Match" { + if not body :text :contains "Plain Text" { + test_fail "failed to match (1)"; + } + + if not body :text :contains "Stupid Text" { + test_fail "failed to match (2)"; + } +} + +test "Double Slash" { + if body :text :contains "Plain Stupid Text" { + test_fail "matched \"text/plain/stupid\""; + } +} + +/* + * + */ + +test_set "message" text: +From: justin@example.com +To: carl@example.nl +Subject: Frop +Content-Type: multipart/mixed; boundary=limit + +This is a multi-part message in MIME format. + +--limit +Content-Type: text/plain + +This is a text message. + +--limit +Content-Type: text/html + +<html><body>This is HTML</body></html> + +--limit +Content-Type: application/sieve + +keep; + +--limit-- +. +; + +test "Full Content Type" { + if not body :text :contains "This is a text message" { + test_fail "failed to match text/plain content"; + } + + if not body :text :contains "This is HTML" { + test_fail "failed to match text/html content"; + } + + if body :text :contains "<html>" { + test_fail "erroneously matched text/html markup"; + } + + if body :text :contains "keep;" { + test_fail "body :text test matched non-text content"; + } +} + +/* + * + */ + +test_set "message" text: +From: Whomever <whoever@example.com> +To: Someone <someone@example.com> +Date: Sat, 10 Oct 2009 00:30:04 +0200 +Subject: whatever +Content-Type: multipart/mixed; boundary=outer + +This is a multi-part message in MIME format. + +--outer +Content-Type: multipart/alternative; boundary=inner + +This is a nested multi-part message in MIME format. + +--inner +Content-Type: text/plain; charset="us-ascii" + +Hello + +--inner +Content-Type: text/html; charset="us-ascii" + +<html><body>HTML Hello</body></html> + +--inner +Content-Type: application/xhtml+xml; charset="us-ascii" + +<html><body>XHTML Hello</body></html> + +--inner-- + +This is the end of the inner MIME multipart. + +--outer +Content-Type: message/rfc822 + +From: Someone Else +Subject: Hello, this is an elaborate request for you to finally say hello + already! + +Please say Hello + +--outer-- + +This is the end of the outer MIME multipart. +. +; + +/* RFC5173, Section 5.2: + * + * The search for MIME parts matching the :content specification is + * recursive and automatically descends into multipart and + * message/rfc822 MIME parts. All MIME parts with matching types are + * searched for the key strings. The test returns true if any + * combination of a searched MIME part and key-list argument match. + */ + +test "Nested Search" { + if not body :text :contains "Hello" { + test_fail "failed to match text/plain content"; + } + if not body :text :contains "HTML Hello" { + test_fail "failed to match text/html content"; + } + if not body :text :contains "XHTML Hello" { + test_fail "failed to match application/xhtml+xml content"; + } + if body :text :contains ["<html>", "body"] { + test_fail "erroneously matched text/html markup"; + } + if not body :text :contains "Please say Hello" { + test_fail "failed to match message/rfc822 body"; + } + if body :text :contains "MIME" { + test_fail "erroneously matched multipart prologue/epilogue text"; + } +} + +/* + * Broken/Empty parts + */ + +test_set "message" text: +From: Whomever <whoever@example.com> +To: Someone <someone@example.com> +Date: Sat, 10 Oct 2009 00:30:04 +0200 +Subject: whatever +Content-Type: multipart/mixed; boundary=outer + +This is a multi-part message in MIME format. + +--outer +Content-Type: text/html + +--outer +Content-Type: text/html; charset=utf-8 +Content-Transfer-Encoding: multipart/related +Content-Disposition: inline + +<html><body>Please say Hello</body></html> + +--outer-- + +This is the end of the outer MIME multipart. +. +; + +test "Nested Search" { + if body :text :contains "Hello" { + test_fail "Cannot match empty/broken part"; + } + if body :text :contains ["<html>", "body"] { + test_fail "erroneously matched text/html markup"; + } + if body :text :contains "MIME" { + test_fail "erroneously matched multipart prologue/epilogue text"; + } +} + diff --git a/pigeonhole/tests/extensions/date/basic.svtest b/pigeonhole/tests/extensions/date/basic.svtest new file mode 100644 index 0000000..5d0b33f --- /dev/null +++ b/pigeonhole/tests/extensions/date/basic.svtest @@ -0,0 +1,73 @@ +require "vnd.dovecot.testsuite"; +require "date"; +require "variables"; +require "relational"; + +test_set "message" text: +From: stephan@example.org +To: sirius@friep.example.com +Subject: Frop! +Date: Mon, 20 Jul 2009 21:44:43 +0300 +Delivery-Date: Mon, 22 Jul 2009 23:30:14 +0300 +Invalid-Date: Moo, 34 Juul 3060 25:30:42 +6600 +Wanna date? +. +; + +test "Defaults" { + if not date :originalzone "date" "std11" "mon, 20 jul 2009 21:44:43 +0300" { + test_fail "default comparator is not i;ascii-casemap"; + } + + if anyof ( date "date" "std11" "Mon", date "date" "std11" "*") { + test_fail "default match type appears to be :contains or :matches"; + } +} + +test "Count" { + if not date :count "eq" "date" "date" "1" { + test_fail "count of existing date header field is not 1"; + } + + if not date :count "eq" "resent-date" "date" "0" { + test_fail "count of non-existent date header field is not 0"; + } +} + +test "Invalid" { + if date :matches "invalid-date" "std11" "*" { + test_fail "matched invalid date: ${0}"; + } +} + +test "Comparison" { + if not date :originalzone :is "delivery-date" "date" "2009-07-22" { + if date :originalzone :matches "delivery-date" "date" "*" { set "date" "${1}"; } + test_fail "date is invalid: ${date}"; + } + if not date :originalzone :value "ge" "delivery-date" "date" "2009-07-22" { + test_fail "date comparison ge failed equal"; + } + + if not date :originalzone :value "ge" "delivery-date" "date" "2009-07-21" { + test_fail "date comparison ge failed greater"; + } + + if anyof (not date :originalzone :value "ge" "delivery-date" "date" "2009-06-22", + not date :originalzone :value "ge" "date" "date" "2006-07-22" ) { + test_fail "date comparison ge failed much greater"; + } + + if not date :originalzone :value "le" "delivery-date" "date" "2009-07-22" { + test_fail "date comparison le failed equal"; + } + + if not date :originalzone :value "le" "delivery-date" "date" "2009-07-23" { + test_fail "date comparison le failed less"; + } + + if anyof (not date :originalzone :value "le" "delivery-date" "date" "2009-09-22", + not date :originalzone :value "le" "date" "date" "2012-07-22" ) { + test_fail "date comparison ge failed much less"; + } +} diff --git a/pigeonhole/tests/extensions/date/date-parts.svtest b/pigeonhole/tests/extensions/date/date-parts.svtest new file mode 100644 index 0000000..edc565c --- /dev/null +++ b/pigeonhole/tests/extensions/date/date-parts.svtest @@ -0,0 +1,120 @@ +require "vnd.dovecot.testsuite"; +require "date"; +require "variables"; + +test_set "message" text: +From: stephan@example.org +To: sirius@friep.example.com +Subject: Frop! +Date: Mon, 20 Jul 2009 21:44:43 +0300 +Delivery-Date: Mon, 22 Jul 2009 23:30:14 +0300 + +Wanna date? +. +; + +/* "year" => the year, "0000" .. "9999". */ +test "Year" { + if not date :originalzone "date" "year" "2009" { + test_fail "failed to extract year part"; + } +} + +/* "month" => the month, "01" .. "12". */ +test "Month" { + if not date :originalzone "date" "month" "07" { + test_fail "failed to extract month part"; + } +} + +/* "day" => the day, "01" .. "31". */ +test "Day" { + if not date :originalzone "date" "day" "20" { + test_fail "failed to extract day part"; + } +} + +/* "date" => the date in "yyyy-mm-dd" format. */ +test "Date" { + if not date :originalzone "date" "date" "2009-07-20" { + test_fail "failed to extract date part"; + } +} + +/* "julian" => the Modified Julian Day, that is, the date + expressed as an integer number of days since + 00:00 UTC on November 17, 1858 (using the Gregorian + calendar). This corresponds to the regular + Julian Day minus 2400000.5. */ +test "Julian" { + if not date :originalzone "date" "julian" "55032" { + if date :matches :originalzone "date" "julian" "*" { } + test_fail "failed to extract julian part: ${0}"; + } + if not date :originalzone "delivery-date" "julian" "55034" { + if date :matches :originalzone "delivery-date" "julian" "*" { } + test_fail "failed to extract julian part: ${0}"; + } +} + +/* "hour" => the hour, "00" .. "23". */ +test "Hour" { + if not date :originalzone "date" "hour" "21" { + test_fail "failed to extract hour part"; + } +} + +/* "minute" => the minute, "00" .. "59". */ +test "Minute" { + if not date :originalzone "date" "minute" "44" { + test_fail "failed to extract minute part"; + } +} + +/* "second" => the second, "00" .. "60". */ +test "Second" { + if not date :originalzone "date" "second" "43" { + test_fail "failed to extract second part"; + } +} + +/* "time" => the time in "hh:mm:ss" format. */ +test "Time" { + if not date :originalzone "date" "time" "21:44:43" { + test_fail "failed to extract time part"; + } +} + +/* "iso8601" => the date and time in restricted ISO 8601 format. */ +test "ISO8601" { + if not date :originalzone "date" "iso8601" "2009-07-20T21:44:43+03:00" { + test_fail "failed to extract iso8601 part"; + } +} + +/* "std11" => the date and time in a format appropriate + for use in a Date: header field [RFC2822]. */ +test "STD11" { + if not date :originalzone "date" "std11" "Mon, 20 Jul 2009 21:44:43 +0300" { + test_fail "failed to extract std11 part"; + } +} + +/* "zone" => the time zone in use. */ +test "zone" { + if not date :originalzone "date" "zone" "+0300" { + test_fail "failed to extract zone part"; + } + + if not date :zone "+0200" "date" "zone" "+0200" { + test_fail "failed to extract zone part"; + } +} + +/* "weekday" => the day of the week expressed as an integer between + "0" and "6". "0" is Sunday, "1" is Monday, etc. */ +test "Weekday" { + if not date :originalzone "date" "weekday" "1" { + test_fail "failed to extract weekday part"; + } +} diff --git a/pigeonhole/tests/extensions/date/zones.svtest b/pigeonhole/tests/extensions/date/zones.svtest new file mode 100644 index 0000000..77adb77 --- /dev/null +++ b/pigeonhole/tests/extensions/date/zones.svtest @@ -0,0 +1,76 @@ +require "vnd.dovecot.testsuite"; +require "date"; +require "variables"; + +/* Extract local timezone first */ +test "Local-Zone" { + if not currentdate :matches "zone" "*" { + test_fail "matches '*' failed for zone part."; + } + set "local_zone" "${0}"; +} + +/* FIXME: using variables somehow fails here */ +if string "${local_zone}" "+0200" { +test_set "message" text: +From: stephan@example.org +To: sirius@friep.example.com +Subject: Frop! +Date: Mon, 20 Jul 2009 21:44:43 +0300 +Delivery-Date: Mon, 23 Jul 2009 05:30:14 +0800 + +Wanna date? +. +; +} else { +test_set "message" text: +From: stephan@example.org +To: sirius@friep.example.com +Subject: Frop! +Date: Mon, 20 Jul 2009 21:44:43 +0300 +Delivery-Date: Mon, 22 Jul 2009 23:30:14 +0200 + +Wanna date? +. +; +} + +test "Specified Zone" { + if not date :zone "+0200" "date" "zone" "+0200" { + if date :matches :zone "+0200" "date" "zone" "*" {} + test_fail "zone is incorrect: ${0}"; + } + + if not date :zone "+0200" "date" "time" "20:44:43" { + test_fail "zone is not applied"; + } +} + +test "Original Zone" { + if not date :originalzone "date" "zone" "+0300" { + if date :matches :originalzone "date" "zone" "*" {} + test_fail "zone is incorrect: ${0}"; + } + + if not date :originalzone "date" "time" "21:44:43" { + test_fail "time should be left untouched"; + } +} + +test "Local Zone Shift" { + if anyof ( + allof ( + string "${local_zone}" "+0200", + date "delivery-date" "iso8601" "2009-07-23T05:30:14+08:00"), + allof ( + not string "${local_zone}" "+0200", + date "delivery-date" "iso8601" "2009-07-22T23:30:14+02:00")) { + + if date :matches "delivery-date" "iso8601" "*" + { set "a" "${0}"; } + if date :originalzone :matches "delivery-date" "iso8601" "*" + { set "b" "${0}"; } + + test_fail "time not shifted to local zone: ${b} => ${a}"; + } +} diff --git a/pigeonhole/tests/extensions/duplicate/errors.svtest b/pigeonhole/tests/extensions/duplicate/errors.svtest new file mode 100644 index 0000000..108a0f0 --- /dev/null +++ b/pigeonhole/tests/extensions/duplicate/errors.svtest @@ -0,0 +1,54 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +/* + * Invalid syntax + */ + +test "Invalid Syntax" { + if test_script_compile "errors/syntax.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "17" { + test_fail "wrong number of errors reported"; + } +} + +test "Invalid Syntax (vnd)" { + if test_script_compile "errors/syntax-vnd.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "5" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Extension conflict + */ + +test "Extension conflict" { + if test_script_compile "errors/conflict.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "2" { + test_fail "wrong number of errors reported"; + } +} + +test "Extension conflict (vnd first)" { + if test_script_compile "errors/conflict-vnd.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "2" { + test_fail "wrong number of errors reported"; + } +} + + diff --git a/pigeonhole/tests/extensions/duplicate/errors/conflict-vnd.sieve b/pigeonhole/tests/extensions/duplicate/errors/conflict-vnd.sieve new file mode 100644 index 0000000..1c133df --- /dev/null +++ b/pigeonhole/tests/extensions/duplicate/errors/conflict-vnd.sieve @@ -0,0 +1,4 @@ +require "vnd.dovecot.duplicate"; +require "duplicate"; + +if duplicate { keep; } diff --git a/pigeonhole/tests/extensions/duplicate/errors/conflict.sieve b/pigeonhole/tests/extensions/duplicate/errors/conflict.sieve new file mode 100644 index 0000000..aa9b038 --- /dev/null +++ b/pigeonhole/tests/extensions/duplicate/errors/conflict.sieve @@ -0,0 +1,4 @@ +require "duplicate"; +require "vnd.dovecot.duplicate"; + +if duplicate { keep; } diff --git a/pigeonhole/tests/extensions/duplicate/errors/syntax-vnd.sieve b/pigeonhole/tests/extensions/duplicate/errors/syntax-vnd.sieve new file mode 100644 index 0000000..f62aa2c --- /dev/null +++ b/pigeonhole/tests/extensions/duplicate/errors/syntax-vnd.sieve @@ -0,0 +1,19 @@ +require "vnd.dovecot.duplicate"; + +# Used as a command +duplicate; + +# Used with no argument (not an error) +if duplicate {} + +# Used with string argument +if duplicate "frop" { } + +# Used with numer argument +if duplicate 23423 { } + +# Used with numer argument +if duplicate ["frop"] { } + + + diff --git a/pigeonhole/tests/extensions/duplicate/errors/syntax.sieve b/pigeonhole/tests/extensions/duplicate/errors/syntax.sieve new file mode 100644 index 0000000..a561cfb --- /dev/null +++ b/pigeonhole/tests/extensions/duplicate/errors/syntax.sieve @@ -0,0 +1,54 @@ +require "duplicate"; + +# Used as a command +duplicate; + +# Used with no argument (not an error) +if duplicate {} + +# Used with string argument +if duplicate "frop" { } + +# Used with numner argument +if duplicate 23423 { } + +# Used with numer argument +if duplicate ["frop"] { } + +# Used with unknown tag +if duplicate :test "frop" { } + +# Bad :header parameter +if duplicate :header 23 {} + +# Bad :uniqueid parameter +if duplicate :uniqueid 23 {} + +# Bad :handle parameter +if duplicate :handle ["a", "b", "c"] {} + +# Bad seconds parameter +if duplicate :seconds "a" {} + +# Missing :header parameter +if duplicate :header {} + +# Missing :uniqueid parameter +if duplicate :uniqueid {} + +# Missing :handle parameter +if duplicate :handle {} + +# Missing seconds parameter +if duplicate :seconds {} + +# :last with a parameter +if duplicate :last "frop" {} + +# :last as :seconds parameter +if duplicate :seconds :last {} + +# Conflicting tags +if duplicate :header "X-Frop" :uniqueid "FROP!" { } + + diff --git a/pigeonhole/tests/extensions/duplicate/execute-vnd.svtest b/pigeonhole/tests/extensions/duplicate/execute-vnd.svtest new file mode 100644 index 0000000..386550f --- /dev/null +++ b/pigeonhole/tests/extensions/duplicate/execute-vnd.svtest @@ -0,0 +1,20 @@ +require "vnd.dovecot.testsuite"; +require "vnd.dovecot.duplicate"; + +test "Run" { + if duplicate { + test_fail "test erroneously reported a duplicate"; + } + + if duplicate :handle "handle" { + test_fail "test with name erroneously reported a duplicate"; + } + + if duplicate { + test_fail "test erroneously reported a duplicate"; + } + + if duplicate :handle "handle" { + test_fail "test with name erroneously reported a duplicate"; + } +} diff --git a/pigeonhole/tests/extensions/duplicate/execute.svtest b/pigeonhole/tests/extensions/duplicate/execute.svtest new file mode 100644 index 0000000..9e060ff --- /dev/null +++ b/pigeonhole/tests/extensions/duplicate/execute.svtest @@ -0,0 +1,41 @@ +require "vnd.dovecot.testsuite"; +require "duplicate"; + +# Simple execution tests; no duplicate verification can be tested yet. +test "Run" { + if duplicate { + test_fail "test erroneously reported a duplicate"; + } + + if duplicate :handle "handle" { + test_fail "test with :handle erroneously reported a duplicate"; + } + + if duplicate { + test_fail "test erroneously reported a duplicate"; + } + + if duplicate :handle "handle" { + test_fail "test with :handle erroneously reported a duplicate"; + } + + if duplicate :header "X-frop" { + test_fail "test with :header erroneously reported a duplicate"; + } + + if duplicate :uniqueid "FROP!" { + test_fail "test with :uniqueid erroneously reported a duplicate"; + } + + if duplicate :seconds 90 { + test_fail "test with :seconds erroneously reported a duplicate"; + } + + if duplicate :seconds 90 :last { + test_fail "test with :seconds :last erroneously reported a duplicate"; + } + + if duplicate :last { + test_fail "test with :seconds :last erroneously reported a duplicate"; + } +} diff --git a/pigeonhole/tests/extensions/editheader/addheader.svtest b/pigeonhole/tests/extensions/editheader/addheader.svtest new file mode 100644 index 0000000..426b43d --- /dev/null +++ b/pigeonhole/tests/extensions/editheader/addheader.svtest @@ -0,0 +1,833 @@ +require "vnd.dovecot.testsuite"; +require "encoded-character"; +require "variables"; +require "fileinto"; +require "mailbox"; +require "body"; + +require "editheader"; + +set "message" text: +From: stephan@example.com +To: timo@example.com +Subject: Frop! + +Frop! + +. +; + +test_set "message" "${message}"; +test "Addheader - first" { + if size :over 76 { + test_fail "original message is longer than 76 bytes?!"; + } + + addheader "X-Some-Header" "Header content"; + + if not size :over 76 { + test_fail "mail is not larger"; + } + + if size :over 107 { + test_fail "mail is too large"; + } + + if size :under 107 { + test_fail "mail is too small"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained"; + } + + if not exists "x-some-header" { + test_fail "header not added"; + } + + if not header :is "x-some-header" "Header content" { + test_fail "wrong content added"; + } + + redirect "frop@example.com"; + fileinto :create "folder1"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :folder "folder1" 0 { + test_fail "message not stored"; + } + + if not size :over 76 { + test_fail "stored mail is not larger"; + } + + if size :over 107 { + test_fail "stored mail is too large"; + } + + if size :under 100 { + test_fail "stored mail is too small"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in stored mail"; + } + + if not exists "x-some-header" { + test_fail "header not in stored mail"; + } + + if not header :is "x-some-header" "Header content" { + test_fail "wrong content in stored mail "; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in stored mail"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in redirected mail"; + } + + if not exists "x-some-header" { + test_fail "header not in redirected mail"; + } + + if not header :is "x-some-header" "Header content" { + test_fail "wrong content in redirected mail "; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + +test_result_reset; +test_set "message" "${message}"; +test "Addheader - first (two)" { + if size :over 76 { + test_fail "original message is longer than 76 bytes?!"; + } + + addheader "X-Some-Header" "Header content"; + addheader "X-Some-Other-Header" "More header content"; + + if not size :over 76 { + test_fail "mail is not larger"; + } + + if size :over 149 { + test_fail "mail is too large"; + } + + if size :under 149 { + test_fail "mail is too small"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained"; + } + + if not exists "x-some-header" { + test_fail "header #1 not added"; + } + + if not header :is "x-some-header" "Header content" { + test_fail "wrong content added #1"; + } + + if not exists "x-some-other-header" { + test_fail "header #2 not added"; + } + + if not header :is "x-some-other-header" "More header content" { + test_fail "wrong content added #2"; + } + + redirect "frop@example.com"; + fileinto :create "folder2"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :folder "folder2" 0 { + test_fail "message not stored"; + } + + if not size :over 76 { + test_fail "stored mail is not larger"; + } + + if size :over 149 { + test_fail "stored mail is too large"; + } + + if size :under 100 { + test_fail "stored mail is too small"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in stored mail"; + } + + if not exists "x-some-header" { + test_fail "header #1 not in stored mail"; + } + + if not header :is "x-some-header" "Header content" { + test_fail "wrong content #1 in stored mail "; + } + + if not exists "x-some-other-header" { + test_fail "header #2 not in stored mail"; + } + + if not header :is "x-some-other-header" "More header content" { + test_fail "wrong content #2 in stored mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in stored mail"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in redirected mail"; + } + + if not exists "x-some-header" { + test_fail "header not in redirected mail"; + } + + if not header :is "x-some-header" "Header content" { + test_fail "wrong content in redirected mail "; + } + + if not exists "x-some-other-header" { + test_fail "header #2 not in redirected mail"; + } + + if not header :is "x-some-other-header" "More header content" { + test_fail "wrong content #2 in redirected mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + +test_result_reset; +test_set "message" "${message}"; +test "Addheader - last" { + if size :over 76 { + test_fail "original message is longer than 76 bytes?!"; + } + + addheader :last "X-Some-Header" "Header content"; + + if not size :over 76 { + test_fail "mail is not larger"; + } + + if size :over 107 { + test_fail "mail is too large"; + } + + if size :under 107 { + test_fail "mail is too small"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained"; + } + + if not exists "x-some-header" { + test_fail "header not added"; + } + + if not header :is "x-some-header" "Header content" { + test_fail "wrong content added"; + } + + redirect "frop@example.com"; + fileinto :create "folder3"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :folder "folder3" 0 { + test_fail "message not stored"; + } + + if not size :over 76 { + test_fail "stored mail is not larger"; + } + + if size :over 107 { + test_fail "stored mail is too large"; + } + + if size :under 100 { + test_fail "stored mail is too small"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in stored mail"; + } + + if not exists "x-some-header" { + test_fail "header not in stored mail"; + } + + if not header :is "x-some-header" "Header content" { + test_fail "wrong content in stored mail "; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in stored mail"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in redirected mail"; + } + + if not exists "x-some-header" { + test_fail "header not in redirected mail"; + } + + if not header :is "x-some-header" "Header content" { + test_fail "wrong content in redirected mail "; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + +test_result_reset; +test_set "message" "${message}"; +test "Addheader - last (two)" { + if size :over 76 { + test_fail "original message is longer than 76 bytes?!"; + } + + addheader :last "X-Some-Header" "Header content"; + addheader "X-Some-Other-Header" "More header content"; + + if not size :over 76 { + test_fail "mail is not larger"; + } + + if size :over 149 { + test_fail "mail is too large"; + } + + if size :under 149 { + test_fail "mail is too small"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained"; + } + + if not exists "x-some-header" { + test_fail "header #1 not added"; + } + + if not header :is "x-some-header" "Header content" { + test_fail "wrong content added #1"; + } + + if not exists "x-some-other-header" { + test_fail "header #2 not added"; + } + + if not header :is "x-some-other-header" "More header content" { + test_fail "wrong content added #2"; + } + + redirect "frop@example.com"; + fileinto :create "folder4"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :folder "folder4" 0 { + test_fail "message not stored"; + } + + if not size :over 76 { + test_fail "stored mail is not larger"; + } + + if size :over 149 { + test_fail "stored mail is too large"; + } + + if size :under 100 { + test_fail "stored mail is too small"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in stored mail"; + } + + if not exists "x-some-header" { + test_fail "header #1 not in stored mail"; + } + + if not header :is "x-some-header" "Header content" { + test_fail "wrong content #1 in stored mail"; + } + + if not exists "x-some-other-header" { + test_fail "header #2 not in stored mail"; + } + + if not header :is "x-some-other-header" "More header content" { + test_fail "wrong content #2 in stored mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in stored mail"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in redirected mail"; + } + + if not exists "x-some-header" { + test_fail "header #1 not in redirected mail"; + } + + if not header :is "x-some-header" "Header content" { + test_fail "wrong content #1 in redirected mail "; + } + + if not exists "x-some-other-header" { + test_fail "header #2 not in redirected mail"; + } + + if not header :is "x-some-other-header" "More header content" { + test_fail "wrong content #2 in redirected mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + +test_result_reset; +test_set "message" "${message}"; +test "Addheader - framed" { + if size :over 76 { + test_fail "original message is longer than 76 bytes?!"; + } + + addheader "X-Some-Header-first" "Header content first"; + addheader :last "X-Some-Header-last" "Header content last"; + + if not size :over 76 { + test_fail "mail is not larger"; + } + + if size :over 160 { + test_fail "mail is too large"; + } + + if size :under 160 { + test_fail "mail is too small"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained"; + } + + if not exists "x-some-header-first" { + test_fail "first header not added"; + } + + if not exists "x-some-header-last" { + test_fail "last header not added"; + } + + if not header :is "x-some-header-first" "Header content first" { + test_fail "wrong first content added"; + } + + if not header :is "x-some-header-last" "Header content last" { + test_fail "wrong last content added"; + } + + redirect "frop@example.com"; + fileinto :create "folder5"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :folder "folder5" 0 { + test_fail "message not stored"; + } + + if not size :over 76 { + test_fail "stored mail is not larger"; + } + + if size :over 160 { + test_fail "stored mail is too large"; + } + + if size :under 152 { + test_fail "stored mail is too small"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in stored mail"; + } + + if not exists "x-some-header-first" { + test_fail "first header not in stored mail"; + } + + if not exists "x-some-header-last" { + test_fail "last header not in stored mail"; + } + + if not header :is "x-some-header-first" "Header content first" { + test_fail "wrong first header content in stored mail "; + } + + if not header :is "x-some-header-last" "Header content last" { + test_fail "wrong last header content in stored mail "; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in stored mail"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in redirected mail"; + } + + if not exists "x-some-header-first" { + test_fail "first header not in redirected mail"; + } + + if not exists "x-some-header-last" { + test_fail "last header not in redirected mail"; + } + + if not header :is "x-some-header-first" "Header content first" { + test_fail "wrong first header content in redirected mail "; + } + + if not header :is "x-some-header-last" "Header content last" { + test_fail "wrong last header content in redirected mail "; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + +/* + * Addheader - folded + */ + +test_result_reset; +test_set "message" "${message}"; +test "Addheader - folded" { + set "before" + "This is very long header content, folded to fit inside multiple header lines. This may cause problems, so that is why it is tested here."; + set "after" + "This is somewhat longer header content, folded to fit inside multiple header lines. This may cause problems, so that is why it is tested here."; + + addheader :last "X-Some-Header-first" "${before}"; + addheader :last "X-Some-Header-last" "${after}"; + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained"; + } + + if not exists "x-some-header-first" { + test_fail "first header not added"; + } + + if not exists "x-some-header-last" { + test_fail "last header not added"; + } + + if not header :is "x-some-header-first" "${before}" { + test_fail "wrong first content added"; + } + + if not header :is "x-some-header-last" "${after}" { + test_fail "wrong last content added"; + } + + redirect "frop@example.com"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in redirected mail"; + } + + if not exists "x-some-header-first" { + test_fail "first header not in redirected mail"; + } + + if not exists "x-some-header-last" { + test_fail "last header not in redirected mail"; + } + + if not header :is "x-some-header-first" "${before}" { + test_fail "wrong first header content in redirected mail "; + } + + if not header :is "x-some-header-last" "${after}" { + test_fail "wrong last header content in redirected mail "; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + +/* + * Addheader - newlines + */ + +test_result_reset; +test_set "message" "${message}"; +test "Addheader - newlines" { + set "before" text: +This is very long header content + containing newlines. This may + cause some problems, so that + is why it is tested here. +. +; + + set "after" text: +This is somewhat longer header content + containing newlines. This may + cause some problems, so that + is why it is tested here. +. +; + + set "before_out" + "This is very long header content containing newlines. This may cause some problems, so that is why it is tested here."; + + set "after_out" + "This is somewhat longer header content containing newlines. This may cause some problems, so that is why it is tested here."; + + addheader "X-Some-Header-first" "${before}"; + addheader :last "X-Some-Header-last" "${after}"; + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained"; + } + + if not exists "x-some-header-first" { + test_fail "first header not added"; + } + + if not exists "x-some-header-last" { + test_fail "last header not added"; + } + + if not header :is "x-some-header-first" "${before_out}" { + if header :matches "x-some-header-first" "*" {} + test_fail "wrong first content added: `${0}`"; + } + + if not header :is "x-some-header-last" "${after_out}" { + if header :matches "x-some-header-last" "*" {} + test_fail "wrong last content added: `${0}`"; + } + + redirect "frop@example.com"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in redirected mail"; + } + + if not exists "x-some-header-first" { + test_fail "first header not in redirected mail"; + } + + if not exists "x-some-header-last" { + test_fail "last header not in redirected mail"; + } + + if not header :is "x-some-header-first" "${before_out}" { + if header :matches "x-some-header-first" "*" {} + test_fail "wrong first header content in redirected mail: `${0}`"; + } + + if not header :is "x-some-header-last" "${after_out}" { + if header :matches "x-some-header-last" "*" {} + test_fail "wrong last header content in redirected mail: `${0}`"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + +test_result_reset; +test_set "message" "${message}"; +test "Addheader - implicit keep" { + if size :over 76 { + test_fail "original message is longer than 76 bytes?!"; + } + + addheader "X-Some-Header" "Header content"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :folder "INBOX" 0 { + test_fail "message not stored"; + } + + if not size :over 76 { + test_fail "stored mail is not larger"; + } + + if size :over 107 { + test_fail "stored mail is too large"; + } + + if size :under 100 { + test_fail "stored mail is too small"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in stored message"; + } + + if not exists "x-some-header" { + test_fail "header not added to stored message"; + } + + if not header :is "x-some-header" "Header content" { + test_fail "wrong content added to stored message"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in stored mail"; + } +} + +test_set "message" "${message}"; +test "Addheader - UTF 8" { + if size :over 76 { + test_fail "original message is longer than 76 bytes?!"; + } + + addheader "X-Some-Header" "Это тест!"; + fileinto :create "folder6"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :folder "folder6" 0 { + test_fail "message not stored"; + } + + if not exists "x-some-header" { + test_fail "header not added to stored message"; + } + + if not header :is "x-some-header" "Это тест!" { + if header :matches "x-some-header" "*" {} + test_fail "Bel character not retained: `${0}`"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in stored mail"; + } +} + +test_result_reset; + +test_set "message" "${message}"; +test "Addheader - devious characters" { + if size :over 76 { + test_fail "original message is longer than 76 bytes?!"; + } + + addheader "X-Some-Header" "Ring my ${hex:07}!"; + fileinto :create "folder7"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :folder "folder7" 0 { + test_fail "message not stored"; + } + + if not exists "x-some-header" { + test_fail "header not added to stored message"; + } + + if header :is "x-some-header" "Ring my !" { + if header :matches "x-some-header" "*" {} + test_fail "Bel character not retained: `${0}`"; + } + + if not header :is "x-some-header" "Ring my ${hex:07}!" { + if header :matches "x-some-header" "*" {} + test_fail "Incorrect header value: `${0}`"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in stored mail"; + } +} diff --git a/pigeonhole/tests/extensions/editheader/alternating.svtest b/pigeonhole/tests/extensions/editheader/alternating.svtest new file mode 100644 index 0000000..44d459c --- /dev/null +++ b/pigeonhole/tests/extensions/editheader/alternating.svtest @@ -0,0 +1,181 @@ +require "vnd.dovecot.testsuite"; +require "variables"; +require "fileinto"; +require "mailbox"; +require "body"; + +require "editheader"; + +set "message" text: +From: stephan@example.com +To: timo@example.com +Subject: Frop! + +Frop! + +. +; + + +test_set "message" "${message}"; +test "Alternating - add; delete" { + addheader "X-Some-Header" "Header content"; + + if not exists "x-some-header" { + test_fail "header not added"; + } + + if not header :is "x-some-header" "Header content" { + test_fail "wrong content added"; + } + + redirect "frop@example.com"; + + deleteheader "X-Some-Header"; + + if exists "x-some-header" { + test_fail "header not deleted"; + } + + fileinto :create "folder1"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + /* redirected message */ + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not exists "x-some-header" { + test_fail "added header not in redirected mail"; + } + + if not header :is "x-some-header" "Header content" { + test_fail "wrong content in redirected mail "; + } + + /* stored message message */ + + if not test_message :folder "folder1" 0 { + test_fail "message not stored"; + } + + if exists "x-some-header" { + test_fail "added header still present stored mail"; + } +} + +test_result_reset; + +test_set "message" "${message}"; +test "Alternating - delete; add" { + deleteheader "Subject"; + + if exists "subject" { + test_fail "header not deleted"; + } + + redirect "frop@example.com"; + + addheader "Subject" "Friep!"; + + if not exists "subject" { + test_fail "header not added"; + } + + if not header :is "subject" "Friep!" { + test_fail "wrong content added"; + } + + fileinto :create "folder2"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + /* redirected message */ + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if exists "subject" { + test_fail "deleted header still present redirected mail"; + } + + /* stored message message */ + + if not test_message :folder "folder2" 0 { + test_fail "message not stored"; + } + + if not exists "subject" { + test_fail "added header not in stored mail"; + } + + if not header :is "subject" "Friep!" { + test_fail "wrong content in redirected mail "; + } +} + +test_result_reset; + +test_set "message" "${message}"; +test "Alternating - add :last; delete any" { + addheader :last "X-Some-Header" "Header content"; + + if not exists "x-some-header" { + test_fail "header not added"; + } + + if not header :is "x-some-header" "Header content" { + test_fail "wrong content added"; + } + + redirect "frop@example.com"; + + deleteheader "X-Some-Other-Header"; + + if not exists "x-some-header" { + test_fail "header somehow deleted"; + } + + fileinto :create "folder3"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + /* redirected message */ + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not exists "x-some-header" { + test_fail "added header not in redirected mail"; + } + + if not header :is "x-some-header" "Header content" { + test_fail "wrong content in redirected mail "; + } + + /* stored message message */ + + if not test_message :folder "folder3" 0 { + test_fail "message not stored"; + } + + if not exists "x-some-header" { + test_fail "added header lost in stored mail"; + } + + if not header :is "x-some-header" "Header content" { + test_fail "wrong content in stored mail "; + } + +} + diff --git a/pigeonhole/tests/extensions/editheader/deleteheader.svtest b/pigeonhole/tests/extensions/editheader/deleteheader.svtest new file mode 100644 index 0000000..8b9d3ad --- /dev/null +++ b/pigeonhole/tests/extensions/editheader/deleteheader.svtest @@ -0,0 +1,1115 @@ +require "vnd.dovecot.testsuite"; +require "variables"; +require "fileinto"; +require "mailbox"; +require "body"; + +require "editheader"; + +set "message" text: +X-A: Onzinnige informatie +X-B: kun je maar beter +X-C: niet via e-mail versturen +From: stephan@example.com +X-D: en daarom is het nuttig +To: timo@example.com +Subject: Frop! +X-A: dit terstond te verwijderen, +X-B: omdat dit anders +X-C: alleen maar schijfruimte verspilt. + +Frop! + +. +; + +test_set "message" "${message}"; +test "Deleteheader - nonexistent" { + if size :over 288 { + test_fail "original message is longer than 288 bytes?!"; + } + + if size :under 288 { + test_fail "original message is shorter than 288 bytes?!"; + } + + deleteheader "X-Z"; + + if size :under 288 { + test_fail "message is shorter than original"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C header not retained"; + } + + redirect "frop@example.com"; + fileinto :create "folder1"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :folder "folder1" 0 { + test_fail "message not stored"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in stored mail"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained in stored mail"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C header not retained in stored mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in stored mail"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in redirected mail"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained in redirected mail"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C header not retained in redirected mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + +test_set "message" "${message}"; +test "Deleteheader - nonexistent (match)" { + if size :over 288 { + test_fail "original message is longer than 288 bytes?!"; + } + + if size :under 288 { + test_fail "original message is shorter than 288 bytes?!"; + } + + deleteheader :matches "X-Z" "*frop*"; + + if size :under 288 { + test_fail "message is shorter than original"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C header not retained"; + } + + redirect "frop@example.com"; + fileinto :create "folder1b"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :folder "folder1b" 0 { + test_fail "message not stored"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in stored mail"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained in stored mail"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C header not retained in stored mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in stored mail"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in redirected mail"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained in redirected mail"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C header not retained in redirected mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + +test_result_reset; +test_set "message" "${message}"; +test "Deleteheader - one" { + if size :over 288 { + test_fail "original message is longer than 288 bytes?!"; + } + + if size :under 288 { + test_fail "original message is shorter than 288 bytes?!"; + } + + deleteheader "X-D"; + + if not size :under 288 { + test_fail "edited message is not shorter"; + } + + if size :over 258 { + test_fail "edited message is too long"; + } + + if size :under 258 { + test_fail "edited message is too short"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C header not retained"; + } + + if exists "X-D" { + test_fail "X-D header not deleted"; + } + + redirect "frop@example.com"; + fileinto :create "folder2"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :folder "folder2" 0 { + test_fail "message not stored"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in stored mail"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained in stored mail"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C header not retained in stored mail"; + } + + if exists "X-D" { + test_fail "X-D header not deleted in stored mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in stored mail"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in redirected mail"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained in redirected mail"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C header not retained in redirected mail"; + } + + if exists "X-D" { + test_fail "X-D header not deleted in redirected mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + +test_result_reset; +test_set "message" "${message}"; +test "Deleteheader - two (first)" { + if size :over 288 { + test_fail "original message is longer than 288 bytes?!"; + } + + if size :under 288 { + test_fail "original message is shorter than 288 bytes?!"; + } + + deleteheader "X-A"; + + if not size :under 288 { + test_fail "edited message is not shorter"; + } + + if size :over 226 { + test_fail "edited message is too long"; + } + + if size :under 226 { + test_fail "edited message is too short"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C header not retained"; + } + + if exists "X-A" { + test_fail "X-A header not deleted"; + } + + redirect "frop@example.com"; + fileinto :create "folder3"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :folder "folder3" 0 { + test_fail "message not stored"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in stored mail"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained in stored mail"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C header not retained in stored mail"; + } + + if exists "X-A" { + test_fail "X-A header not deleted in stored mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in stored mail"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in redirected mail"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained in redirected mail"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C header not retained in redirected mail"; + } + + if exists "X-A" { + test_fail "X-A header not deleted in redirected mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + +test_result_reset; +test_set "message" "${message}"; +test "Deleteheader - two (last)" { + if size :over 288 { + test_fail "original message is longer than 288 bytes?!"; + } + + if size :under 288 { + test_fail "original message is shorter than 288 bytes?!"; + } + + deleteheader "X-C"; + + if not size :under 288 { + test_fail "edited message is not shorter"; + } + + if size :over 215 { + test_fail "edited message is too long"; + } + + if size :under 215 { + test_fail "edited message is too short"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained"; + } + + if not header :is "X-A" "dit terstond te verwijderen," { + test_fail "original X-A header not retained"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained"; + } + + if exists "X-C" { + test_fail "X-C header not deleted"; + } + + redirect "frop@example.com"; + fileinto :create "folder4"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :folder "folder4" 0 { + test_fail "message not stored"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in stored mail"; + } + + if not header :is "X-A" "dit terstond te verwijderen," { + test_fail "original X-A header not retained in stored mail"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained in stored mail"; + } + + if exists "X-C" { + test_fail "X-C header not deleted in stored mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in stored mail"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in redirected mail"; + } + + if not header :is "X-A" "dit terstond te verwijderen," { + test_fail "original X-A header not retained in redirected mail"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained in redirected mail"; + } + + if exists "X-C" { + test_fail "X-C header not deleted in redirected mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + +test_result_reset; +test_set "message" "${message}"; +test "Deleteheader - :index" { + if size :over 288 { + test_fail "original message is longer than 288 bytes?!"; + } + + if size :under 288 { + test_fail "original message is shorter than 288 bytes?!"; + } + + deleteheader :index 1 "X-A"; + deleteheader :index 2 "X-C"; + + if not size :under 288 { + test_fail "edited message is not shorter"; + } + + if size :over 220 { + test_fail "edited message is too long"; + } + + if size :under 220 { + test_fail "edited message is too short"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained"; + } + + if not header :is "X-A" "dit terstond te verwijderen," { + test_fail "original X-A (2) header not retained"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C (1) header not retained"; + } + + if header :is "X-A" "Onzinnige informatie" { + test_fail "original X-A (1) header not deleted"; + } + + if header :is "X-C" "alleen maar schijfruimte verspilt." { + test_fail "original X-C (2) header not deleted"; + } + + redirect "frop@example.com"; + fileinto :create "folder5"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :folder "folder5" 0 { + test_fail "message not stored"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in stored mail"; + } + + if not header :is "X-A" "dit terstond te verwijderen," { + test_fail "original X-A (2) header not retained in stored mail"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C (1) header not retained in stored mail"; + } + + if header :is "X-A" "Onzinnige informatie" { + test_fail "original X-A (1) header not deleted in stored mail"; + } + + if header :is "X-C" "alleen maar schijfruimte verspilt." { + test_fail "original X-C (2) header not deleted in stored mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in stored mail"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in redirected mail"; + } + + if not header :is "X-A" "dit terstond te verwijderen," { + test_fail "original X-A (2) header not retained redirected mail"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-B (1) header not retained redirected mail"; + } + + if header :is "X-A" "Onzinnige informatie" { + test_fail "original X-A (1) header not deleted redirected mail"; + } + + if header :is "X-C" "alleen maar schijfruimte verspilt." { + test_fail "original X-B (2) header not deleted redirected mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + +test_result_reset; +test_set "message" "${message}"; +test "Deleteheader - :index :last" { + if size :over 288 { + test_fail "original message is longer than 288 bytes?!"; + } + + if size :under 288 { + test_fail "original message is shorter than 288 bytes?!"; + } + + deleteheader :index 1 :last "X-A"; + deleteheader :last :index 2 "X-C"; + + if size :over 221 { + test_fail "edited message is too long"; + } + + if size :under 221 { + test_fail "edited message is too short"; + } + + if not size :under 288 { + test_fail "edited message is not shorter"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained"; + } + + if not header :is "X-A" "Onzinnige informatie" { + test_fail "original X-A (1) header not retained"; + } + + if not header :is "X-C" "alleen maar schijfruimte verspilt." { + test_fail "original X-C (2) header not retained"; + } + + if header :is "X-A" "dit terstond te verwijderen," { + test_fail "original X-A (2) header not deleted"; + } + + if header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C (1) header not deleted"; + } + + redirect "frop@example.com"; + fileinto :create "folder6"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :folder "folder6" 0 { + test_fail "message not stored"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in stored mail"; + } + + if not header :is "X-A" "Onzinnige informatie" { + test_fail "original X-A (1) header not retained in stored mail"; + } + + if not header :is "X-C" "alleen maar schijfruimte verspilt." { + test_fail "original X-C (2) header not retained in stored mail"; + } + + if header :is "X-A" "dit terstond te verwijderen," { + test_fail "original X-A (2) header not deleted in stored mail"; + } + + if header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C (1) header not deleted in stored mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in stored mail"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in redirected mail"; + } + + if header :is "X-A" "dit terstond te verwijderen," { + test_fail "original X-A (2) header not deleted redirected mail"; + } + + if header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-B (1) header not deleted redirected mail"; + } + + if not header :is "X-A" "Onzinnige informatie" { + test_fail "original X-A (1) header not retained redirected mail"; + } + + if not header :is "X-C" "alleen maar schijfruimte verspilt." { + test_fail "original X-B (2) header not retained redirected mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + +test_result_reset; +test_set "message" "${message}"; +test "Deleteheader - implicit keep" { + deleteheader "X-D"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :folder "INBOX" 0 { + test_fail "message not stored"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in stored mail"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained in stored mail"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C header not retained in stored mail"; + } + + if exists "X-D" { + test_fail "X-D header not deleted in stored mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in stored mail"; + } +} + +/* + * + */ + +test_result_reset; + +test_set "message" text: +X-A: Dit is een klein verhaaltje +X-B: om te testen of de correcte +X-C: informatie wordt herkend en +X-D: verwijderd. Zo valt goed te +X-A: zien dat het allemaal werkt +X-B: zoals het bedoeld is. Alles +X-C: wordt in een keer getest op +X-D: een wijze die efficient die +X-A: problemen naar voren brengt +X-B: die bij dit nieuwe deel van +X-C: de programmatuur naar voren +X-D: kunnen komen. Zo werkt het! + +Frop! +. +; + +test "Deleteheader - :matches" { + if size :over 417 { + test_fail "original message is longer than 417 bytes?!"; + } + + if size :under 417 { + test_fail "original message is shorter than 417 bytes?!"; + } + + deleteheader :matches "X-A" "*klein*"; + deleteheader :matches "X-B" "*bedoeld*"; + deleteheader :matches "X-C" "*programmatuur*"; + deleteheader :contains "X-D" ["verwijderd", "!"]; + + if not size :under 417 { + test_fail "edited message is not shorter"; + } + + if size :over 247 { + test_fail "edited message is too long"; + } + + if size :under 247 { + test_fail "edited message is too short"; + } + + if not header :is "X-A" "zien dat het allemaal werkt" { + test_fail "original X-A (2) header not retained"; + } + + if not header :is "X-A" "problemen naar voren brengt" { + test_fail "original X-A (3) header not retained"; + } + + if not header :is "X-B" "om te testen of de correcte" { + test_fail "original X-B (1) header not retained"; + } + + if not header :is "X-B" "die bij dit nieuwe deel van" { + test_fail "original X-B (3) header not retained"; + } + + if not header :is "X-C" "informatie wordt herkend en" { + test_fail "original X-C (1) header not retained"; + } + + if not header :is "X-C" "wordt in een keer getest op" { + test_fail "original X-C (2) header not retained"; + } + + if not header :is "X-D" "een wijze die efficient die" { + test_fail "original X-C (2) header not retained"; + } + + if header :is "X-A" "Dit is een klein verhaaltje" { + test_fail "original X-A (1) header not deleted"; + } + + if header :is "X-B" "zoals het bedoeld is. Alles" { + test_fail "original X-B (2) header not deleted"; + } + + if header :is "X-C" "de programmatuur naar voren" { + test_fail "original X-C (3) header not deleted"; + } + + if header :is "X-D" "verwijderd. Zo valt goed te" { + test_fail "original X-C (1) header not deleted"; + } + + if header :is "X-D" "kunnen komen. Zo werkt het!" { + test_fail "original X-C (3) header not deleted"; + } + + redirect "frop@example.com"; + fileinto :create "folder7"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :folder "folder7" 0 { + test_fail "message not stored"; + } + + if not header :is "X-A" "zien dat het allemaal werkt" { + test_fail "original X-A (2) header not retained in stored mail"; + } + + if not header :is "X-A" "problemen naar voren brengt" { + test_fail "original X-A (3) header not retained in stored mail"; + } + + if not header :is "X-B" "om te testen of de correcte" { + test_fail "original X-B (1) header not retained in stored mail"; + } + + if not header :is "X-B" "die bij dit nieuwe deel van" { + test_fail "original X-B (3) header not retained in stored mail"; + } + + if not header :is "X-C" "informatie wordt herkend en" { + test_fail "original X-C (1) header not retained in stored mail"; + } + + if not header :is "X-C" "wordt in een keer getest op" { + test_fail "original X-C (2) header not retained in stored mail"; + } + + if not header :is "X-D" "een wijze die efficient die" { + test_fail "original X-C (2) header not retained in stored mail"; + } + + if header :is "X-A" "Dit is een klein verhaaltje" { + test_fail "original X-A (1) header not deleted in stored mail"; + } + + if header :is "X-B" "zoals het bedoeld is. Alles" { + test_fail "original X-B (2) header not deleted in stored mail"; + } + + if header :is "X-C" "de programmatuur naar voren" { + test_fail "original X-C (3) header not deleted in stored mail"; + } + + if header :is "X-D" "verwijderd. Zo valt goed te" { + test_fail "original X-C (1) header not deleted in stored mail"; + } + + if header :is "X-D" "kunnen komen. Zo werkt het!" { + test_fail "original X-C (3) header not deleted in stored mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in stored mail"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not header :is "X-A" "zien dat het allemaal werkt" { + test_fail "original X-A (2) header not retained in redirected mail"; + } + + if not header :is "X-A" "problemen naar voren brengt" { + test_fail "original X-A (3) header not retained in redirected mail"; + } + + if not header :is "X-B" "om te testen of de correcte" { + test_fail "original X-B (1) header not retained in redirected mail"; + } + + if not header :is "X-B" "die bij dit nieuwe deel van" { + test_fail "original X-B (3) header not retained in redirected mail"; + } + + if not header :is "X-C" "informatie wordt herkend en" { + test_fail "original X-C (1) header not retained in redirected mail"; + } + + if not header :is "X-C" "wordt in een keer getest op" { + test_fail "original X-C (2) header not retained in redirected mail"; + } + + if not header :is "X-D" "een wijze die efficient die" { + test_fail "original X-C (2) header not retained in redirected mail"; + } + + if header :is "X-A" "Dit is een klein verhaaltje" { + test_fail "original X-A (1) header not deleted in redirected mail"; + } + + if header :is "X-B" "zoals het bedoeld is. Alles" { + test_fail "original X-B (2) header not deleted in redirected mail"; + } + + if header :is "X-C" "de programmatuur naar voren" { + test_fail "original X-C (3) header not deleted in redirected mail"; + } + + if header :is "X-D" "verwijderd. Zo valt goed te" { + test_fail "original X-C (1) header not deleted in redirected mail"; + } + + if header :is "X-D" "kunnen komen. Zo werkt het!" { + test_fail "original X-C (3) header not deleted in redirected mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + + +/* + * + */ + +set "message2" text: +X-A: Long folded header to test removal of folded + headers from a message. This is the top header. +X-B: First intermittent unfolded header +X-A: Long folded header to test removal of folded + headers from a message. This is the middle header. +X-B: Second intermittent unfolded header +X-A: Long folded header to test removal of folded + headers from a message. This is the bottom header, + which concludes the header of this message. + +Frop! +. +; + +test_result_reset; +test_set "message" "${message2}"; +test "Deleteheader - folded" { + deleteheader "X-A"; + + if exists "X-A" { + test_fail "original X-A (1) header not deleted"; + } + + if not header :is "X-B" "First intermittent unfolded header" { + test_fail "original X-B (2) header not retained"; + } + + if not header :is "X-B" "Second intermittent unfolded header" { + test_fail "original X-B (2) header not retained"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } + + redirect "frop@example.com"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if exists "X-A" { + test_fail "original X-A (1) header not deleted in redirected mail"; + } + + if not header :is "X-B" "First intermittent unfolded header" { + test_fail "original X-B (2) header not retained in redirected mail"; + } + + if not header :is "X-B" "Second intermittent unfolded header" { + test_fail "original X-B (2) header not retained in redirected mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + +test_result_reset; +test_set "message" "${message2}"; +test "Deleteheader - folded (match)" { + deleteheader :matches "X-A" "*header*"; + + if exists "X-A" { + test_fail "original X-A (1) header not deleted"; + } + + if not header :is "X-B" "First intermittent unfolded header" { + test_fail "original X-B (2) header not retained"; + } + + if not header :is "X-B" "Second intermittent unfolded header" { + test_fail "original X-B (2) header not retained"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } + + redirect "frop@example.com"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if exists "X-A" { + test_fail "original X-A (1) header not deleted in redirected mail"; + } + + if not header :is "X-B" "First intermittent unfolded header" { + test_fail "original X-B (2) header not retained in redirected mail"; + } + + if not header :is "X-B" "Second intermittent unfolded header" { + test_fail "original X-B (2) header not retained in redirected mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + + +/* + * TEST: Ignoring whitespace + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.com +Subject: Help +X-A: Text +X-B: Text + +Text +. +; + +test "Ignoring whitespace" { + deleteheader :is "subject" "Help"; + deleteheader :is "x-a" "Text"; + deleteheader :is "x-b" "Text"; + + if exists "subject" { + test_fail "subject header not deleted"; + } + + if exists "x-a" { + test_fail "x-a header not deleted"; + } + + if exists "x-b" { + test_fail "x-b header not deleted"; + } +} + +/* + * TEST: Interaction with body test + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.com +Subject: Hoppa + +Text +. +; + +test "Interaction with body test" { + addheader "X-Frop" "frop"; + + if body "!TEST!" {} + + deleteheader "subject"; + + if exists "subject" { + test_fail "subject header not deleted"; + } +} + diff --git a/pigeonhole/tests/extensions/editheader/errors.svtest b/pigeonhole/tests/extensions/editheader/errors.svtest new file mode 100644 index 0000000..1d1f24d --- /dev/null +++ b/pigeonhole/tests/extensions/editheader/errors.svtest @@ -0,0 +1,164 @@ +require "vnd.dovecot.testsuite"; +require "comparator-i;ascii-numeric"; +require "relational"; +require "variables"; + +require "editheader"; + +test "Invalid field-name" { + if test_script_compile "errors/field-name.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "5" { + test_fail "wrong number of errors reported"; + } + + if not test_error :index 1 :matches "*field name*X-field:*invalid*" { + test_fail "wrong error reported (1)"; + } + + if not test_error :index 2 :matches "*field name*X field*invalid*" { + test_fail "wrong error reported (2)"; + } + + if not test_error :index 3 :matches "*field name*X-field:*invalid*" { + test_fail "wrong error reported (3)"; + } + + if not test_error :index 4 :matches "*field name*X field*invalid*" { + test_fail "wrong error reported (4)"; + } +} + +test "Invalid field-name at runtime " { + if not test_script_compile "errors/field-name-runtime.sieve" { + test_fail "compile failed"; + } + + if test_script_run { + test_fail "run should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "1" { + test_fail "wrong number of errors reported"; + } + + if not test_error :matches "*field name*X-field:*invalid*" { + test_fail "wrong error reported"; + } +} + +test "Invalid field value" { + if test_script_compile "errors/field-value.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "2" { + test_fail "wrong number of errors reported"; + } + + if not test_error :index 1 :matches "*value*Woah*invalid*" { + test_fail "wrong error reported (1): ${0}"; + } +} + +test "Command syntax (FIXME: count only)" { + if test_script_compile "errors/command-syntax.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "10" { + test_fail "wrong number of errors reported"; + } +} + +/* + * TEST - Size limit + */ + +test "Size limit" { + if not test_script_compile "errors/size-limit.sieve" { + test_fail "compile should have succeeded"; + } + + test_config_set "sieve_editheader_max_header_size" "1024"; + test_config_reload :extension "editheader"; + + if test_script_compile "errors/size-limit.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "2" { + test_fail "wrong number of errors reported"; + } +} + + +/* + * TEST - Size limit at runtime + */ + +test_config_set "sieve_editheader_max_header_size" ""; +test_config_reload :extension "editheader"; + +test "Size limit at runtime" { + if not test_script_compile "errors/size-limit-runtime.sieve" { + test_fail "compile should have succeeded"; + } + + if not test_script_run { + test_fail "run failed"; + } + + test_config_set "sieve_editheader_max_header_size" "1024"; + test_config_reload :extension "editheader"; + + if not test_script_compile "errors/size-limit-runtime.sieve" { + test_fail "compile should have succeeded"; + } + + if test_script_run { + test_fail "run should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "1" { + test_fail "wrong number of errors reported"; + } +} + +/* + * TEST - Implicit keep at runtime error + */ + +test_set "message" text: +From: stephan@example.com +To: tss@example.com +Subject: Frop + +Frop! +. +; + +test "Implicit keep at runtime error" { + if not test_script_compile "errors/runtime-error.sieve" { + test_fail "compile failed"; + } + + if not test_script_run { + test_fail "run failed"; + } + + if test_result_execute { + test_fail "result execution should have failed"; + } + + if not test_message :folder "INBOX" 0 { + test_fail "message not stored (no implicit keep)"; + } + + if exists "X-Frop" { + test_fail "implicit keep message has editheader changes"; + } +} + diff --git a/pigeonhole/tests/extensions/editheader/errors/command-syntax.sieve b/pigeonhole/tests/extensions/editheader/errors/command-syntax.sieve new file mode 100644 index 0000000..8543e6d --- /dev/null +++ b/pigeonhole/tests/extensions/editheader/errors/command-syntax.sieve @@ -0,0 +1,42 @@ +require "editheader"; + +/* "addheader" [":last"] <field-name: string> <value: string> + */ + +# 1: missing field name and value +addheader; + +# 2: missing value +addheader "x-frop"; + +# 3: value not a string; number +addheader "x-frop" 2; + +# 4: value not a string; list +addheader "x-frop" ["frop"]; + +# 5: strange tag +addheader :tag "x-frop" "frop"; + +/* "deleteheader" [":index" <fieldno: number> [":last"]] + * [COMPARATOR] [MATCH-TYPE] + * <field-name: string> + * [<value-patterns: string-list>] + */ + +# 6: missing field name +deleteheader; + +# 7: :last tag without index +deleteheader :last "x-frop"; + +# 8: :index tag with string argument +deleteheader :index "frop" "x-frop"; + +# OK: match type without value patterns +deleteheader :matches "x-frop"; + +# 9: value patterns not a string(list) +deleteheader "x-frop" 1; + + diff --git a/pigeonhole/tests/extensions/editheader/errors/field-name-runtime.sieve b/pigeonhole/tests/extensions/editheader/errors/field-name-runtime.sieve new file mode 100644 index 0000000..3f34461 --- /dev/null +++ b/pigeonhole/tests/extensions/editheader/errors/field-name-runtime.sieve @@ -0,0 +1,6 @@ +require "editheader"; +require "variables"; + +set "header" "X-field:"; + +addheader "${header}" "Frop"; diff --git a/pigeonhole/tests/extensions/editheader/errors/field-name.sieve b/pigeonhole/tests/extensions/editheader/errors/field-name.sieve new file mode 100644 index 0000000..469bfc8 --- /dev/null +++ b/pigeonhole/tests/extensions/editheader/errors/field-name.sieve @@ -0,0 +1,19 @@ +require "editheader"; + +# Ok +addheader "X-field" "Frop"; + +# Invalid ':' +addheader "X-field:" "Frop"; + +# Invalid ' ' +addheader "X field" "Frop"; + +# Ok +deleteheader "X-field"; + +# Invalid ':' +deleteheader "X-field:"; + +# Invalid ' ' +deleteheader "X field"; diff --git a/pigeonhole/tests/extensions/editheader/errors/field-value.sieve b/pigeonhole/tests/extensions/editheader/errors/field-value.sieve new file mode 100644 index 0000000..c9f4eab --- /dev/null +++ b/pigeonhole/tests/extensions/editheader/errors/field-value.sieve @@ -0,0 +1,15 @@ +require "editheader"; +require "encoded-character"; + +# Ok +addheader "X-field" "Frop"; + +# Ok +addheader "X-field" "Frop +Frml"; + +# Invalid 'BELL'; but not an error +addheader "X-field" "Yeah${hex:07}!"; + +# Invalid 'NUL' +addheader "X-field" "Woah${hex:00}!"; diff --git a/pigeonhole/tests/extensions/editheader/errors/runtime-error.sieve b/pigeonhole/tests/extensions/editheader/errors/runtime-error.sieve new file mode 100644 index 0000000..b308d74 --- /dev/null +++ b/pigeonhole/tests/extensions/editheader/errors/runtime-error.sieve @@ -0,0 +1,6 @@ +require "editheader"; +require "fileinto"; + +addheader "X-Frop" "Friep"; + +fileinto "Rediculous.non-existent.folder"; diff --git a/pigeonhole/tests/extensions/editheader/errors/size-limit-runtime.sieve b/pigeonhole/tests/extensions/editheader/errors/size-limit-runtime.sieve new file mode 100644 index 0000000..73a1437 --- /dev/null +++ b/pigeonhole/tests/extensions/editheader/errors/size-limit-runtime.sieve @@ -0,0 +1,46 @@ +require "editheader"; +require "variables"; + +set "blob" text: +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +. +; + +addheader "x-frop" "${blob}"; diff --git a/pigeonhole/tests/extensions/editheader/errors/size-limit.sieve b/pigeonhole/tests/extensions/editheader/errors/size-limit.sieve new file mode 100644 index 0000000..598f5f9 --- /dev/null +++ b/pigeonhole/tests/extensions/editheader/errors/size-limit.sieve @@ -0,0 +1,43 @@ +require "editheader"; + +addheader "x-frop" text: +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +. +; diff --git a/pigeonhole/tests/extensions/editheader/execute.svtest b/pigeonhole/tests/extensions/editheader/execute.svtest new file mode 100644 index 0000000..e65cc5d --- /dev/null +++ b/pigeonhole/tests/extensions/editheader/execute.svtest @@ -0,0 +1,57 @@ +require "vnd.dovecot.testsuite"; +require "include"; +require "variables"; +require "editheader"; + +/* + * Testsuite self-test + */ + +set "message" "."; +addheader "X-Some-Header" "Header content"; +test_result_reset; +test_set "message" "${message}"; + +/* + * Multi script + */ + +test_result_reset; + +test_set "message" text: +From: idiot@example.com +To: idiot@example.org +Subject: Frop! + +Frop. +. +; + +test_result_reset; +test "Multi script" { + if not test_multiscript [ + "execute/multiscript-before.sieve", + "execute/multiscript-personal.sieve", + "execute/multiscript-after.sieve" + ] { + test_fail "failed to run all scripts"; + } + + test_message :folder "INBOX" 0; + + if not header "subject" "Frop!" { + test_fail "keep not executed."; + } + + if not header "X-Before" "before" { + test_fail "No X-Before header"; + } + + if not header "X-Personal" "personal" { + test_fail "No X-Personal header"; + } + + if not header "X-After" "after" { + test_fail "No X-After header"; + } +} diff --git a/pigeonhole/tests/extensions/editheader/execute/multiscript-after.sieve b/pigeonhole/tests/extensions/editheader/execute/multiscript-after.sieve new file mode 100644 index 0000000..f11f02d --- /dev/null +++ b/pigeonhole/tests/extensions/editheader/execute/multiscript-after.sieve @@ -0,0 +1,4 @@ +require "editheader"; + +addheader "X-After" "after"; + diff --git a/pigeonhole/tests/extensions/editheader/execute/multiscript-before.sieve b/pigeonhole/tests/extensions/editheader/execute/multiscript-before.sieve new file mode 100644 index 0000000..5c8a988 --- /dev/null +++ b/pigeonhole/tests/extensions/editheader/execute/multiscript-before.sieve @@ -0,0 +1,4 @@ +require "editheader"; + +addheader "X-Before" "before"; + diff --git a/pigeonhole/tests/extensions/editheader/execute/multiscript-personal.sieve b/pigeonhole/tests/extensions/editheader/execute/multiscript-personal.sieve new file mode 100644 index 0000000..92e82ac --- /dev/null +++ b/pigeonhole/tests/extensions/editheader/execute/multiscript-personal.sieve @@ -0,0 +1,4 @@ +require "editheader"; + +addheader "X-Personal" "personal"; + diff --git a/pigeonhole/tests/extensions/editheader/protected.svtest b/pigeonhole/tests/extensions/editheader/protected.svtest new file mode 100644 index 0000000..148a9c8 --- /dev/null +++ b/pigeonhole/tests/extensions/editheader/protected.svtest @@ -0,0 +1,173 @@ +require "vnd.dovecot.testsuite"; + +require "variables"; +require "encoded-character"; +require "editheader"; + +set "message" text: +Received: by example.com (Postfix, from userid 202) + id 32A131WFW23QWE4; Mon, 21 Nov 2011 05:25:26 +0200 (EET) +Delivery-date: Mon, 21 Nov 2011 04:26:04 +0100 +Auto-Submitted: yes +X-Friep: frop 3 +Subject: Frop! +From: stephan@example.com +To: tss@example.com + +Frop! +. +; + +test_set "message" "${message}"; +test "Default protected" { + if not exists "received" { + test_fail "received header did not exist in the first place"; + } + + if not exists "auto-submitted" { + test_fail "auto-submitted header did not exist in the first place"; + } + + deleteheader "received"; + deleteheader "auto-submitted"; + deleteheader "subject"; + + if not exists "received" { + test_fail "protected received header was deleted"; + } + + if not exists "auto-submitted" { + test_fail "protected auto-submitted header was deleted"; + } + + if exists "subject" { + test_fail "subject header cannot be protected, but it was not deleted"; + } +} + +test_config_set "sieve_editheader_protected" "subject delivery-date x-frop"; +test_config_reload :extension "editheader"; + +test_set "message" "${message}"; +test "Configured protected" { + if not exists "delivery-date" { + test_fail "received header did not exist in the first place"; + } + + if not exists "subject" { + test_fail "received header did not exist in the first place"; + } + + if exists "x-frop" { + test_fail "x-frop header already present"; + } + + deleteheader "delivery-date"; + deleteheader "subject"; + addheader "x-frop" "Frop!"; + + if not exists "delivery-date" { + test_fail "protected delivery-date header was deleted"; + } + + if exists "subject" { + test_fail "subject header cannot be protected, but it was not deleted"; + } + + if exists "x-frop" { + test_fail "protected x-frop header was added"; + } +} + +test_config_set "sieve_editheader_protected" ""; +test_config_set "sieve_editheader_forbid_add" "subject x-frop"; +test_config_set "sieve_editheader_forbid_delete" "subject x-friep"; +test_config_reload :extension "editheader"; + +test_set "message" "${message}"; +test "Configured forbid_add/forbid_delete" { + if not exists "delivery-date" { + test_fail "received header did not exist in the first place"; + } + + if not exists "subject" { + test_fail "received header did not exist in the first place"; + } + + if not exists "x-friep" { + test_fail "x-friep header did not exist in the first place"; + } + + if exists "x-frop" { + test_fail "x-frop header already present"; + } + + deleteheader "delivery-date"; + deleteheader "subject"; + deleteheader "x-friep"; + + if exists "delivery-date" { + test_fail "unprotected delivery-date header was not deleted"; + } + + if exists "subject" { + test_fail "subject header cannot be protected, but it was not deleted"; + } + + if not exists "x-friep" { + test_fail "protected x-friep header was deleted"; + } + + addheader "delivery-date" "Yesterday"; + addheader "subject" "Fropfrop!"; + addheader "x-frop" "Frop!"; + addheader "received" text: +by sieve.example.com (My little Sieve script) +id 3jhl22khhf23f; Mon, 24 Aug 2015 04:11:54 -0600; +. +; + addheader "auto-submitted" "no way"; + + if not header "delivery-date" "Yesterday" { + test_fail "unprotected delivery-date header was not added"; + } + + if not header "subject" "Fropfrop!" { + test_fail "subject header cannot be protected, but it was not added"; + } + + if exists "x-frop" { + test_fail "protected x-frop header was added"; + } + + if not header :contains "received" "sieve.example.com" { + test_fail "received header was not added"; + } + + if not header "auto-submitted" "no way" { + test_fail "autosubmitted header was not added"; + } +} + +/* + * TEST - Bad header configuration + */ + +test_config_set "sieve_editheader_protected" "${unicode:1F4A9} delivery-date"; +test_config_reload :extension "editheader"; + +test_set "message" "${message}"; +test "Bad header configuration" { + if not exists "delivery-date" { + test_fail "delivery-date header did not exist in the first place"; + } + + deleteheader "delivery-date"; + + if not exists "delivery-date" { + test_fail "protected delivery-date header was deleted"; + } +} + +test_config_set "sieve_editheader_protected" ""; +test_config_reload :extension "editheader"; diff --git a/pigeonhole/tests/extensions/editheader/utf8.svtest b/pigeonhole/tests/extensions/editheader/utf8.svtest new file mode 100644 index 0000000..159a71c --- /dev/null +++ b/pigeonhole/tests/extensions/editheader/utf8.svtest @@ -0,0 +1,97 @@ +require "vnd.dovecot.testsuite"; + +require "encoded-character"; +require "variables"; +require "editheader"; + +test_set "message" text: +Subject: Frop! +From: stephan@example.com +To: stephan@example.com + +Frop! +. +; + +test "UTF8 - add; get" { + set "comment" "Ein unerh${unicode:00F6}rt gro${unicode:00DF}er Test"; + + addheader "Comment" "${comment}"; + + if not exists "comment" { + test_fail "header not added"; + } + + if not header :is "comment" "${comment}" { + test_fail "wrong content added/retrieved"; + } + + redirect "frop@example.com"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + /* redirected message */ + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not exists "comment" { + test_fail "header not added in redirected mail"; + } + + if not header :is "comment" "${comment}" { + test_fail "wrong content added/retrieved from redirected mail"; + } +} + +test_result_reset; + +test_set "message" text: +Subject: Frop! +Comment: Ein =?utf-8?q?unerh=C3=B6rt_gro=C3=9Fer?= Test +X-Spam: no +From: stephan@example.com +To: stephan@example.com + +Frop! +. +; + +test "UTF8 - existing; delete other; get" { + set "comment" "Ein unerh${unicode:00F6}rt gro${unicode:00DF}er Test"; + + deleteheader "x-spam"; + + if not exists "comment" { + test_fail "header not present"; + } + + if not header :is "comment" "${comment}" { + test_fail "wrong content retrieved"; + } + + redirect "frop@example.com"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + /* redirected message */ + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not exists "comment" { + test_fail "header not present in redirected mail"; + } + + if not header :is "comment" "${comment}" { + test_fail "wrong content retrieved from redirected mail"; + } +} + + diff --git a/pigeonhole/tests/extensions/encoded-character.svtest b/pigeonhole/tests/extensions/encoded-character.svtest new file mode 100644 index 0000000..150d812 --- /dev/null +++ b/pigeonhole/tests/extensions/encoded-character.svtest @@ -0,0 +1,180 @@ +require "vnd.dovecot.testsuite"; + +require "encoded-character"; +require "variables"; + +test "HEX equality one" { + if not string "${hex:42}" "B" { + test_fail "failed to match the string 'B'"; + } + + if string "${hex:42}" "b" { + test_fail "matched nonsense"; + } + + if string "${hex:42}" "" { + test_fail "substitution failed"; + } +} + +test "HEX equality one middle" { + if not string " ${hex:42} " " B " { + test_fail "failed to match the string ' B '"; + } + + if string " ${hex:42} " " b " { + test_fail "matched nonsense"; + } + + if string " ${hex:42} " " " { + test_fail "substitution failed"; + } +} + +test "HEX equality one begin" { + if not string "${hex:42} " "B " { + test_fail "failed to match the string 'B '"; + } + + if string "${hex:42} " " b" { + test_fail "matched nonsense"; + } + + if string "${hex:42} " " " { + test_fail "substitution failed"; + } +} + +test "HEX equality one end" { + if not string " ${hex:42}" " B" { + test_fail "failed to match the string ' B'"; + } + + if string " ${hex:42}" " b " { + test_fail "matched nonsense"; + } + + if string " ${hex:42}" " " { + test_fail "substitution failed"; + } +} + +test "HEX equality two triple" { + if not string "${hex:42 61 64}${hex: 61 73 73}" "Badass" { + test_fail "failed to match the string 'Badass'"; + } + + if string "${hex:42 61 64}${hex: 61 73 73}" "Sadass" { + test_fail "matched nonsense"; + } + + if string "${hex:42 61 64}${hex: 61 73 73}" "" { + test_fail "substitution failed"; + } +} + +test "HEX equality braindead" { + if not string "${hex:42 72 61 69 6E 64 65 61 64}" "Braindead" { + test_fail "failed to match the string 'Braindead'"; + } + + if string "${hex:42 72 61 69 6E 64 65 61 64}" "Brian Nut" { + test_fail "matched nonsense"; + } +} + +test "Syntax errors" { + if anyof( not string "$" "${hex:24}", not string "$ " "${hex:24} ", not string " $" " ${hex:24}" ) { + test_fail "loose $ handled inappropriately"; + } + + if anyof( not string "${" "${hex:24}{", not string "a${" "a${hex:24}{", not string "${a" "${hex:24}{a" ) { + test_fail "loose ${ handled inappropriately"; + } + + if anyof( not string "${}" "${hex:24}{}", not string "b${}" "b${hex:24}{}", not string "${}b" "${hex:24}{}b" ) { + test_fail "entirely missing content handled inappropriately"; + } + + if not string "${:}" "${hex:24}{:}" { + test_fail "missing content handled inappropriately"; + } + + if not string "${hex:}" "${hex:24}{hex:}" { + test_fail "missing hex content handled inappropriately"; + } + + if not string "${unicode:}" "${hex:24}{unicode:}" { + test_fail "missing unicode content handled inappropriately"; + } + + if not string "${hex:sss}" "${hex:24}{hex:sss}" { + test_fail "erroneous hex content handled inappropriately"; + } + + if not string "${unicode:ttt}" "${hex:24}{unicode:ttt}" { + test_fail "erroneous unicode content handled inappropriately"; + } + + if not string "${hex:aa aa" "${hex:24}{hex:aa aa" { + test_fail "unterminated hex content handled inappropriately"; + } + + if not string "${unicode: aaaa aaaa" "${hex:24}{unicode: aaaa aaaa" { + test_fail "unterminated unicode content handled inappropriately"; + } +} + +/* + * RFC Examples + */ + +test "RFC Examples" { + if not string "$${hex:40}" "$@" { + test_fail "failed RFC example 1"; + } + + if not string "${hex: 40 }" "@" { + test_fail "failed RFC example 2"; + } + + if not string "${HEX: 40}" "@" { + test_fail "failed RFC example 3"; + } + + if not string "${hex:40" "${hex:40" { + test_fail "failed RFC example 4"; + } + + if not string "${hex:400}" "${hex:400}" { + test_fail "failed RFC example 5"; + } + + if not string "${hex:4${hex:30}}" "${hex: 24}{hex:40}" { + test_fail "failed RFC example 6"; + } + + if not string "${unicode:40}" "@" { + test_fail "failed RFC example 7"; + } + + if not string "${ unicode:40}" "${ unicode:40}" { + test_fail "failed RFC example 8"; + } + + if not string "${UNICODE:40}" "@" { + test_fail "failed RFC example 9"; + } + + if not string "${UnICoDE:0000040}" "@" { + test_fail "failed RFC example 10"; + } + + if not string "${Unicode:40}" "@" { + test_fail "failed RFC example 11"; + } + + if not string "${Unicode:Cool}" "${Unicode:Cool}" { + test_fail "failed RFC example 12"; + } +} diff --git a/pigeonhole/tests/extensions/enotify/basic.svtest b/pigeonhole/tests/extensions/enotify/basic.svtest new file mode 100644 index 0000000..2a03aee --- /dev/null +++ b/pigeonhole/tests/extensions/enotify/basic.svtest @@ -0,0 +1,15 @@ +require "vnd.dovecot.testsuite"; +require "enotify"; + +test "Execute" { + /* Test to catch runtime segfaults */ + if valid_notify_method + "mailto:stephan@example.com" { + + /* Test to catch runtime segfaults */ + notify + :message "This is probably very important" + :importance "1" + "mailto:stephan@example.com%2cstephan@example.org?subject=Important%20message%20received"; + } +} diff --git a/pigeonhole/tests/extensions/enotify/encodeurl.svtest b/pigeonhole/tests/extensions/enotify/encodeurl.svtest new file mode 100644 index 0000000..d334dd3 --- /dev/null +++ b/pigeonhole/tests/extensions/enotify/encodeurl.svtest @@ -0,0 +1,359 @@ +require "vnd.dovecot.testsuite"; +require "encoded-character"; +require "variables"; +require "enotify"; + +/* + * :encodeurl simple + */ + +test ":encodeurl simple" { + set :encodeurl "url_data" "\\frop\\&fruts/^@"; + + if not string :is :comparator "i;octet" "${url_data}" "%5Cfrop%5C%26fruts%2F%5E%40" { + test_fail "url data encoded incorrectly '${url_data}'"; + } +} + +/* + * :encodeurl variable size limit + */ + +test_config_set "sieve_variables_max_variable_size" "4000"; +test_config_reload :extension "variables"; + +set "a" text: +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@ +. +; + +test ":encodeurl variable size limit" { + set :length "alen" "${a}"; + + if not string "${alen}" "4000" { + test_fail "variable 'a' not 4000 bytes long (${alen})"; + } + + set :encodeurl "b" "${a}"; + set :length "blen" "${b}"; + + if not string "${blen}" "3999" { + test_fail "variable 'b' not 3999 bytes long (${blen})"; + } + + set :encodeurl "c" "0${a}"; + set :length "clen" "${c}"; + + if not string "${clen}" "4000" { + test_fail "variable 'c' not 4000 bytes long (${clen})"; + } + + set "cmt" "%40%40%40%40%40%40%40%40%40%40%40%40"; + set "cmt" "${cmt}%40%40%40%40%40%40%40%40%40%40%40%0D%0A"; + set "cmh" "${cmt}${cmt}${cmt}${cmt}"; + set "cm" "${cmh}${cmh}${cmh}${cmh}${cmh}${cmh}${cmh}${cmh}${cmh}${cmh}"; + set "cm" "${cm}${cmh}${cmh}${cmh}"; + set "cm" "0${cm}${cmt}%40%40%40%40%40%40%40%40"; + + if not string :is "${c}" "${cm}" { + test_fail "variable 'c' has unexpected value"; + } + + set :encodeurl "d" "00${a}"; + set :length "dlen" "${d}"; + + if not string "${dlen}" "3998" { + test_fail "variable 'd' not 3998 bytes long (${dlen})"; + } +} + +/* + * :encodeurl variable size limit UTF-8 + */ + +test_config_set "sieve_variables_max_variable_size" "4000"; +test_config_reload :extension "variables"; + +set "a" text: +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03}${unicode:4e03} +. +; + +test ":encodeurl variable size limit UTF-8" { + set :length "alen" "${a}"; + + if not string "${alen}" "546" { + test_fail "variable 'a' not 549 characters long (${alen})"; + } + + set :encodeurl "b" "${a}"; + set :length "blen" "${b}"; + + if not string "${blen}" "3978" { + test_fail "variable 'b' not 3978 bytes long (${blen})"; + } + + set :encodeurl "c" "${a}${unicode:4e00}${unicode:4e00}"; + set :length "clen" "${c}"; + + if not string "${clen}" "3996" { + test_fail "variable 'c' not 3996 bytes long (${clen})"; + } + + set :encodeurl "d" "${a}${unicode:4e00}${unicode:4e00}${unicode:4e00}"; + set :length "dlen" "${d}"; + + if not string "${dlen}" "3996" { + test_fail "variable 'd' not 3996 bytes long (${dlen})"; + } + + set :encodeurl "e" "0000${a}${unicode:4e00}${unicode:4e00}"; + set :length "elen" "${e}"; + + if not string "${elen}" "4000" { + test_fail "variable 'e' not 4000 bytes long (${elen})"; + } + + set :encodeurl "f" "00000${a}${unicode:4e00}${unicode:4e00}"; + set :length "flen" "${f}"; + + if not string "${flen}" "3992" { + test_fail "variable 'f' not 3992 bytes long (${flen})"; + } +} diff --git a/pigeonhole/tests/extensions/enotify/errors.svtest b/pigeonhole/tests/extensions/enotify/errors.svtest new file mode 100644 index 0000000..5af36df --- /dev/null +++ b/pigeonhole/tests/extensions/enotify/errors.svtest @@ -0,0 +1,45 @@ +require "vnd.dovecot.testsuite"; +require "comparator-i;ascii-numeric"; +require "relational"; + +require "enotify"; + +test "Invalid URI (FIXME: count only)" { + if test_script_compile "errors/uri.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "2" { + test_fail "wrong number of errors reported"; + } +} + +test "Invalid mailto URI (FIXME: count only)" { + if test_script_compile "errors/uri-mailto.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "7" { + test_fail "wrong number of errors reported"; + } +} + +test "Invalid mailto :from address (FIXME: count only)" { + if test_script_compile "errors/from-mailto.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "wrong number of errors reported"; + } +} + +test "Invalid :options argument (FIXME: count only)" { + if test_script_compile "errors/options.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "6" { + test_fail "wrong number of errors reported"; + } +} diff --git a/pigeonhole/tests/extensions/enotify/errors/from-mailto.sieve b/pigeonhole/tests/extensions/enotify/errors/from-mailto.sieve new file mode 100644 index 0000000..d519256 --- /dev/null +++ b/pigeonhole/tests/extensions/enotify/errors/from-mailto.sieve @@ -0,0 +1,7 @@ +require "enotify"; + +# 1: Invalid from address +notify :from "stephan#example.org" "mailto:stephan@example.com"; + +# 2: Empty from address +notify :from "" "mailto:stephan@example.com"; diff --git a/pigeonhole/tests/extensions/enotify/errors/options.sieve b/pigeonhole/tests/extensions/enotify/errors/options.sieve new file mode 100644 index 0000000..58d2265 --- /dev/null +++ b/pigeonhole/tests/extensions/enotify/errors/options.sieve @@ -0,0 +1,18 @@ +require "enotify"; + +# 1: empty option +notify :options "" "mailto:stephan@example.org"; + +# 2: invalid option name syntax +notify :options "frop" "mailto:stephan@example.org"; + +# 3: invalid option name syntax +notify :options "_frop=" "mailto:stephan@example.org"; + +# 4: invalid option name syntax +notify :options "=frop" "mailto:stephan@example.org"; + +# 5: invalid value +notify :options "frop=frml +frop" "mailto:stephan@example.org"; + diff --git a/pigeonhole/tests/extensions/enotify/errors/uri-mailto.sieve b/pigeonhole/tests/extensions/enotify/errors/uri-mailto.sieve new file mode 100644 index 0000000..2aced86 --- /dev/null +++ b/pigeonhole/tests/extensions/enotify/errors/uri-mailto.sieve @@ -0,0 +1,20 @@ +require "enotify"; + +# 1: Invalid character in to part +notify "mailto:stephan@example.org;?header=frop"; + +# 2: Invalid character in hname +notify "mailto:stephan@example.org?header<=frop"; + +# 3: Invalid character in hvalue +notify "mailto:stephan@example.org?header=fr>op"; + +# 4: Invalid header name +notify "mailto:stephan@example.org?header:=frop"; + +# 5: Invalid recipient +notify "mailto:stephan%23example.org"; + +# 6: Invalid to header recipient +notify "mailto:stephan@example.org?to=nico%23frop.example.org"; + diff --git a/pigeonhole/tests/extensions/enotify/errors/uri.sieve b/pigeonhole/tests/extensions/enotify/errors/uri.sieve new file mode 100644 index 0000000..13ead81 --- /dev/null +++ b/pigeonhole/tests/extensions/enotify/errors/uri.sieve @@ -0,0 +1,5 @@ +require "enotify"; + +# 1: Invalid url scheme +notify "snailto:stephan@example.org"; + diff --git a/pigeonhole/tests/extensions/enotify/execute.svtest b/pigeonhole/tests/extensions/enotify/execute.svtest new file mode 100644 index 0000000..cd6486d --- /dev/null +++ b/pigeonhole/tests/extensions/enotify/execute.svtest @@ -0,0 +1,99 @@ +require "vnd.dovecot.testsuite"; +require "relational"; + + +/* + * Execution testing (currently just meant to trigger any segfaults) + */ + +test "RFC Example 1" { + if not test_script_compile "execute/draft-rfc-ex1.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script run failed"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } +} + +test "RFC Example 2" { + if not test_script_compile "execute/draft-rfc-ex2.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script execute failed"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } +} + +/* tel: not supported +test "RFC Example 3" { + if not test_script_compile "execute/draft-rfc-ex3.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script execute failed"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } +} +*/ + +/* tel: and xmmp: not supported +test "RFC Example 5" { + if not test_script_compile "execute/draft-rfc-ex5.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script execute failed"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } +} +*/ + +test "RFC Example 6" { + if not test_script_compile "execute/draft-rfc-ex6.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script execute failed"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } +} + +test "Duplicate recipients" { + if not test_script_compile "execute/duplicates.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script execute failed"; + } + + if test_result_action :count "ne" "2" { + test_fail "second notify action was discarded entirely"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } +} diff --git a/pigeonhole/tests/extensions/enotify/execute/draft-rfc-ex1.sieve b/pigeonhole/tests/extensions/enotify/execute/draft-rfc-ex1.sieve new file mode 100644 index 0000000..6747d7b --- /dev/null +++ b/pigeonhole/tests/extensions/enotify/execute/draft-rfc-ex1.sieve @@ -0,0 +1,26 @@ +require ["enotify", "fileinto", "variables"]; + +if header :contains "from" "boss@example.org" { + notify :importance "1" + :message "This is probably very important" + "mailto:alm@example.com"; + # Don't send any further notifications + stop; +} + +if header :contains "to" "sievemailinglist@example.org" { + # :matches is used to get the value of the Subject header + if header :matches "Subject" "*" { + set "subject" "${1}"; + } + + # :matches is used to get the value of the From header + if header :matches "From" "*" { + set "from" "${1}"; + } + + notify :importance "3" + :message "[SIEVE] ${from}: ${subject}" + "mailto:alm@example.com"; + fileinto "INBOX.sieve"; +} diff --git a/pigeonhole/tests/extensions/enotify/execute/draft-rfc-ex2.sieve b/pigeonhole/tests/extensions/enotify/execute/draft-rfc-ex2.sieve new file mode 100644 index 0000000..a5c6a26 --- /dev/null +++ b/pigeonhole/tests/extensions/enotify/execute/draft-rfc-ex2.sieve @@ -0,0 +1,22 @@ +require ["enotify", "fileinto", "variables", "envelope"]; + +if header :matches "from" "*@*.example.org" { + # :matches is used to get the MAIL FROM address + if envelope :all :matches "from" "*" { + set "env_from" " [really: ${1}]"; + } + + # :matches is used to get the value of the Subject header + if header :matches "Subject" "*" { + set "subject" "${1}"; + } + + # :matches is used to get the address from the From header + if address :matches :all "from" "*" { + set "from_addr" "${1}"; + } + + notify :message "${from_addr}${env_from}: ${subject}" + "mailto:alm@example.com"; +} + diff --git a/pigeonhole/tests/extensions/enotify/execute/draft-rfc-ex3.sieve b/pigeonhole/tests/extensions/enotify/execute/draft-rfc-ex3.sieve new file mode 100644 index 0000000..a7b4a64 --- /dev/null +++ b/pigeonhole/tests/extensions/enotify/execute/draft-rfc-ex3.sieve @@ -0,0 +1,31 @@ +require ["enotify", "variables"]; + +set "notif_method" + "xmpp:tim@example.com?message;subject=SIEVE;body=You%20got%20mail"; + +if header :contains "subject" "Your dog" { + set "notif_method" "tel:+14085551212"; +} + +if header :contains "to" "sievemailinglist@example.org" { + set "notif_method" ""; +} + +if not string :is "${notif_method}" "" { + notify "${notif_method}"; +} + +if header :contains "from" "boss@example.org" { + # :matches is used to get the value of the Subject header + if header :matches "Subject" "*" { + set "subject" "${1}"; + } + + # don't need high importance notification for + # a 'for your information' + if not header :contains "subject" "FYI:" { + notify :importance "1" :message "BOSS: ${subject}" + "tel:+14085551212"; + } +} + diff --git a/pigeonhole/tests/extensions/enotify/execute/draft-rfc-ex5.sieve b/pigeonhole/tests/extensions/enotify/execute/draft-rfc-ex5.sieve new file mode 100644 index 0000000..c6b7dc6 --- /dev/null +++ b/pigeonhole/tests/extensions/enotify/execute/draft-rfc-ex5.sieve @@ -0,0 +1,11 @@ +require ["enotify"]; + +if notify_method_capability + "xmpp:tim@example.com?message;subject=SIEVE" + "Online" + "yes" { + notify :importance "1" :message "You got mail" + "xmpp:tim@example.com?message;subject=SIEVE"; +} else { + notify :message "You got mail" "tel:+14085551212"; +} diff --git a/pigeonhole/tests/extensions/enotify/execute/draft-rfc-ex6.sieve b/pigeonhole/tests/extensions/enotify/execute/draft-rfc-ex6.sieve new file mode 100644 index 0000000..6a65c64 --- /dev/null +++ b/pigeonhole/tests/extensions/enotify/execute/draft-rfc-ex6.sieve @@ -0,0 +1,5 @@ +require ["enotify", "variables"]; + +set :encodeurl "body_param" "Safe body&evil=evilbody"; + +notify "mailto:tim@example.com?body=${body_param}"; diff --git a/pigeonhole/tests/extensions/enotify/execute/duplicates.sieve b/pigeonhole/tests/extensions/enotify/execute/duplicates.sieve new file mode 100644 index 0000000..17f2388 --- /dev/null +++ b/pigeonhole/tests/extensions/enotify/execute/duplicates.sieve @@ -0,0 +1,4 @@ +require "enotify"; + +notify :message "Incoming stupidity." "mailto:stephan@example.org%2cstephan@friep.example.com%2cidiot@example.org"; +notify :message "There it is." "mailto:tss@example.net%2cstephan@example.org%2cidiot@example.org%2cnico@frop.example.org%2cstephan@friep.example.com"; diff --git a/pigeonhole/tests/extensions/enotify/mailto.svtest b/pigeonhole/tests/extensions/enotify/mailto.svtest new file mode 100644 index 0000000..68d8daa --- /dev/null +++ b/pigeonhole/tests/extensions/enotify/mailto.svtest @@ -0,0 +1,541 @@ +require "vnd.dovecot.testsuite"; +require "enotify"; +require "relational"; +require "envelope"; +require "variables"; +require "comparator-i;ascii-numeric"; + +/* + * Simple test + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test "Simple" { + notify "mailto:stephan@example.org"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not header :matches "Auto-Submitted" "auto-notified*" { + test_fail "auto-submitted header set inappropriately"; + } + + if not exists "X-Sieve" { + test_fail "x-sieve header missing from outgoing message"; + } + + if anyof ( + not header :matches "x-priority" "3 *", + not header "importance" "normal") { + + test_fail "default priority is not normal"; + } +} + +/* + * Multiple recipients + */ + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test "Multiple recipients" { + notify "mailto:timo@example.com%2cstephan@dovecot.example.net?cc=postmaster@frop.example.org&subject=Frop%20received"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not address :is "to" "timo@example.com" { + test_fail "first To address missing"; + } + + if not address :is "to" "stephan@dovecot.example.net" { + test_fail "second To address missing"; + } + + if not address :is "cc" "postmaster@frop.example.org" { + test_fail "first Cc address missing"; + } + + if not address :count "eq" :comparator "i;ascii-numeric" "to" "2" { + test_fail "too many recipients in To header"; + } + + if not address :count "eq" :comparator "i;ascii-numeric" "cc" "1" { + test_fail "too many recipients in Cc header"; + } + + if not header "subject" "Frop received" { + test_fail "subject header set incorrectly"; + } + + test_message :smtp 1; + + if not header :matches "Auto-Submitted" "auto-notified*" { + test_fail "auto-submitted header not found for second message"; + } + + test_message :smtp 2; + + if not header :matches "Auto-Submitted" "auto-notified*" { + test_fail "auto-submitted header not found for third message"; + } +} + +/* + * Duplicate recipients + */ + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test "Duplicate recipients" { + notify "mailto:timo@example.com%2cstephan@dovecot.example.net?cc=stephan@dovecot.example.net"; + notify "mailto:stephan@example.org?cc=timo@example.com"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if address "Cc" "stephan@dovecot.example.net" { + test_fail "duplicate recipient not removed from first message"; + } + + test_message :smtp 1; + + if address "Cc" "timo@example.com" { + test_fail "duplicate recipient not removed from second message"; + } +} + + +/* + * Notifying on automated messages + */ + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Auto-submitted: auto-notify +Subject: Frop! + +Klutsefluts. +. +; + +test "Notifying on automated messages" { + notify "mailto:stephan@example.org?cc=timo@example.com"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + if test_message :smtp 0 { + test_fail "notified of auto-submitted message"; + } +} + +/* + * Envelope + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test_result_reset; + +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "bertus@frop.example.org"; + +test "Envelope" { + notify "mailto:stephan@example.org?cc=timo@example.com"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not envelope :localpart :is "from" "postmaster" { + test_fail "envelope sender set incorrectly"; + } + + if not envelope :is "to" "stephan@example.org" { + test_fail "envelope sender set incorrectly"; + } + + test_message :smtp 1; + + if not envelope :localpart :is "from" "postmaster" { + test_fail "envelope sender set incorrectly"; + } + + if not envelope :is "to" "timo@example.com" { + test_fail "envelope sender set incorrectly"; + } +} + +/* + * Envelope :from + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "bertus@frop.example.org"; + +test_result_reset; + +test "Envelope :from" { + notify :from "nico@frop.example.org" + "mailto:stephan@example.org?cc=timo@example.com"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not envelope :is "from" "nico@frop.example.org" { + test_fail "envelope sender set incorrectly"; + } + + if not envelope :is "to" "stephan@example.org" { + test_fail "envelope sender set incorrectly"; + } + + test_message :smtp 1; + + if not envelope :is "from" "nico@frop.example.org" { + test_fail "envelope sender set incorrectly"; + } + + if not envelope :is "to" "timo@example.com" { + test_fail "envelope sender set incorrectly"; + } +} + +/* + * Envelope <> + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test_set "envelope.from" "<>"; +test_set "envelope.to" "bertus@frop.example.org"; + +test_result_reset; + +test "Envelope <>" { + notify :from "nico@frop.example.org" + "mailto:stephan@example.org?cc=timo@example.com"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not envelope :is "from" "" { + test_fail "envelope sender set incorrectly"; + } + + if not envelope :is "to" "stephan@example.org" { + test_fail "envelope recipient set incorrectly"; + } + + test_message :smtp 1; + + if not envelope :is "from" "" { + test_fail "envelope sender set incorrectly"; + } + + if not envelope :is "to" "timo@example.com" { + test_fail "envelope recipient set incorrectly"; + } +} + +/* + * Envelope config - sender + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "bertus@frop.example.org"; + +test_config_set "sieve_notify_mailto_envelope_from" + "sender"; +test_config_reload :extension "enotify"; +test_result_reset; + +test "Envelope config - sender" { + notify :from "nico@frop.example.org" + "mailto:stephan@example.org?cc=timo@example.com"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not header :is "from" "nico@frop.example.org" { + test_fail "from set incorrectly"; + } + + if not envelope :is "from" "sirius@example.org" { + test_fail "envelope sender set incorrectly"; + } + + if not envelope :is "to" "stephan@example.org" { + test_fail "envelope recipient set incorrectly"; + } + + test_message :smtp 1; + + if not header :is "from" "nico@frop.example.org" { + test_fail "from set incorrectly"; + } + + if not envelope :is "from" "sirius@example.org" { + test_fail "envelope sender set incorrectly"; + } + + if not envelope :is "to" "timo@example.com" { + test_fail "envelope recipient set incorrectly"; + } +} + +/* + * Envelope config - recipient + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "bertus@frop.example.org"; + +test_config_set "sieve_notify_mailto_envelope_from" + "recipient"; +test_config_reload :extension "enotify"; +test_result_reset; + +test "Envelope config - recipient" { + notify :from "nico@frop.example.org" + "mailto:stephan@example.org?cc=timo@example.com"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not header :is "from" "nico@frop.example.org" { + test_fail "from set incorrectly"; + } + + if not envelope :is "from" "bertus@frop.example.org" { + test_fail "envelope sender set incorrectly"; + } + + if not envelope :is "to" "stephan@example.org" { + test_fail "envelope recipient set incorrectly"; + } + + test_message :smtp 1; + + if not header :is "from" "nico@frop.example.org" { + test_fail "from set incorrectly"; + } + + if not envelope :is "from" "bertus@frop.example.org" { + test_fail "envelope sender set incorrectly"; + } + + if not envelope :is "to" "timo@example.com" { + test_fail "envelope recipient set incorrectly"; + } +} + +/* + * Envelope config - user_email + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "bertus@frop.example.org"; + +test_config_set "sieve_notify_mailto_envelope_from" + "user_email"; +test_config_set "sieve_user_email" "b.wortel@example.org"; +test_config_reload; +test_config_reload :extension "enotify"; +test_result_reset; + +test "Envelope config - user_email" { + notify :from "nico@frop.example.org" + "mailto:stephan@example.org?cc=timo@example.com"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not header :is "from" "nico@frop.example.org" { + test_fail "from set incorrectly"; + } + + if not envelope :is "from" "b.wortel@example.org" { + test_fail "envelope sender set incorrectly"; + } + + if not envelope :is "to" "stephan@example.org" { + test_fail "envelope recipient set incorrectly"; + } + + test_message :smtp 1; + + if not header :is "from" "nico@frop.example.org" { + test_fail "from set incorrectly"; + } + + if not envelope :is "from" "b.wortel@example.org" { + test_fail "envelope sender set incorrectly"; + } + + if not envelope :is "to" "timo@example.com" { + test_fail "envelope recipient set incorrectly"; + } +} + +/* + * UTF-8 addresses + */ + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test "UTF-8 address" { + set "to" "=?utf-8?q?G=C3=BCnther?= M. Karotte <g.m.karotte@example.com>"; + set "cc" "Dieter T. =?utf-8?q?Stoppelr=C3=BCbe?= <d.t.stoppelruebe@example.com>"; + + set :encodeurl "to_enc" "${to}"; + set :encodeurl "cc_enc" "${cc}"; + + notify "mailto:?to=${to_enc}&cc=${cc_enc}"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + set "expected" "Günther M. Karotte <g.m.karotte@example.com>"; + if not header :is "to" "${expected}" { + if header :matches "to" "*" { set "decoded" "${1}"; } + + test_fail text: +to header is not encoded/decoded properly: +expected: ${expected} +decoded: ${decoded} +. +; + } + + set "expected" "Dieter T. Stoppelrübe <d.t.stoppelruebe@example.com>"; + if not header :is "cc" "${expected}" { + if header :matches "cc" "*" { set "decoded" "${1}"; } + + test_fail text: +to header is not encoded/decoded properly: +expected: ${expected} +decoded: ${decoded} +. +; + } +} diff --git a/pigeonhole/tests/extensions/enotify/notify_method_capability.svtest b/pigeonhole/tests/extensions/enotify/notify_method_capability.svtest new file mode 100644 index 0000000..0d13477 --- /dev/null +++ b/pigeonhole/tests/extensions/enotify/notify_method_capability.svtest @@ -0,0 +1,12 @@ +require "vnd.dovecot.testsuite"; +require "enotify"; + +test "Mailto" { + if not notify_method_capability :is "mailto:stephan@example.org" "online" "maybe" { + test_fail "test should have matched"; + } + + if notify_method_capability :is "mailto:stephan@example.org" "online" "yes" { + test_fail "test should not have matched"; + } +} diff --git a/pigeonhole/tests/extensions/enotify/valid_notify_method.svtest b/pigeonhole/tests/extensions/enotify/valid_notify_method.svtest new file mode 100644 index 0000000..35255d6 --- /dev/null +++ b/pigeonhole/tests/extensions/enotify/valid_notify_method.svtest @@ -0,0 +1,31 @@ +require "vnd.dovecot.testsuite"; + +require "enotify"; + +test "Mailto: invalid header name" { + if valid_notify_method + "mailto:stephan@example.org?header:=frop" { + test_fail "invalid uri accepted"; + } +} + +test "Mailto: invalid recipient" { + if valid_notify_method + "mailto:stephan%23example.org" { + test_fail "invalid uri accepted"; + } +} + +test "Mailto: invalid to header recipient" { + if valid_notify_method + "mailto:stephan@example.org?to=nico%23frop.example.org" { + test_fail "invalid uri accepted"; + } +} + +test "Mailto: valid URI" { + if not valid_notify_method + "mailto:stephan@example.org" { + test_fail "valid uri denied"; + } +} diff --git a/pigeonhole/tests/extensions/envelope.svtest b/pigeonhole/tests/extensions/envelope.svtest new file mode 100644 index 0000000..9cf3b8b --- /dev/null +++ b/pigeonhole/tests/extensions/envelope.svtest @@ -0,0 +1,244 @@ +require "vnd.dovecot.testsuite"; + +require "envelope"; + +/* + * Empty envelope addresses + */ + +/* RFC 5228, Section 5.4: The null reverse-path is matched against as the empty + * string, regardless of the ADDRESS-PART argument specified. + */ + +test "Envelope - from empty" { + /* Return_path: "" */ + + test_set "envelope.from" ""; + + if not envelope :all :is "from" "" { + test_fail "failed to (:all :is)-match a \"\" return path"; + } + + if not envelope :all :contains "from" "" { + test_fail "failed to (:all :contains)-match a \"\" return path"; + } + + if not envelope :domain :is "from" "" { + test_fail "failed to (:domain :is)-match a \"\" return path"; + } + + if not envelope :domain :contains "from" "" { + test_fail "failed to (:domain :contains)-match a \"\" return path"; + } + + /* Return path: <> */ + + test_set "envelope.from" "<>"; + + if not envelope :all :is "from" "" { + test_fail "failed to (:all :is)-match a <> return path"; + } + + if not envelope :all :contains "from" "" { + test_fail "failed to (:all :contains)-match a <> return path"; + } + + if not envelope :domain :is "from" "" { + test_fail "failed to (:domain :is)-match a <> return path"; + } + + if not envelope :domain :contains "from" "" { + test_fail "failed to (:domain :contains)-match a <> return path"; + } + + if envelope :all :is "from" "nico@frop.example.org" { + test_fail "envelope test matches nonsense"; + } +} + +/* + * Invalid envelope addresses + */ + +test "Envelope - invalid paths" { + /* Return_path: "hutsefluts" */ + + test_set "envelope.from" "hutsefluts@"; + test_set "envelope.to" "knurft@"; + + if envelope :all :is "from" "hutsefluts@" { + test_fail ":all address part matched syntactically incorrect reverse path"; + } + if envelope :all :is "to" "knurft@" { + test_fail ":all address part matched syntactically incorrect forward path"; + } +} + +/* + * Syntax errors + */ + +test "Envelope - syntax errors" { + /* Control */ + test_set "envelope.from" "<stephan@example.org>"; + if not envelope :all :is "from" "stephan@example.org" { + test_fail "correct control test failed"; + } + + # Duplicate < + test_set "envelope.from" "<<stephan@example.org>"; + if envelope :all :is "from" "stephan@example.org" { + test_fail "failed to recognize syntax error (1)"; + } + + # Spurious > + test_set "envelope.from" "stephan@example.org>"; + if envelope :all :is "from" "stephan@example.org" { + test_fail "failed to recognize syntax error (2)"; + } + + # Missing > + test_set "envelope.from" "<stephan@example.org"; + if envelope :all :is "from" "stephan@example.org" { + test_fail "failed to recognize syntax error (3)"; + } + + # No @ + test_set "envelope.from" "<stephan example.org>"; + if envelope :domain :contains "from" "example" { + test_fail "failed to recognize syntax error (4)"; + } + + # Duplicate @ + test_set "envelope.from" "<stephan@@example.org>"; + if envelope :domain :contains "from" "example" { + test_fail "failed to recognize syntax error (5)"; + } +} + +/* + * Ignoring source routes + */ + +test "Envelope - source route" { + /* Single */ + test_set "envelope.from" "<@cola.example.org:stephan@example.org>"; + if not envelope :localpart :is "from" "stephan" { + test_fail "parsing path with source route (single) failed"; + } + + /* Dual */ + test_set "envelope.from" "<@cola.example.org,@mx.utwente.nl:stephan@example.org>"; + if not envelope :localpart :is "from" "stephan" { + test_fail "parsing path with source route (dual) failed"; + } + + /* Multiple */ + test_set "envelope.from" "<@cola.example.org,@mx.utwente.nl,@smtp.example.net:stephan@example.org>"; + if not envelope :localpart :is "from" "stephan" { + test_fail "parsing path with source route (multiple) failed"; + } +} + +test "Envelope - source route errors" { + test_set "envelope.to" "<cola.example.org:stephan@example.org>"; + if envelope :domain :contains "to" "" { + test_fail "parsing syntactically incorrect path should have failed (1)"; + } + + test_set "envelope.to" "<@.example.org:stephan@example.org>"; + if envelope :domain :contains "to" "" { + test_fail "parsing syntactically incorrect path should have failed (2)"; + } + + test_set "envelope.to" "<@cola..nl:stephan@example.org>"; + if envelope :domain :contains "to" "" { + test_fail "parsing syntactically incorrect path should have failed (3)"; + } + + test_set "envelope.to" "<@cola.example.orgstephan@example.org>"; + if envelope :domain :contains "to" "" { + test_fail "parsing syntactically incorrect path should have failed (4)"; + } + + test_set "envelope.to" "<@cola.example.org@mx.utwente.nl:stephan@example.org>"; + if envelope :domain :contains "to" "" { + test_fail "parsing syntactically incorrect path should have failed (5)"; + } + + test_set "envelope.to" "<@cola.example.org,mx.utwente.nl:stephan@example.org>"; + if envelope :domain :contains "to" "" { + test_fail "parsing syntactically incorrect path should have failed (6)"; + } + + test_set "envelope.to" "<@cola.example.org,@mx.utwente.nl,stephan@example.org>"; + if envelope :domain :contains "to" "" { + test_fail "parsing syntactically incorrect path should have failed (7)"; + } +} + +test "Envelope - local part only" { + test_set "envelope.to" "<MAILER-DAEMON>"; + if not envelope :is "to" "MAILER-DAEMON" { + test_fail "failed to parse local_part only path"; + } + + test_set "envelope.to" "MAILER-DAEMON@"; + if envelope :is "to" "MAILER-DAEMON" { + test_fail "parsing syntactically incorrect path with missing domain"; + } + + test_set "envelope.to" "<MAILER-DAEMON>"; + if not envelope :is "to" "MAILER-DAEMON" { + test_fail "failed to parse local_part only path with angle brackets"; + } +} + +test "Envelope - Japanese localpart" { + test_set "envelope.to" ".japanese@example.com"; + if not envelope :localpart :is "to" ".japanese" { + test_fail "failed to parse japanese local_part (1)"; + } + + test_set "envelope.to" "japanese.@example.com"; + if not envelope :localpart :is "to" "japanese." { + test_fail "failed to parse japanese local_part (2)"; + } + + test_set "envelope.to" "japanese...localpart@example.com"; + if not envelope :localpart :is "to" "japanese...localpart" { + test_fail "failed to parse japanese local_part (3)"; + } + + test_set "envelope.to" "..japanese...localpart..@example.com"; + if not envelope :localpart :is "to" "..japanese...localpart.." { + test_fail "failed to parse japanese local_part (4)"; + } +} + +test "Envelope - Non-standard hostnames" { + test_set "envelope.to" "japanese@_example.com"; + if not envelope :domain :is "to" "_example.com" { + test_fail "failed to parse non-standard domain (1)"; + } + + test_set "envelope.to" "japanese@ex_ample.com"; + if not envelope :domain :is "to" "ex_ample.com" { + test_fail "failed to parse non-standard domain (2)"; + } + + test_set "envelope.to" "japanese@example_.com"; + if not envelope :domain :is "to" "example_.com" { + test_fail "failed to parse non-standard domain (3)"; + } + + test_set "envelope.to" "japanese@-example.com"; + if not envelope :domain :is "to" "-example.com" { + test_fail "failed to parse non-standard domain (4)"; + } + + test_set "envelope.to" "japanese@example-.com"; + if not envelope :domain :is "to" "example-.com" { + test_fail "failed to parse non-standard domain (5)"; + } +} diff --git a/pigeonhole/tests/extensions/environment/basic.svtest b/pigeonhole/tests/extensions/environment/basic.svtest new file mode 100644 index 0000000..bb0beb4 --- /dev/null +++ b/pigeonhole/tests/extensions/environment/basic.svtest @@ -0,0 +1,33 @@ +require "vnd.dovecot.testsuite"; +require "environment"; +require "variables"; + +test "Name" { + if not environment :contains "name" "pigeonhole" { + if environment :matches "name" "*" { set "env_name" "${1}"; } + + test_fail "name environment returned invalid value(1): ${env_name}"; + } + + if not environment :contains "name" "sieve" { + if environment :matches "name" "*" { set "env_name" "${1}"; } + + test_fail "name environment returned invalid value(2): ${env_name}"; + } + + if environment :contains "name" "cyrus" { + test_fail "something is definitely wrong here"; + } + + if not environment :is :comparator "i;octet" "name" "Pigeonhole Sieve" { + test_fail "name environment does not match exactly with what is expected"; + } +} + +test "Location" { + if not environment "location" "MS" { + test_fail "wrong testsuite environment location"; + } +} + + diff --git a/pigeonhole/tests/extensions/environment/rfc.svtest b/pigeonhole/tests/extensions/environment/rfc.svtest new file mode 100644 index 0000000..c3177ae --- /dev/null +++ b/pigeonhole/tests/extensions/environment/rfc.svtest @@ -0,0 +1,28 @@ +require "vnd.dovecot.testsuite"; +require "environment"; +require "relational"; + +test "Non-existent" { + if environment :contains "nonsense" "" { + test_fail "matched unknown environment item"; + } +} + +test "Exists" { + if not environment :contains "version" "" { + test_fail "failed to match known environment item"; + } +} + +test "Count" { + if anyof ( + environment :count "eq" "nonsense" "0", + environment :count "eq" "nonsense" "1" + ) { + test_fail "count should not match unknown environment item"; + } + + if not environment :count "eq" "location" "1" { + test_fail "count of non-empty environment should be 1"; + } +} diff --git a/pigeonhole/tests/extensions/ihave/errors.svtest b/pigeonhole/tests/extensions/ihave/errors.svtest new file mode 100644 index 0000000..c6b9750 --- /dev/null +++ b/pigeonhole/tests/extensions/ihave/errors.svtest @@ -0,0 +1,19 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +test "Error command" { + if not test_script_compile "errors/error.sieve" { + test_fail "compile failed"; + } + + if test_script_run { + test_fail "execution should have failed"; + } + + if test_error :count "gt" :comparator "i;ascii-numeric" "1" { + test_fail "too many runtime errors reported"; + } +} + diff --git a/pigeonhole/tests/extensions/ihave/errors/error.sieve b/pigeonhole/tests/extensions/ihave/errors/error.sieve new file mode 100644 index 0000000..8da0fe7 --- /dev/null +++ b/pigeonhole/tests/extensions/ihave/errors/error.sieve @@ -0,0 +1,3 @@ +require "ihave"; + +error "Something failed."; diff --git a/pigeonhole/tests/extensions/ihave/execute.svtest b/pigeonhole/tests/extensions/ihave/execute.svtest new file mode 100644 index 0000000..701d817 --- /dev/null +++ b/pigeonhole/tests/extensions/ihave/execute.svtest @@ -0,0 +1,23 @@ +require "vnd.dovecot.testsuite"; + +/* + * Execution testing (currently just meant to trigger any segfaults) + */ + +test "Basic" { + if not test_script_compile "execute/ihave.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script run failed"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } + + test_binary_save "ihave-basic"; + test_binary_load "ihave-basic"; +} + diff --git a/pigeonhole/tests/extensions/ihave/execute/ihave.sieve b/pigeonhole/tests/extensions/ihave/execute/ihave.sieve new file mode 100644 index 0000000..0fe84c8 --- /dev/null +++ b/pigeonhole/tests/extensions/ihave/execute/ihave.sieve @@ -0,0 +1,7 @@ +require "ihave"; + +if ihave "nonsense-extension" { + nonsense_command "Frop!"; +} + +redirect "frop@example.com"; diff --git a/pigeonhole/tests/extensions/ihave/restrictions.svtest b/pigeonhole/tests/extensions/ihave/restrictions.svtest new file mode 100644 index 0000000..5dba126 --- /dev/null +++ b/pigeonhole/tests/extensions/ihave/restrictions.svtest @@ -0,0 +1,14 @@ +require "vnd.dovecot.testsuite"; +require "ihave"; + +test "Restricted: encoded-character" { + if ihave "encoded-character" { + test_fail "encoded-character extension is incompatible with ihave"; + } +} + +test "Restricted: variables" { + if ihave "variables" { + test_fail "variables extension is incompatible with ihave"; + } +} diff --git a/pigeonhole/tests/extensions/imap4flags/basic.svtest b/pigeonhole/tests/extensions/imap4flags/basic.svtest new file mode 100644 index 0000000..d6af444 --- /dev/null +++ b/pigeonhole/tests/extensions/imap4flags/basic.svtest @@ -0,0 +1,332 @@ +require "vnd.dovecot.testsuite"; + +require "imap4flags"; +require "relational"; +require "variables"; +require "comparator-i;ascii-numeric"; + +/* + * Basic functionality tests + */ + +test "Hasflag empty" { + if hasflag "\\Seen" { + test_fail "hasflag sees initial \\seen flag were there should be none"; + } + if hasflag "\\draft" { + test_fail "hasflag sees initial \\draft flag were there should be none"; + } + if hasflag "\\recent" { + test_fail "hasflag sees initial \\recent flag were there should be none"; + } + if hasflag "\\flagged" { + test_fail "hasflag sees initial \\flagged flag were there should be none"; + } + if hasflag "\\answered" { + test_fail "hasflag sees initial \\answered flag were there should be none"; + } + if hasflag "\\deleted" { + test_fail "hasflag sees initial \\deleted flag were there should be none"; + } + + if hasflag :comparator "i;ascii-numeric" :count "ge" "1" { + test_fail "hasflag sees initial flags were there should be none"; + } +} + +test "Setflag; Hasflag one" { + setflag "\\seen"; + + if not hasflag "\\Seen" { + test_fail "flag not set of hasflag fails to see it"; + } + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "1" { + test_fail "flag not set of hasflag fails to see it"; + } + + if hasflag "$Nonsense" { + test_fail "hasflag sees other flag that the one set"; + } +} + +test "Hasflag; duplicates" { + set "Flags" "A B C D E F A B C D E F"; + + if hasflag :comparator "i;ascii-numeric" :count "gt" "Flags" "6" { + test_fail "hasflag must ignore duplicates"; + } + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "Flags" "6" { + test_fail "hasflag :count gives strange results"; + } +} + +test "Flag operations" { + setflag "A"; + + if not hasflag "A" { + test_fail "hasflag misses set flag"; + } + + if hasflag :comparator "i;ascii-numeric" :count "gt" "1" { + test_fail "hasflag sees more than one flag"; + } + + addflag "B"; + + if not hasflag "B" { + test_fail "flag \"B\" not added"; + } + + if not hasflag "A" { + test_fail "flag \"A\" not retained"; + } + + if hasflag :comparator "i;ascii-numeric" :count "gt" "2" { + test_fail "hasflag sees more than two flags"; + } + + addflag ["C", "D", "E F"]; + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "6" { + test_fail "hasflag sees more than two flags"; + } + + removeflag ["D"]; + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "5" { + test_fail "hasflag sees more than two flags"; + } + + if hasflag "D" { + test_fail "removed flag still present"; + } + + set "var" "G"; + addflag "${var}"; + + if not hasflag "G" { + test_fail "flag \"G\" not added"; + } + + if not hasflag "A" { + test_fail "flag \"A\" not retained"; + } + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "6" { + test_fail "hasflag sees something other than six flags"; + } +} + +test "Variable flag operations" { + setflag "frop" "A"; + + if not hasflag "frop" "A" { + test_fail "hasflag misses set flag"; + } + + if hasflag :comparator "i;ascii-numeric" :count "gt" "frop" "1" { + test_fail "hasflag sees more than one flag"; + } + + addflag "frop" "B"; + + if not hasflag "frop" "B" { + test_fail "flag \"B\" not added"; + } + + if not hasflag "frop" "A" { + test_fail "flag \"A\" not retained"; + } + + if hasflag :comparator "i;ascii-numeric" :count "gt" "frop" "2" { + test_fail "hasflag sees more than two flags"; + } + + addflag "frop" ["C", "D", "E F"]; + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "frop" "6" { + test_fail "hasflag sees something other than six flags"; + } + + removeflag "frop" ["D"]; + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "frop" "5" { + test_fail "hasflag sees something other than five flags"; + } + + if hasflag "frop" "D" { + test_fail "removed flag still present"; + } + + set "var" "G"; + addflag "frop" "${var}"; + + if not hasflag "frop" "G" { + test_fail "flag \"G\" not added"; + } + + if not hasflag "frop" "A" { + test_fail "flag \"A\" not retained"; + } + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "frop" "6" { + test_fail "hasflag sees something other than six flags"; + } +} + +test "Setflag; string list" { + setflag ["A B", "C D"]; + + if not hasflag "A" { + test_fail "hasflag misses A flag"; + } + + if not hasflag "B" { + test_fail "hasflag misses B flag"; + } + + if not hasflag "C" { + test_fail "hasflag misses C flag"; + } + + if not hasflag "D" { + test_fail "hasflag misses D flag"; + } + + if hasflag :comparator "i;ascii-numeric" :count "ne" "4" { + test_fail "hasflag sees incorrect number of flags"; + } +} + +test "Removal: one" { + setflag "\\seen"; + + if not hasflag "\\seen" { + test_fail "hasflag misses set flag"; + } + + removeflag "\\seen"; + + if hasflag "\\seen" { + test_fail "flag not removed"; + } + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "0" { + test_fail "flags are still set"; + } +} + +test "Removal: first" { + setflag "$frop \\seen"; + + if not allof ( hasflag "\\seen", hasflag "$frop" ) { + test_fail "hasflag misses set flags"; + } + + removeflag "$frop"; + + if not hasflag "\\seen" { + test_fail "wrong flag removed"; + } + + if hasflag "$frop" { + test_fail "flag not removed"; + } + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "1" { + test_fail "more than one flag remains set"; + } +} + +test "Removal: last" { + setflag "\\seen $friep"; + + if not allof ( hasflag "\\seen", hasflag "$friep" ) { + test_fail "hasflag misses set flags"; + } + + removeflag "$friep"; + + if not hasflag "\\seen" { + test_fail "wrong flag removed"; + } + + if hasflag "$friep" { + test_fail "flag not removed"; + } + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "1" { + test_fail "more than one flag remains set"; + } +} + +test "Removal: middle" { + setflag "\\seen $friep \\flagged"; + + if not allof ( hasflag "\\flagged", hasflag "\\seen", hasflag "$friep" ) { + test_fail "hasflag misses set flags"; + } + + removeflag "$friep"; + + if not allof ( hasflag "\\seen", hasflag "\\flagged" ) { + test_fail "wrong flag removed"; + } + + if hasflag "$friep" { + test_fail "flag not removed"; + } + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "2" { + test_fail "more than two flags remain set"; + } +} + +test "Removal: duplicates" { + setflag "\\seen $friep $friep \\flagged $friep"; + + if not allof ( hasflag "\\flagged", hasflag "\\seen", hasflag "$friep" ) { + test_fail "hasflag misses set flags"; + } + + removeflag "$friep"; + + if not allof ( hasflag "\\seen", hasflag "\\flagged" ) { + test_fail "wrong flag removed"; + } + + if hasflag "$friep" { + test_fail "flag not removed"; + } + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "2" { + test_fail "more than two flags remain set"; + } +} + +test "Removal: whitespace" { + setflag " \\seen $friep $friep \\flagged $friep "; + + if not allof ( hasflag "\\flagged", hasflag "\\seen", hasflag "$friep" ) { + test_fail "hasflag misses set flags"; + } + + removeflag "$friep"; + + if not allof ( hasflag "\\seen", hasflag "\\flagged" ) { + test_fail "wrong flag removed"; + } + + if hasflag "$friep" { + test_fail "flag not removed"; + } + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "2" { + test_fail "more than two flags remain set"; + } +} + + + diff --git a/pigeonhole/tests/extensions/imap4flags/execute.svtest b/pigeonhole/tests/extensions/imap4flags/execute.svtest new file mode 100644 index 0000000..1ee1906 --- /dev/null +++ b/pigeonhole/tests/extensions/imap4flags/execute.svtest @@ -0,0 +1,68 @@ +require "vnd.dovecot.testsuite"; +require "imap4flags"; +require "relational"; + + +/* + * Execution testing + */ + +test_mailbox_create "INBOX.Junk"; +test_mailbox_create "INBOX.Nonsense"; + +test "Flags Side Effect" { + if not test_script_compile "execute/flags-side-effect.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script execute failed"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } + + test_result_reset; + + if not test_message :folder "INBOX.Junk" 0 { + test_fail "message not stored in INBOX.Junk"; + } + + if not hasflag :count "eq" "1" { + test_fail "invalid number of flags for message in INBOX.Junk"; + } + + if not hasflag :is "NONSENSE" { + test_fail "invalid flag set for message in INBOX.Junk"; + } + + test_result_reset; + + if not test_message :folder "INBOX" 0 { + test_fail "message not stored in INBOX"; + } + + if not hasflag :count "eq" "1" { + test_fail "invalid number of flags for message in INBOX"; + } + + if not hasflag :is "\\seen" { + test_fail "invalid flag set for message in INBOX"; + } + + test_result_reset; + + if not test_message :folder "INBOX.Nonsense" 0 { + test_fail "message not stored in INBOX.Nonsense"; + } + + if not hasflag :count "eq" "1" { + test_fail "invalid number of flags for message in Inbox.Nonsense"; + } + + if not hasflag :is "IMPLICIT" { + test_fail "invalid flag set for message in Inbox.Nonsene"; + } + +} diff --git a/pigeonhole/tests/extensions/imap4flags/execute/flags-side-effect.sieve b/pigeonhole/tests/extensions/imap4flags/execute/flags-side-effect.sieve new file mode 100644 index 0000000..17de0ad --- /dev/null +++ b/pigeonhole/tests/extensions/imap4flags/execute/flags-side-effect.sieve @@ -0,0 +1,18 @@ +require "imap4flags"; +require "fileinto"; + +/* + * When keep/fileinto is used multiple times in a script and duplicate + * message elimination is performed, the last flag list value MUST win. + */ + +setflag "IMPLICIT"; + +fileinto :flags "\\Seen \\Draft" "INBOX.Junk"; +fileinto :flags "NONSENSE" "INBOX.Junk"; + +keep; +keep :flags "\\Seen"; + +fileinto :flags "\\Seen" "Inbox.Nonsense"; +fileinto "Inbox.Nonsense"; diff --git a/pigeonhole/tests/extensions/imap4flags/flagstore.svtest b/pigeonhole/tests/extensions/imap4flags/flagstore.svtest new file mode 100644 index 0000000..bf11402 --- /dev/null +++ b/pigeonhole/tests/extensions/imap4flags/flagstore.svtest @@ -0,0 +1,146 @@ +require "vnd.dovecot.testsuite"; +require "fileinto"; +require "imap4flags"; +require "relational"; +require "comparator-i;ascii-numeric"; +require "mailbox"; + +test_set "message" text: +From: Henry von Flockenstoffen <henry@example.com> +To: Dieter von Ausburg <dieter@example.com> +Subject: Test message. + +Test message. +. +; + +test "Basic" { + if hasflag :comparator "i;ascii-numeric" :count "ge" "1" { + test_fail "some flags or keywords are already set"; + } + + setflag "$label1 \\answered"; + + fileinto :create "Uninteresting"; + + if not test_result_execute { + test_fail "failed to execute first result"; + } + + test_result_reset; + + setflag "\\draft \\seen Junk"; + + fileinto "Uninteresting"; + + if not test_result_execute { + test_fail "failed to execute second result"; + } + + test_result_reset; + + fileinto :flags "\\flagged" "Uninteresting"; + + if not test_result_execute { + test_fail "failed to execute third result"; + } + + test_result_reset; + + test_message :folder "Uninteresting" 0; + + if not hasflag "$label1 \\answered" { + test_fail "flags not stored for first message"; + } + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "2" { + test_fail "invalid number of flags set for first message"; + } + + test_result_reset; + + test_message :folder "Uninteresting" 1; + + if not hasflag "\\draft \\seen Junk" { + test_fail "flags not stored for second message"; + } + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "3" { + test_fail "invalid number of flags set for second message"; + } + + test_result_reset; + + test_message :folder "Uninteresting" 2; + + if not hasflag "\\flagged" { + test_fail "flags not stored for third message"; + } + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "1" { + test_fail "invalid number of flags set for third message"; + } +} + +test_result_reset; +test_set "message" text: +From: Henry von Flockenstoffen <henry@example.com> +To: Dieter von Ausburg <dieter@example.com> +Subject: Test message. + +Test message. +. +; + +test "Flag changes between stores" { + if hasflag :comparator "i;ascii-numeric" :count "ge" "1" { + test_fail "some flags or keywords are already set"; + } + + setflag "$label1 \\answered"; + fileinto :create "FolderA"; + + setflag "$label2"; + fileinto :create "FolderB"; + + fileinto :create :flags "\\seen \\draft \\flagged" "FolderC"; + + if not test_result_execute { + test_fail "failed to execute first result"; + } + + test_result_reset; + test_message :folder "FolderA" 0; + + if not hasflag "\\answered $label1" { + test_fail "flags not stored for first message"; + } + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "2" { + test_fail "invalid number of flags set for first message"; + } + + test_result_reset; + test_message :folder "FolderB" 0; + + if not hasflag "$label2" { + test_fail "flag not stored for second message"; + } + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "1" { + test_fail "invalid number of flags set for second message"; + } + + test_result_reset; + test_message :folder "FolderC" 0; + + if not hasflag "\\seen \\flagged \\draft" { + test_fail "flags not stored for third message"; + } + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "3" { + test_fail "invalid number of flags set for third message"; + } +} + + diff --git a/pigeonhole/tests/extensions/imap4flags/flagstring.svtest b/pigeonhole/tests/extensions/imap4flags/flagstring.svtest new file mode 100644 index 0000000..23b6b34 --- /dev/null +++ b/pigeonhole/tests/extensions/imap4flags/flagstring.svtest @@ -0,0 +1,82 @@ +require "vnd.dovecot.testsuite"; +require "imap4flags"; +require "variables"; + +test "Duplicates: setflag" { + setflag "flags" "\\seen \\seen"; + + if not string "${flags}" "\\seen" { + test_fail "duplicate \\seen flag item not removed (1)"; + } + + setflag "flags" "\\seen $frop \\seen"; + + if not string "${flags}" "\\seen $frop" { + test_fail "duplicate \\seen flag item not removed (2)"; + } + + setflag "flags" "\\seen $frop $frop \\seen"; + + if not string "${flags}" "\\seen $frop" { + test_fail "duplicate \\seen flag item not removed (3)"; + } + + setflag "flags" "$frop \\seen $frop \\seen"; + + if not string "${flags}" "$frop \\seen" { + test_fail "duplicate \\seen flag item not removed (4)"; + } + + setflag "flags" "$frop \\seen \\seen \\seen \\seen $frop $frop $frop \\seen"; + + if not string "${flags}" "$frop \\seen" { + test_fail "duplicate \\seen flag item not removed (5)"; + } +} + +test "Duplicates: addflag" { + setflag "flags" ""; + addflag "flags" "\\seen \\seen"; + + if not string "${flags}" "\\seen" { + test_fail "duplicate \\seen flag item not removed (1)"; + } + + setflag "flags" ""; + addflag "flags" "\\seen $frop \\seen"; + + if not string "${flags}" "\\seen $frop" { + test_fail "duplicate \\seen flag item not removed (2)"; + } + + setflag "flags" ""; + addflag "flags" "\\seen $frop $frop \\seen"; + + if not string "${flags}" "\\seen $frop" { + test_fail "duplicate \\seen flag item not removed (3)"; + } + + setflag "flags" ""; + addflag "flags" "$frop \\seen $frop \\seen"; + + if not string "${flags}" "$frop \\seen" { + test_fail "duplicate \\seen flag item not removed (4)"; + } + + setflag "flags" ""; + addflag "flags" "$frop \\seen \\seen \\seen \\seen $frop $frop $frop \\seen"; + + if not string "${flags}" "$frop \\seen" { + test_fail "duplicate \\seen flag item not removed (5)"; + } + + setflag "flags" "$frop \\seen"; + addflag "flags" "\\seen \\seen \\seen $frop $frop $frop \\seen"; + + if not string "${flags}" "$frop \\seen" { + test_fail "duplicate \\seen flag item not removed (6)"; + } +} + + + diff --git a/pigeonhole/tests/extensions/imap4flags/hasflag.svtest b/pigeonhole/tests/extensions/imap4flags/hasflag.svtest new file mode 100644 index 0000000..1088190 --- /dev/null +++ b/pigeonhole/tests/extensions/imap4flags/hasflag.svtest @@ -0,0 +1,91 @@ +require "vnd.dovecot.testsuite"; + +require "imap4flags"; +require "relational"; +require "variables"; +require "comparator-i;ascii-numeric"; + +/* + * Generic tests + */ + +test "Ignoring \"\"" { + setflag ""; + + if hasflag "" { + test_fail "hasflag fails to ignore empty string"; + } +} + +/* + * Variables + */ + +test "Multiple variables" { + setflag "A" "Aflag"; + setflag "B" "Bflag"; + setflag "C" "Cflag"; + + if not hasflag ["a", "b", "c"] ["Bflag"] { + test_fail "hasflag failed to match multiple flags variables"; + } +} + +/* + * RFC examples + */ + +test "RFC hasflag example - :is" { + setflag "A B"; + + if not hasflag ["b","A"] { + test_fail "list representation did not match"; + } + + if not hasflag :is "b A" { + test_fail "string representation did not match"; + } +} + +test "RFC hasflag example - :contains variable" { + set "MyVar" "NonJunk Junk gnus-forward $Forwarded NotJunk JunkRecorded $Junk $NotJunk"; + + if not hasflag :contains "MyVar" "Junk" { + test_fail "failed true example 1"; + } + + if not hasflag :contains "MyVar" "forward" { + test_fail "failed true example 2"; + } + + if not hasflag :contains "MyVar" ["label", "forward"] { + test_fail "failed true example 3"; + } + + if not hasflag :contains "MyVar" ["junk", "forward"] { + test_fail "failed true example 4"; + } + + if not hasflag :contains "MyVar" "junk forward" { + test_fail "failed true example 4 (rewrite 1)"; + } + + if not hasflag :contains "MyVar" "forward junk" { + test_fail "failed true example 4 (rewrite 2)"; + } + + if hasflag :contains "MyVar" "label" { + test_fail "failed false example 1"; + } + + if hasflag :contains "MyVar" ["label1", "label2"] { + test_fail "failed false example 2"; + } +} + +test "RFC hasflag example - :count variable" { + set "MyFlags" "A B"; + if not hasflag :count "ge" :comparator "i;ascii-numeric" "MyFlags" "2" { + test_fail "failed count \"ge\" comparison"; + } +} diff --git a/pigeonhole/tests/extensions/imap4flags/multiscript.svtest b/pigeonhole/tests/extensions/imap4flags/multiscript.svtest new file mode 100644 index 0000000..5080eda --- /dev/null +++ b/pigeonhole/tests/extensions/imap4flags/multiscript.svtest @@ -0,0 +1,55 @@ +require "vnd.dovecot.testsuite"; +require "imap4flags"; +require "relational"; +require "comparator-i;ascii-numeric"; +require "mailbox"; +require "fileinto"; + +test "Segfault Trigger 1" { + + if not test_multiscript [ + "multiscript/group-spam.sieve", + "multiscript/spam.sieve", + "multiscript/sent-store.sieve"] + { + test_fail "failed multiscript execution"; + } +} + +test_set "message" text: +From: Henry von Flockenstoffen <henry@example.com> +To: Dieter von Ausburg <dieter@example.com> +Subject: Test message. + +Test message. +. +; + +test "Internal Flags" { + if hasflag :comparator "i;ascii-numeric" :count "ge" "1" { + test_fail "some flags or keywords are already set"; + } + + if not test_multiscript [ + "multiscript/setflag.sieve", + "multiscript/fileinto.sieve"] + { + test_fail "failed multiscript execution"; + } + + test_result_reset; + test_message :folder "folder" 0; + + if not hasflag "\\answered" { + test_fail "\\answered flag not stored for message"; + } + + if not hasflag "$label1" { + test_fail "$label1 keyword not stored for message"; + } + + if not hasflag :comparator "i;ascii-numeric" :count "eq" "2" { + test_fail "invalid number of flags set for message"; + } +} + diff --git a/pigeonhole/tests/extensions/imap4flags/multiscript/fileinto.sieve b/pigeonhole/tests/extensions/imap4flags/multiscript/fileinto.sieve new file mode 100644 index 0000000..94892a5 --- /dev/null +++ b/pigeonhole/tests/extensions/imap4flags/multiscript/fileinto.sieve @@ -0,0 +1,4 @@ +require "fileinto"; +require "mailbox"; + +fileinto :create "folder"; diff --git a/pigeonhole/tests/extensions/imap4flags/multiscript/group-spam.sieve b/pigeonhole/tests/extensions/imap4flags/multiscript/group-spam.sieve new file mode 100644 index 0000000..92ea3b9 --- /dev/null +++ b/pigeonhole/tests/extensions/imap4flags/multiscript/group-spam.sieve @@ -0,0 +1,14 @@ +require ["fileinto", "variables", "envelope"]; + +if header :contains "X-Group-Mail" ["Yes", "YES", "1"] { + if header :contains "X-Spam-Flag" ["Yes", "YES", "1"] { + if envelope :matches :localpart "to" "*" { + fileinto "group/${1}/SPAM"; stop; + } + } + if address :is ["To"] "sales@florist.ru" { + fileinto "group/info/Orders"; + } + stop; +} +keep; diff --git a/pigeonhole/tests/extensions/imap4flags/multiscript/sent-store.sieve b/pigeonhole/tests/extensions/imap4flags/multiscript/sent-store.sieve new file mode 100644 index 0000000..cb21daa --- /dev/null +++ b/pigeonhole/tests/extensions/imap4flags/multiscript/sent-store.sieve @@ -0,0 +1,7 @@ +require ["imap4flags"]; + +if header :contains "X-Set-Seen" ["Yes", "YES", "1"] { + setflag "\\Seen"; +} + +keep; diff --git a/pigeonhole/tests/extensions/imap4flags/multiscript/setflag.sieve b/pigeonhole/tests/extensions/imap4flags/multiscript/setflag.sieve new file mode 100644 index 0000000..c992d19 --- /dev/null +++ b/pigeonhole/tests/extensions/imap4flags/multiscript/setflag.sieve @@ -0,0 +1,3 @@ +require "imap4flags"; + +setflag "$label1 \\answered"; diff --git a/pigeonhole/tests/extensions/imap4flags/multiscript/spam.sieve b/pigeonhole/tests/extensions/imap4flags/multiscript/spam.sieve new file mode 100644 index 0000000..9e1b6c3 --- /dev/null +++ b/pigeonhole/tests/extensions/imap4flags/multiscript/spam.sieve @@ -0,0 +1,8 @@ +require ["fileinto"]; + +if header :contains "X-Spam-Flag" ["Yes", "YES", "1"] { + fileinto "SPAM"; +} +keep; + + diff --git a/pigeonhole/tests/extensions/include/errors.svtest b/pigeonhole/tests/extensions/include/errors.svtest new file mode 100644 index 0000000..6f8b1cc --- /dev/null +++ b/pigeonhole/tests/extensions/include/errors.svtest @@ -0,0 +1,149 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +/* + * Generic include errors + */ + +test "Generic" { + if test_script_compile "errors/generic.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "wrong number of errors reported"; + } +} + +test "Circular - direct" { + if test_script_compile "errors/circular-1.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "wrong number of errors reported"; + } +} + +test "Circular - one intermittent" { + if test_script_compile "errors/circular-2.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "4" { + test_fail "wrong number of errors reported"; + } +} + +test "Circular - two intermittent" { + if test_script_compile "errors/circular-3.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "5" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Using global without variables required + */ + +test "Variables inactive" { + if test_script_compile "errors/variables-inactive.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Generic variables errors + */ + +test "Variables" { + if test_script_compile "errors/variables.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "3" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Global variable namespace + */ + +test "Global Namespace" { + if test_script_compile "errors/global-namespace.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "4" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Invalid script names + */ + +test "Invalid Script Names" { + if test_script_compile "errors/scriptname.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "8" { + test_fail "wrong number of errors reported"; + } +} + +/* Include limit */ + +test "Include limit" { + test_config_set "sieve_include_max_includes" "3"; + test_config_reload :extension "include"; + + if test_script_compile "errors/include-limit.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "2" { + test_fail "wrong number of errors reported"; + } + + test_config_set "sieve_include_max_includes" "255"; + test_config_reload :extension "include"; + + if not test_script_compile "errors/include-limit.sieve" { + test_fail "compile should have succeeded"; + } +} + +/* Depth limit */ + +test "Depth limit" { + test_config_set "sieve_include_max_nesting_depth" "2"; + test_config_reload :extension "include"; + + if test_script_compile "errors/depth-limit.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "4" { + test_fail "wrong number of errors reported"; + } + + test_config_set "sieve_include_max_nesting_depth" "10"; + test_config_reload :extension "include"; + + if not test_script_compile "errors/depth-limit.sieve" { + test_fail "compile should have succeeded"; + } +} + diff --git a/pigeonhole/tests/extensions/include/errors/action-conflicts.sieve b/pigeonhole/tests/extensions/include/errors/action-conflicts.sieve new file mode 100644 index 0000000..ddeb42c --- /dev/null +++ b/pigeonhole/tests/extensions/include/errors/action-conflicts.sieve @@ -0,0 +1,4 @@ +require "include"; + +include "action-fileinto"; +include "action-reject"; diff --git a/pigeonhole/tests/extensions/include/errors/circular-1.sieve b/pigeonhole/tests/extensions/include/errors/circular-1.sieve new file mode 100644 index 0000000..22b6f87 --- /dev/null +++ b/pigeonhole/tests/extensions/include/errors/circular-1.sieve @@ -0,0 +1,5 @@ +require "include"; + +discard; + +include "circular-one"; diff --git a/pigeonhole/tests/extensions/include/errors/circular-2.sieve b/pigeonhole/tests/extensions/include/errors/circular-2.sieve new file mode 100644 index 0000000..0cfa375 --- /dev/null +++ b/pigeonhole/tests/extensions/include/errors/circular-2.sieve @@ -0,0 +1,5 @@ +require "include"; + +discard; + +include "circular-two"; diff --git a/pigeonhole/tests/extensions/include/errors/circular-3.sieve b/pigeonhole/tests/extensions/include/errors/circular-3.sieve new file mode 100644 index 0000000..1ad95b6 --- /dev/null +++ b/pigeonhole/tests/extensions/include/errors/circular-3.sieve @@ -0,0 +1,5 @@ +require "include"; + +discard; + +include "circular-three"; diff --git a/pigeonhole/tests/extensions/include/errors/depth-limit.sieve b/pigeonhole/tests/extensions/include/errors/depth-limit.sieve new file mode 100644 index 0000000..93291b6 --- /dev/null +++ b/pigeonhole/tests/extensions/include/errors/depth-limit.sieve @@ -0,0 +1,3 @@ +require "include"; + +include :personal "depth-limit-1"; diff --git a/pigeonhole/tests/extensions/include/errors/generic.sieve b/pigeonhole/tests/extensions/include/errors/generic.sieve new file mode 100644 index 0000000..66eba18 --- /dev/null +++ b/pigeonhole/tests/extensions/include/errors/generic.sieve @@ -0,0 +1,7 @@ +require "include"; + +# Non-existent sieve script +include "frop.sieve"; + +# Use of / in script names +include "../frop.sieve"; diff --git a/pigeonhole/tests/extensions/include/errors/global-namespace.sieve b/pigeonhole/tests/extensions/include/errors/global-namespace.sieve new file mode 100644 index 0000000..3827b60 --- /dev/null +++ b/pigeonhole/tests/extensions/include/errors/global-namespace.sieve @@ -0,0 +1,13 @@ +require "variables"; +require "include"; + +# Invalid namespace +set "globl.var" "frop"; + +# Sub-namespace +set "global.env.0" "12"; + +# Invalid variable name +set "global.12" "porf"; + + diff --git a/pigeonhole/tests/extensions/include/errors/include-limit.sieve b/pigeonhole/tests/extensions/include/errors/include-limit.sieve new file mode 100644 index 0000000..f6689dd --- /dev/null +++ b/pigeonhole/tests/extensions/include/errors/include-limit.sieve @@ -0,0 +1,6 @@ +require "include"; + +include "rfc-ex1-always_allow"; +include "rfc-ex2-spam_filter_script"; +include "rfc-ex1-mailing_lists"; +include "rfc-ex1-spam_tests"; diff --git a/pigeonhole/tests/extensions/include/errors/scriptname.sieve b/pigeonhole/tests/extensions/include/errors/scriptname.sieve new file mode 100644 index 0000000..9a10c3d --- /dev/null +++ b/pigeonhole/tests/extensions/include/errors/scriptname.sieve @@ -0,0 +1,25 @@ +require "variables"; +require "include"; +require "encoded-character"; + +# Slash +include "../frop"; + +# More slashes +include "../../james/sieve/vacation"; + +# 0000-001F; [CONTROL CHARACTERS] +include "idiotic${unicode: 001a}"; + +# 007F; DELETE +include "idiotic${unicode: 007f}"; + +# 0080-009F; [CONTROL CHARACTERS] +include "idiotic${unicode: 0085}"; + +# 2028; LINE SEPARATOR +include "idiotic${unicode: 2028}"; + +# 2029; PARAGRAPH SEPARATOR +include "idiotic${unicode: 2029}"; + diff --git a/pigeonhole/tests/extensions/include/errors/variables-inactive.sieve b/pigeonhole/tests/extensions/include/errors/variables-inactive.sieve new file mode 100644 index 0000000..06e0df1 --- /dev/null +++ b/pigeonhole/tests/extensions/include/errors/variables-inactive.sieve @@ -0,0 +1,7 @@ +require "include"; +require "fileinto"; + +global "friep"; +global "frop"; + +fileinto "Frop"; diff --git a/pigeonhole/tests/extensions/include/errors/variables.sieve b/pigeonhole/tests/extensions/include/errors/variables.sieve new file mode 100644 index 0000000..eac99f8 --- /dev/null +++ b/pigeonhole/tests/extensions/include/errors/variables.sieve @@ -0,0 +1,23 @@ +require "include"; +require "variables"; + +# Duplicate global declaration (not an error) +global "frml"; +global "frml"; + +keep; + +# Global after command not being require or global (not an error) +global "friep"; + +# DEPRECATED: import/export after command not being require or import/export +export "friep"; +import "friep"; + +# Marking local variable as global +set "frutsels" "frop"; +global "frutsels"; +set "frutsels" "frop"; + + + diff --git a/pigeonhole/tests/extensions/include/execute.svtest b/pigeonhole/tests/extensions/include/execute.svtest new file mode 100644 index 0000000..734ac66 --- /dev/null +++ b/pigeonhole/tests/extensions/include/execute.svtest @@ -0,0 +1,68 @@ +require "vnd.dovecot.testsuite"; +require "include"; +require "variables"; + +test_set "message" text: +From: idiot@example.com +To: idiot@example.org +Subject: Frop! + +Frop. +. +; + +test "Actions Fileinto" { + test_mailbox_create "aaaa"; + test_mailbox_create "bbbb"; + + if not test_script_compile "execute/actions-fileinto.sieve" { + test_fail "failed to compile sieve script"; + } + + test_binary_save "actions-fileinto"; + test_binary_load "actions-fileinto"; + + if not test_script_run { + test_fail "failed to execute sieve script"; + } + + if not test_result_execute { + test_fail "failed to execute result"; + } + + test_message :folder "aaaa" 0; + + if not header "subject" "Frop!" { + test_fail "fileinto \"aaaa\" not executed."; + } + + test_message :folder "bbbb" 0; + + if not header "subject" "Frop!" { + test_fail "fileinto \"bbbb\" not executed."; + } +} + +test "Namespace - file" { + if not test_script_compile "execute/namespace.sieve" { + test_fail "failed to compile sub-test"; + } + + if not test_script_run { + test_fail "failed to execute sub-test"; + } +} + +test "Namespace - dict" { + test_config_set "sieve" "dict:file:${tst.path}/included/namespace.dict"; + test_config_set "sieve_global" "dict:file:${tst.path}/included-global/namespace.dict"; + test_config_reload :extension "include"; + + if not test_script_compile "execute/namespace.sieve" { + test_fail "failed to compile sub-test"; + } + + if not test_script_run { + test_fail "failed to execute sub-test"; + } +} diff --git a/pigeonhole/tests/extensions/include/execute/actions-fileinto.sieve b/pigeonhole/tests/extensions/include/execute/actions-fileinto.sieve new file mode 100644 index 0000000..b0b8157 --- /dev/null +++ b/pigeonhole/tests/extensions/include/execute/actions-fileinto.sieve @@ -0,0 +1,5 @@ +require "include"; + +include "actions-fileinto1"; +include "actions-fileinto2"; +include "actions-fileinto3"; diff --git a/pigeonhole/tests/extensions/include/execute/namespace.sieve b/pigeonhole/tests/extensions/include/execute/namespace.sieve new file mode 100644 index 0000000..cbe41a2 --- /dev/null +++ b/pigeonhole/tests/extensions/include/execute/namespace.sieve @@ -0,0 +1,26 @@ +require "vnd.dovecot.testsuite"; +require "include"; +require "variables"; + +set "global.a" "none"; +include :personal "namespace"; + +if string "${global.a}" "none" { + test_fail "personal script not executed"; +} + +if not string "${global.a}" "personal" { + test_fail "executed global instead of personal script: ${global.a}"; +} + +set "global.a" "none"; +include :global "namespace"; + +if string "{global.a}" "none" { + test_fail "global script not executed"; +} + +if not string "${global.a}" "global" { + test_fail "executed personal instead of global script: ${global.a}"; +} + diff --git a/pigeonhole/tests/extensions/include/execute/optional.sieve b/pigeonhole/tests/extensions/include/execute/optional.sieve new file mode 100644 index 0000000..a6ad479 --- /dev/null +++ b/pigeonhole/tests/extensions/include/execute/optional.sieve @@ -0,0 +1,5 @@ +require "include"; + +include :optional "optional-1"; +include :optional "optional-2"; +include :optional "optional-3"; diff --git a/pigeonhole/tests/extensions/include/included-global/namespace.dict b/pigeonhole/tests/extensions/include/included-global/namespace.dict new file mode 100644 index 0000000..8f52fd3 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included-global/namespace.dict @@ -0,0 +1,4 @@ +priv/sieve/name/namespace +1 +priv/sieve/data/1 +require ["variables", "include"]; set "global.a" "global"; diff --git a/pigeonhole/tests/extensions/include/included-global/namespace.sieve b/pigeonhole/tests/extensions/include/included-global/namespace.sieve new file mode 100644 index 0000000..d11c2f1 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included-global/namespace.sieve @@ -0,0 +1,4 @@ +require "include"; +require "variables"; + +set "global.a" "global"; diff --git a/pigeonhole/tests/extensions/include/included-global/rfc-ex1-spam_tests.sieve b/pigeonhole/tests/extensions/include/included-global/rfc-ex1-spam_tests.sieve new file mode 100644 index 0000000..340ceaf --- /dev/null +++ b/pigeonhole/tests/extensions/include/included-global/rfc-ex1-spam_tests.sieve @@ -0,0 +1,7 @@ +require ["reject"]; + +if anyof (header :contains "Subject" "$$", + header :contains "Subject" "Make money") +{ + reject "Not wanted"; +} diff --git a/pigeonhole/tests/extensions/include/included/action-fileinto.sieve b/pigeonhole/tests/extensions/include/included/action-fileinto.sieve new file mode 100644 index 0000000..9aafb95 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/action-fileinto.sieve @@ -0,0 +1,3 @@ +require "fileinto"; + +fileinto "frop"; diff --git a/pigeonhole/tests/extensions/include/included/action-reject.sieve b/pigeonhole/tests/extensions/include/included/action-reject.sieve new file mode 100644 index 0000000..6e7b0b0 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/action-reject.sieve @@ -0,0 +1,3 @@ +require "reject"; + +reject "Ik heb geen zin in die rommel."; diff --git a/pigeonhole/tests/extensions/include/included/actions-fileinto1.sieve b/pigeonhole/tests/extensions/include/included/actions-fileinto1.sieve new file mode 100644 index 0000000..d4c5031 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/actions-fileinto1.sieve @@ -0,0 +1,3 @@ +require "fileinto"; + +fileinto "aaaa"; diff --git a/pigeonhole/tests/extensions/include/included/actions-fileinto2.sieve b/pigeonhole/tests/extensions/include/included/actions-fileinto2.sieve new file mode 100644 index 0000000..f73da0d --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/actions-fileinto2.sieve @@ -0,0 +1,4 @@ +require "fileinto"; + +fileinto "bbbb"; + diff --git a/pigeonhole/tests/extensions/include/included/actions-fileinto3.sieve b/pigeonhole/tests/extensions/include/included/actions-fileinto3.sieve new file mode 100644 index 0000000..d4c5031 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/actions-fileinto3.sieve @@ -0,0 +1,3 @@ +require "fileinto"; + +fileinto "aaaa"; diff --git a/pigeonhole/tests/extensions/include/included/circular-one.sieve b/pigeonhole/tests/extensions/include/included/circular-one.sieve new file mode 100644 index 0000000..2d60606 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/circular-one.sieve @@ -0,0 +1,5 @@ +require "include"; + +keep; + +include "circular-one"; diff --git a/pigeonhole/tests/extensions/include/included/circular-three-2.sieve b/pigeonhole/tests/extensions/include/included/circular-three-2.sieve new file mode 100644 index 0000000..5199f21 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/circular-three-2.sieve @@ -0,0 +1,3 @@ +require "include"; + +include "circular-three-3"; diff --git a/pigeonhole/tests/extensions/include/included/circular-three-3.sieve b/pigeonhole/tests/extensions/include/included/circular-three-3.sieve new file mode 100644 index 0000000..4c062cd --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/circular-three-3.sieve @@ -0,0 +1,3 @@ +require "include"; + +include "circular-three.sieve"; diff --git a/pigeonhole/tests/extensions/include/included/circular-three.sieve b/pigeonhole/tests/extensions/include/included/circular-three.sieve new file mode 100644 index 0000000..13be546 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/circular-three.sieve @@ -0,0 +1,7 @@ +require "include"; + +keep; + +include "circular-three-2"; + + diff --git a/pigeonhole/tests/extensions/include/included/circular-two-2.sieve b/pigeonhole/tests/extensions/include/included/circular-two-2.sieve new file mode 100644 index 0000000..d529214 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/circular-two-2.sieve @@ -0,0 +1,3 @@ +require "include"; + +include "circular-two.sieve"; diff --git a/pigeonhole/tests/extensions/include/included/circular-two.sieve b/pigeonhole/tests/extensions/include/included/circular-two.sieve new file mode 100644 index 0000000..8a879cb --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/circular-two.sieve @@ -0,0 +1,7 @@ +require "include"; + +keep; + +include "circular-two-2"; + + diff --git a/pigeonhole/tests/extensions/include/included/depth-limit-1.sieve b/pigeonhole/tests/extensions/include/included/depth-limit-1.sieve new file mode 100644 index 0000000..ce5571f --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/depth-limit-1.sieve @@ -0,0 +1,3 @@ +require "include"; + +include :personal "depth-limit-2"; diff --git a/pigeonhole/tests/extensions/include/included/depth-limit-2.sieve b/pigeonhole/tests/extensions/include/included/depth-limit-2.sieve new file mode 100644 index 0000000..79c55e0 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/depth-limit-2.sieve @@ -0,0 +1,3 @@ +require "include"; + +include :personal "depth-limit-3"; diff --git a/pigeonhole/tests/extensions/include/included/depth-limit-3.sieve b/pigeonhole/tests/extensions/include/included/depth-limit-3.sieve new file mode 100644 index 0000000..6203a21 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/depth-limit-3.sieve @@ -0,0 +1 @@ +keep; diff --git a/pigeonhole/tests/extensions/include/included/namespace.dict b/pigeonhole/tests/extensions/include/included/namespace.dict new file mode 100644 index 0000000..35d7aaa --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/namespace.dict @@ -0,0 +1,4 @@ +priv/sieve/name/namespace +1 +priv/sieve/data/1 +require ["variables", "include"]; set "global.a" "personal"; diff --git a/pigeonhole/tests/extensions/include/included/namespace.sieve b/pigeonhole/tests/extensions/include/included/namespace.sieve new file mode 100644 index 0000000..3f5738f --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/namespace.sieve @@ -0,0 +1,4 @@ +require "include"; +require "variables"; + +set "global.a" "personal"; diff --git a/pigeonhole/tests/extensions/include/included/once-1.sieve b/pigeonhole/tests/extensions/include/included/once-1.sieve new file mode 100644 index 0000000..288d141 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/once-1.sieve @@ -0,0 +1,9 @@ +require "include"; +require "variables"; + +global "result"; + +set "result" "${result} ONE"; + +return; + diff --git a/pigeonhole/tests/extensions/include/included/once-2.sieve b/pigeonhole/tests/extensions/include/included/once-2.sieve new file mode 100644 index 0000000..abf29e5 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/once-2.sieve @@ -0,0 +1,12 @@ +require "include"; +require "variables"; + +global "result"; + +set "result" "${result} TWO"; + +keep; + +include :once "once-1"; + +return; diff --git a/pigeonhole/tests/extensions/include/included/once-3.sieve b/pigeonhole/tests/extensions/include/included/once-3.sieve new file mode 100644 index 0000000..739651e --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/once-3.sieve @@ -0,0 +1,3 @@ +require "include"; + +include "once-4"; diff --git a/pigeonhole/tests/extensions/include/included/once-4.sieve b/pigeonhole/tests/extensions/include/included/once-4.sieve new file mode 100644 index 0000000..9cc1a47 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/once-4.sieve @@ -0,0 +1,3 @@ +require "include"; + +include :once "once-3"; diff --git a/pigeonhole/tests/extensions/include/included/optional-1.sieve b/pigeonhole/tests/extensions/include/included/optional-1.sieve new file mode 100644 index 0000000..288d141 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/optional-1.sieve @@ -0,0 +1,9 @@ +require "include"; +require "variables"; + +global "result"; + +set "result" "${result} ONE"; + +return; + diff --git a/pigeonhole/tests/extensions/include/included/optional-2.sieve b/pigeonhole/tests/extensions/include/included/optional-2.sieve new file mode 100644 index 0000000..11920f5 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/optional-2.sieve @@ -0,0 +1,9 @@ +require "include"; +require "variables"; + +global "result"; + +set "result" "${result} TWO"; + +keep; + diff --git a/pigeonhole/tests/extensions/include/included/rfc-ex1-always_allow.sieve b/pigeonhole/tests/extensions/include/included/rfc-ex1-always_allow.sieve new file mode 100644 index 0000000..6dc8ddc --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/rfc-ex1-always_allow.sieve @@ -0,0 +1,8 @@ +if header :is "From" "boss@example.com" +{ + keep; +} +elsif header :is "From" "ceo@example.com" +{ + keep; +} diff --git a/pigeonhole/tests/extensions/include/included/rfc-ex1-mailing_lists.sieve b/pigeonhole/tests/extensions/include/included/rfc-ex1-mailing_lists.sieve new file mode 100644 index 0000000..d020972 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/rfc-ex1-mailing_lists.sieve @@ -0,0 +1,10 @@ +require ["fileinto"]; + +if header :is "Sender" "owner-ietf-mta-filters@imc.example.com" +{ + fileinto "lists.sieve"; +} +elsif header :is "Sender" "owner-ietf-imapext@imc.example.com" +{ + fileinto "lists.imapext"; +} diff --git a/pigeonhole/tests/extensions/include/included/rfc-ex1-spam_tests.sieve b/pigeonhole/tests/extensions/include/included/rfc-ex1-spam_tests.sieve new file mode 100644 index 0000000..7916064 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/rfc-ex1-spam_tests.sieve @@ -0,0 +1,10 @@ +require ["reject"]; + +if header :contains "Subject" "XXXX" +{ + reject "Not wanted"; +} +elsif header :is "From" "money@example.com" +{ + reject "Not wanted"; +} diff --git a/pigeonhole/tests/extensions/include/included/rfc-ex2-spam_filter_script.sieve b/pigeonhole/tests/extensions/include/included/rfc-ex2-spam_filter_script.sieve new file mode 100644 index 0000000..01ab984 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/rfc-ex2-spam_filter_script.sieve @@ -0,0 +1,8 @@ +require ["variables", "include"]; +global ["test", "test_mailbox"]; + +if header :contains "Subject" "${test}" +{ + set "test_mailbox" "spam-${test}"; +} + diff --git a/pigeonhole/tests/extensions/include/included/twice-1.sieve b/pigeonhole/tests/extensions/include/included/twice-1.sieve new file mode 100644 index 0000000..a770a3b --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/twice-1.sieve @@ -0,0 +1,7 @@ +require "include"; +require "variables"; + +global "result"; + +set "result" "${result} TWO"; + diff --git a/pigeonhole/tests/extensions/include/included/twice-2.sieve b/pigeonhole/tests/extensions/include/included/twice-2.sieve new file mode 100644 index 0000000..eff9429 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/twice-2.sieve @@ -0,0 +1,8 @@ +require "include"; +require "variables"; + +global "result"; + +set "result" "${result} THREE"; + +include "twice-1"; diff --git a/pigeonhole/tests/extensions/include/included/variables-included1.sieve b/pigeonhole/tests/extensions/include/included/variables-included1.sieve new file mode 100644 index 0000000..5f6cb2f --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/variables-included1.sieve @@ -0,0 +1,7 @@ +require "include"; +require "variables"; + +global ["value1"]; +global ["result1"]; + +set "result1" "${value1} ${global.value2}"; diff --git a/pigeonhole/tests/extensions/include/included/variables-included2.sieve b/pigeonhole/tests/extensions/include/included/variables-included2.sieve new file mode 100644 index 0000000..135e03b --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/variables-included2.sieve @@ -0,0 +1,6 @@ +require "include"; +require "variables"; + +global ["value3", "value4"]; + +set "global.result2" "${value3} ${value4}"; diff --git a/pigeonhole/tests/extensions/include/included/variables-included3.sieve b/pigeonhole/tests/extensions/include/included/variables-included3.sieve new file mode 100644 index 0000000..51bb786 --- /dev/null +++ b/pigeonhole/tests/extensions/include/included/variables-included3.sieve @@ -0,0 +1,8 @@ +require "include"; +require "variables"; + +global "result1"; +global "result2"; +global "result"; + +set "result" "${result1} ${result2}"; diff --git a/pigeonhole/tests/extensions/include/once.svtest b/pigeonhole/tests/extensions/include/once.svtest new file mode 100644 index 0000000..3395c6b --- /dev/null +++ b/pigeonhole/tests/extensions/include/once.svtest @@ -0,0 +1,24 @@ +require "vnd.dovecot.testsuite"; +require "include"; +require "variables"; + +global "result"; + +set "result" ""; + +test "Included Once" { + include "once-1"; + include "once-2"; + + if string "${result}" " ONE TWO ONE" { + test_fail "duplicate included :once script"; + } + + if not string "${result}" " ONE TWO" { + test_fail "unexpected result value: ${result}"; + } +} + +test "Included Once recursive" { + include "once-3"; +} diff --git a/pigeonhole/tests/extensions/include/optional.svtest b/pigeonhole/tests/extensions/include/optional.svtest new file mode 100644 index 0000000..345f830 --- /dev/null +++ b/pigeonhole/tests/extensions/include/optional.svtest @@ -0,0 +1,40 @@ +require "vnd.dovecot.testsuite"; +require "include"; +require "variables"; + +global "result"; +set "result" ""; + +test "Included Optional" { + include :optional "optional-1"; + include :optional "optional-2"; + + if not string "${result}" " ONE TWO" { + test_fail "unexpected result value: ${result}"; + } + + # missing + include :optional "optional-3"; + + if not string "${result}" " ONE TWO" { + test_fail "unexpected result value after missing script: ${result}"; + } +} + + +test "Included Optional - Binary" { + if not test_script_compile "execute/optional.sieve" { + test_fail "failed to compile sieve script"; + } + + test_binary_save "optional"; + test_binary_load "optional"; + + if not test_script_run { + test_fail "failed to execute sieve script"; + } + + if not string "${result}" " ONE TWO" { + test_fail "unexpected result value: ${result}"; + } +} diff --git a/pigeonhole/tests/extensions/include/rfc-ex1-default.sieve b/pigeonhole/tests/extensions/include/rfc-ex1-default.sieve new file mode 100644 index 0000000..5a8cb52 --- /dev/null +++ b/pigeonhole/tests/extensions/include/rfc-ex1-default.sieve @@ -0,0 +1,6 @@ +require ["include"]; + +include :personal "rfc-ex1-always_allow"; +include :global "rfc-ex1-spam_tests"; +include :personal "rfc-ex1-spam_tests"; +include :personal "rfc-ex1-mailing_lists"; diff --git a/pigeonhole/tests/extensions/include/rfc-ex2-default.sieve b/pigeonhole/tests/extensions/include/rfc-ex2-default.sieve new file mode 100644 index 0000000..8b1bf4d --- /dev/null +++ b/pigeonhole/tests/extensions/include/rfc-ex2-default.sieve @@ -0,0 +1,21 @@ +require ["variables", "include", "relational", "fileinto"]; +global "test"; +global "test_mailbox"; + +# The included script may contain repetitive code that is +# effectively a subroutine that can be factored out. +set "test" "$$"; +include "rfc-ex2-spam_filter_script"; + +set "test" "Make money"; +include "rfc-ex2-spam_filter_script"; + +# Message will be filed according to the test that matched last. +if string :count "eq" "${test_mailbox}" "1" +{ + fileinto "INBOX${test_mailbox}"; + stop; +} + +# If nothing matched, the message is implicitly kept. + diff --git a/pigeonhole/tests/extensions/include/rfc.svtest b/pigeonhole/tests/extensions/include/rfc.svtest new file mode 100644 index 0000000..00908ac --- /dev/null +++ b/pigeonhole/tests/extensions/include/rfc.svtest @@ -0,0 +1,13 @@ +require "vnd.dovecot.testsuite"; + +test "RFC example 1" { + if not test_script_compile "rfc-ex1-default.sieve" { + test_fail "failed to compile sieve script"; + } +} + +test "RFC example 2" { + if not test_script_compile "rfc-ex2-default.sieve" { + test_fail "failed to compile sieve script"; + } +} diff --git a/pigeonhole/tests/extensions/include/twice.svtest b/pigeonhole/tests/extensions/include/twice.svtest new file mode 100644 index 0000000..5cd5da2 --- /dev/null +++ b/pigeonhole/tests/extensions/include/twice.svtest @@ -0,0 +1,20 @@ +require "vnd.dovecot.testsuite"; +require "include"; +require "variables"; + +global "result"; + +set "result" "ONE"; + +test "Twice included" { + include "twice-1"; + include "twice-2"; + + if string "${result}" "ONE TWO THREE" { + test_fail "duplicate include failed"; + } + + if not string "${result}" "ONE TWO THREE TWO" { + test_fail "unexpected result: ${result}"; + } +} diff --git a/pigeonhole/tests/extensions/include/variables.svtest b/pigeonhole/tests/extensions/include/variables.svtest new file mode 100644 index 0000000..5c4f8d8 --- /dev/null +++ b/pigeonhole/tests/extensions/include/variables.svtest @@ -0,0 +1,29 @@ +require "vnd.dovecot.testsuite"; + +require "include"; +require "variables"; + +global ["value1", "value2"]; +set "value1" "Works"; +set "value2" "fine."; + +global ["value3", "value4"]; +set "value3" "Yeah"; +set "value4" "it does."; + +include "variables-included1"; +include "variables-included2"; +include "variables-included3"; + +global "result"; + +test "Basic" { + if not string :is "${result}" "Works fine. Yeah it does." { + test_fail "invalid result: ${result}"; + } + + if string :is "${result}" "nonsense" { + test_fail "string test succeeds inappropriately"; + } +} + diff --git a/pigeonhole/tests/extensions/index/basic.svtest b/pigeonhole/tests/extensions/index/basic.svtest new file mode 100644 index 0000000..0706022 --- /dev/null +++ b/pigeonhole/tests/extensions/index/basic.svtest @@ -0,0 +1,93 @@ +require "vnd.dovecot.testsuite"; +require "index"; +require "date"; +require "variables"; +require "subaddress"; + +test_set "message" text: +To: first@friep.example.com +X-A: First +Received: from mx.example.com (127.0.0.13) by mx.example.org + (127.0.0.12) with Macrosoft SMTP Server (TLS) id 1.2.3.4; + Wed, 12 Nov 2014 18:18:31 +0100 +To: second@friep.example.com +From: stephan@example.org +Received: from mx.example.com (127.0.0.13) by mx.example.org + (127.0.0.12) with Macrosoft SMTP Server (TLS) id 1.2.3.4; + Wed, 12 Nov 2014 18:18:30 +0100 +X-A: Second +To: third@friep.example.com +X-A: Third +Received: from mx.example.com (127.0.0.13) by mx.example.org + (127.0.0.12) with Macrosoft SMTP Server (TLS) id 1.2.3.4; + Wed, 12 Nov 2014 18:18:29 +0100 +Subject: Frop! +X-A: Fourth +To: fourth@friep.example.com +Received: from mx.example.com (127.0.0.13) by mx.example.org + (127.0.0.12) with Macrosoft SMTP Server (TLS) id 1.2.3.4; + Wed, 12 Nov 2014 18:18:28 +0100 + +Frop +. +; + +test "Header :index" { + if not header :index 3 "x-a" "Third" { + test_fail "wrong header retrieved"; + } + + if header :index 3 "x-a" ["First", "Second", "Fourth"] { + test_fail "other header retrieved"; + } +} + +test "Header :index :last" { + if not header :index 3 :last "x-a" "Second" { + test_fail "wrong header retrieved"; + } + + if header :index 3 :last "x-a" ["First", "Third", "Fourth"] { + test_fail "other header retrieved"; + } +} + +test "Address :index" { + if not address :localpart :index 2 "to" "second" { + test_fail "wrong header retrieved"; + } + + if address :localpart :index 2 "to" ["first", "third", "fourth"] { + test_fail "other header retrieved"; + } +} + +test "Address :index :last" { + if not address :localpart :index 2 :last "to" "third" { + test_fail "wrong header retrieved"; + } + + if address :localpart :index 2 :last "to" ["first", "second", "fourth"] { + test_fail "other header retrieved"; + } +} + +test "Date :index" { + if not date :index 1 "received" "second" "31" { + test_fail "wrong header retrieved"; + } + + if date :index 1 "received" "second" ["30", "29", "28"] { + test_fail "other header retrieved"; + } +} + +test "Date :index :last" { + if not date :index 1 :last "received" "second" "28"{ + test_fail "wrong header retrieved"; + } + + if date :index 1 :last "received" "second" ["31", "30", "29"] { + test_fail "other header retrieved"; + } +} diff --git a/pigeonhole/tests/extensions/index/errors.svtest b/pigeonhole/tests/extensions/index/errors.svtest new file mode 100644 index 0000000..4bfe2dc --- /dev/null +++ b/pigeonhole/tests/extensions/index/errors.svtest @@ -0,0 +1,20 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +/* + * Invalid syntax + */ + +test "Invalid Syntax" { + if test_script_compile "errors/syntax.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "7" { + test_fail "wrong number of errors reported"; + } +} + + diff --git a/pigeonhole/tests/extensions/index/errors/syntax.sieve b/pigeonhole/tests/extensions/index/errors/syntax.sieve new file mode 100644 index 0000000..ee19d88 --- /dev/null +++ b/pigeonhole/tests/extensions/index/errors/syntax.sieve @@ -0,0 +1,26 @@ +require "date"; +require "index"; + +# Not an error +if header :last :index 2 "to" "ok" { } + +# Not an error +if header :index 444 :last "to" "ok" { } + +# 1: missing argument +if header :index "to" "ok" {} + +# 2: missing argument +if header :index :last "to" "ok" {} + +# 3: erroneous string argument +if header :index "frop" "to" "ok" {} + +# 4: last without index +if header :last "to" "ok" {} + +# 5: index 0 +if header :index 0 "to" "ok" {} + +# 6: index 0 last +if header :index 0 :last "to" "ok" {} diff --git a/pigeonhole/tests/extensions/mailbox/errors.svtest b/pigeonhole/tests/extensions/mailbox/errors.svtest new file mode 100644 index 0000000..0821f52 --- /dev/null +++ b/pigeonhole/tests/extensions/mailbox/errors.svtest @@ -0,0 +1,40 @@ +require "vnd.dovecot.testsuite"; +require "variables"; +require "vnd.dovecot.debug"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +/* + * Invalid syntax + */ + +test "Invalid Syntax" { + if test_script_compile "errors/syntax.sieve" { + test_fail "compile should have failed"; + } + + # FIXME: check warnings + if not test_error :count "eq" :comparator "i;ascii-numeric" "12" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Mailboxexists - bad UTF-8 in mailbox name + */ + +test "Mailboxexists - bad UTF-8 in mailbox name" { + if not test_script_compile "errors/mailboxexists-bad-utf8.sieve" { + test_fail "compile failed"; + } + + if not test_script_run { + test_fail "execution failed"; + } + + # FIXME: check warnings + if not test_error :count "eq" :comparator "i;ascii-numeric" "0" { + test_fail "wrong number of runtime errors reported"; + } +} diff --git a/pigeonhole/tests/extensions/mailbox/errors/mailboxexists-bad-utf8.sieve b/pigeonhole/tests/extensions/mailbox/errors/mailboxexists-bad-utf8.sieve new file mode 100644 index 0000000..e68e00e --- /dev/null +++ b/pigeonhole/tests/extensions/mailbox/errors/mailboxexists-bad-utf8.sieve @@ -0,0 +1,9 @@ +require "mailbox"; +require "variables"; +require "encoded-character"; + +set "mailbox" "${hex:ff}rop"; +if mailboxexists "${mailbox}" { + keep; +} + diff --git a/pigeonhole/tests/extensions/mailbox/errors/syntax.sieve b/pigeonhole/tests/extensions/mailbox/errors/syntax.sieve new file mode 100644 index 0000000..727a6e8 --- /dev/null +++ b/pigeonhole/tests/extensions/mailbox/errors/syntax.sieve @@ -0,0 +1,41 @@ +require "mailbox"; +require "fileinto"; +require "encoded-character"; + +# 1 +if mailboxexists {} +# 2 +if mailboxexists 3423 {} +# 3 +if mailboxexists :frop {} +# 4 +if mailboxexists 24234 "\\Sent" {} +# 5 +if mailboxexists "frop" 32234 {} +# 6 +if mailboxexists "frop" :friep {} + +if mailboxexists "frop" {} +if mailboxexists ["frop", "friep"] {} + +# W:1 +if mailboxexists "${hex:ff}rop" {} +# W:2 +if mailboxexists ["frop", "${hex:ff}riep"] {} + +# 7 +if mailboxexists "frop" ["frop"] {} + +# 8 +fileinto :create 343 "frop"; +# 9 +fileinto :create :frop "frop"; +# 10 +fileinto :create 234234; + +fileinto :create "frop"; + +# 11 +fileinto :create "${hex:ff}rop"; + + diff --git a/pigeonhole/tests/extensions/mailbox/execute.svtest b/pigeonhole/tests/extensions/mailbox/execute.svtest new file mode 100644 index 0000000..cba3034 --- /dev/null +++ b/pigeonhole/tests/extensions/mailbox/execute.svtest @@ -0,0 +1,80 @@ +require "vnd.dovecot.testsuite"; +require "mailbox"; +require "fileinto"; + +test "MailboxExists - None exist" { + if mailboxexists "frop" { + test_fail "mailboxexists confirms existance of unknown folder"; + } +} + +test_mailbox_create "frop"; +test_mailbox_create "friep"; + +test "MailboxExists - Not all exist" { + if mailboxexists ["frop", "friep", "frml"] { + test_fail "mailboxexists confirms existance of unknown folder"; + } +} + +test_mailbox_create "frml"; + +test "MailboxExists - One exists" { + if not mailboxexists ["frop"] { + test_fail "mailboxexists fails to recognize folder"; + } +} + +test "MailboxExists - All exist" { + if not mailboxexists ["frop", "friep", "frml"] { + test_fail "mailboxexists fails to recognize folders"; + } +} + +test ":Create" { + if mailboxexists "created" { + test_fail "mailbox exists already"; + } + + test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop 1 + +Frop! +. + ; + + fileinto :create "created"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + if not mailboxexists "created" { + test_fail "mailbox somehow not created"; + } + + test_result_reset; + + test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop 2 + +Frop! +. + ; + + fileinto "created"; + + if not test_result_execute { + test_fail "execution of result failed second time"; + } + + test_message :folder "created" 0; + + if not header :is "subject" "Frop 1" { + test_fail "incorrect message read back from mail store"; + } +} diff --git a/pigeonhole/tests/extensions/metadata/errors.svtest b/pigeonhole/tests/extensions/metadata/errors.svtest new file mode 100644 index 0000000..3602484 --- /dev/null +++ b/pigeonhole/tests/extensions/metadata/errors.svtest @@ -0,0 +1,56 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +/* + * Invalid syntax + */ + +test "Invalid Syntax" { + if test_script_compile "errors/syntax.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "27" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Metadataexists - bad UTF-8 in mailbox name + */ + +test "Metadataexists - bad UTF-8 in mailbox name" { + if not test_script_compile "errors/metadataexists-bad-utf8.sieve" { + test_fail "compile failed"; + } + + if not test_script_run { + test_fail "execution failed"; + } + + # FIXME: check warnings + if not test_error :count "eq" :comparator "i;ascii-numeric" "0" { + test_fail "wrong number of runtime errors reported"; + } +} + +/* + * Metadata - bad UTF-8 in mailbox name + */ + +test "Metadata - bad UTF-8 in mailbox name" { + if not test_script_compile "errors/metadata-bad-utf8.sieve" { + test_fail "compile failed"; + } + + if not test_script_run { + test_fail "execution failed"; + } + + # FIXME: check warnings + if not test_error :count "eq" :comparator "i;ascii-numeric" "0" { + test_fail "wrong number of runtime errors reported"; + } +} diff --git a/pigeonhole/tests/extensions/metadata/errors/metadata-bad-utf8.sieve b/pigeonhole/tests/extensions/metadata/errors/metadata-bad-utf8.sieve new file mode 100644 index 0000000..fd093a3 --- /dev/null +++ b/pigeonhole/tests/extensions/metadata/errors/metadata-bad-utf8.sieve @@ -0,0 +1,9 @@ +require "mboxmetadata"; +require "variables"; +require "encoded-character"; + +set "mailbox" "${hex:ff}rop"; +if metadata "${mailbox}" "/private/frop" "friep" { + keep; +} + diff --git a/pigeonhole/tests/extensions/metadata/errors/metadataexists-bad-utf8.sieve b/pigeonhole/tests/extensions/metadata/errors/metadataexists-bad-utf8.sieve new file mode 100644 index 0000000..dbb5023 --- /dev/null +++ b/pigeonhole/tests/extensions/metadata/errors/metadataexists-bad-utf8.sieve @@ -0,0 +1,9 @@ +require "mboxmetadata"; +require "variables"; +require "encoded-character"; + +set "mailbox" "${hex:ff}rop"; +if metadataexists "${mailbox}" ["/private/frop", "/shared/friep"] { + keep; +} + diff --git a/pigeonhole/tests/extensions/metadata/errors/syntax.sieve b/pigeonhole/tests/extensions/metadata/errors/syntax.sieve new file mode 100644 index 0000000..c719d94 --- /dev/null +++ b/pigeonhole/tests/extensions/metadata/errors/syntax.sieve @@ -0,0 +1,53 @@ +require "mboxmetadata"; +require "servermetadata"; +require "encoded-character"; + +# 1-4: Used as a command +metadata; +metadataexists; +servermetadata; +servermetadataexists; + +# 5-8: Used with no argument +if metadata {} +if metadataexists {} +if servermetadata {} +if servermetadataexists {} + +# 9-11: Used with one string argument +if metadata "frop" { } +if servermetadata "frop" { } +if metadataexists "frop" { } + +# 12-15: Used with one number argument +if metadata 13123123 { } +if servermetadata 123123 { } +if metadataexists 123123 { } +if servermetadataexists 123123 {} + +# 16-18: Used with one string list argument +if metadata ["frop"] { } +if servermetadata ["frop"] { } +if metadataexists ["frop"] { } + +# 19-22: Used with unknown tag +if metadata :frop "frop" { } +if servermetadata :frop "frop" { } +if metadataexists :frop "frop" { } +if servermetadataexists :frop "frop" {} + +# 23-26: Invalid arguments +if metadata "/private/frop" "friep" {} +if servermetadata "INBOX" "/private/frop" "friep" {} +if metadataexists 23 "/private/frop" {} +if servermetadataexists "INBOX" "/private/frop" {} + +# W1-W4: Invalid annotations +if metadata "INBOX" "frop" "friep" {} +if servermetadata "frop" "friep" {} +if metadataexists "INBOX" ["/private/frop", "/friep"] { } +if servermetadataexists ["/private/frop", "/friep", "/private/friep"] { } + +# W5-W6: Invalid mailbox name +if metadata "${hex:ff}rop" "/private/frop" "friep" {} +if metadataexists "${hex:ff}rop" ["/private/frop", "/shared/friep"] { } diff --git a/pigeonhole/tests/extensions/metadata/execute.svtest b/pigeonhole/tests/extensions/metadata/execute.svtest new file mode 100644 index 0000000..32aac82 --- /dev/null +++ b/pigeonhole/tests/extensions/metadata/execute.svtest @@ -0,0 +1,145 @@ +require "vnd.dovecot.testsuite"; +require "mboxmetadata"; +require "servermetadata"; +require "fileinto"; + +test "MetadataExists - None exist" { + if metadataexists "INBOX" "/private/frop" { + test_fail "metadataexists confirms existence of unknown annotation"; + } +} + +test_imap_metadata_set :mailbox "INBOX" "/private/frop" "FROP!"; +test_imap_metadata_set :mailbox "INBOX" "/private/friep" "FRIEP!"; + +test "MetadataExists - Not all exist" { + if metadataexists "INBOX" + ["/private/frop", "/private/friep", "/private/frml"] { + test_fail "metadataexists confirms existence of unknown annotation"; + } +} + +test_imap_metadata_set :mailbox "INBOX" "/private/friep" "FRIEP!"; +test_imap_metadata_set :mailbox "INBOX" "/private/frml" "FRML!"; + +test "MetadataExists - One exists" { + if not metadataexists "INBOX" ["/private/frop"] { + test_fail "metadataexists fails to recognize annotation"; + } +} + +test "MetadataExists - All exist" { + if not metadataexists "INBOX" + ["/private/frop", "/private/friep", "/private/frml"] { + test_fail "metadataexists fails to recognize annotations"; + } +} + +test "MetadataExists - Invalid" { + if metadataexists "INBOX" + ["/shared/frop", "/friep", "/private/frml"] { + test_fail "metadataexists accepted invalid annotation name"; + } +} + +test "Metadata" { + if not metadata :is "INBOX" "/private/frop" "FROP!" { + test_fail "invalid metadata value for /private/frop"; + } + if metadata :is "INBOX" "/private/frop" "Hutsefluts" { + test_fail "unexpected match for /private/frop"; + } + + if not metadata :is "INBOX" "/private/friep" "FRIEP!" { + test_fail "invalid metadata value for /private/friep"; + } + if metadata :is "INBOX" "/private/friep" "Hutsefluts" { + test_fail "unexpected match for /private/friep"; + } + + if not metadata :is "INBOX" "/private/frml" "FRML!" { + test_fail "invalid metadata value for /private/frml"; + } + if metadata :is "INBOX" "/private/frml" "Hutsefluts" { + test_fail "unexpected match for /private/frml"; + } +} + +test "Metadata - Invalid" { + if metadata :contains "INBOX" "/frop" "" { + test_fail "erroneously found a value for \"/frop\""; + } +} + +test "ServermetadataExists - None exist" { + if servermetadataexists "/private/frop" { + test_fail "servermetadataexists confirms existence of unknown annotation"; + } +} + +# currently not possible to test servermetadata +if false { + +test_imap_metadata_set "/private/frop" "FROP!"; +test_imap_metadata_set "/private/friep" "FRIEP!"; + +test "ServermetadataExists - Not all exist" { + if servermetadataexists + ["/private/frop", "/private/friep", "/private/frml"] { + test_fail "metadataexists confirms existence of unknown annotation"; + } +} + +test_imap_metadata_set "/private/friep" "FRIEP!"; +test_imap_metadata_set "/private/frml" "FRML!"; + +test "ServermetadataExists - One exists" { + if not servermetadataexists ["/private/frop"] { + test_fail "servermetadataexists fails to recognize annotation"; + } +} + +test "ServermetadataExists - All exist" { + if not servermetadataexists + ["/private/frop", "/private/friep", "/private/frml"] { + test_fail "servermetadataexists fails to recognize annotations"; + } +} + +test "ServermetadataExists - Invalid" { + if servermetadataexists + ["frop", "/private/friep", "/private/frml"] { + test_fail "servermetadataexists accepted invalid annotation name"; + } +} + +test "Servermetadata" { + if not servermetadata :is "/private/frop" "FROP!" { + test_fail "invalid servermetadata value for /private/frop"; + } + if servermetadata :is "/private/frop" "Hutsefluts" { + test_fail "unexpected match for /private/frop"; + } + + if not servermetadata :is "/private/friep" "FRIEP!" { + test_fail "invalid servermetadata value for /private/friep"; + } + if servermetadata :is "/private/friep" "Hutsefluts" { + test_fail "unexpected match for /private/friep"; + } + + if not servermetadata :is "/private/frml" "FRML!" { + test_fail "invalid servermetadata value for /private/frml"; + } + if servermetadata :is "/private/frml" "Hutsefluts" { + test_fail "unexpected match for /private/frml"; + } +} + +test "Servermetadata - Invalid" { + if servermetadata :contains "/frop" "" { + test_fail "erroneously found a value for \"/frop\""; + } +} + +} #disabled diff --git a/pigeonhole/tests/extensions/mime/address.svtest b/pigeonhole/tests/extensions/mime/address.svtest new file mode 100644 index 0000000..1607450 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/address.svtest @@ -0,0 +1,281 @@ +require "vnd.dovecot.testsuite"; +require "mime"; +require "foreverypart"; + +/* + * Basic functionionality + */ + +test_set "message" text: +From: stephan@example.com +To: nico@nl.example.com, harry@de.example.com +cc: Timo <tss(no spam)@fi.iki> +Subject: Frobnitzm + +Test. +. +; + +test "Basic functionality" { + /* Must match */ + if not address :mime :anychild :contains ["to", "from"] "harry" { + test_fail "failed to match address (1)"; + } + + if not address :mime :anychild :contains ["to", "from"] "de.example" { + test_fail "failed to match address (2)"; + } + + if not address :mime :anychild :matches "to" "*@*.example.com" { + test_fail "failed to match address (3)"; + } + + if not address :mime :anychild :is "to" "harry@de.example.com" { + test_fail "failed to match address (4)"; + } + + /* Must not match */ + if address :mime :anychild :is ["to", "from"] "nonsense@example.com" { + test_fail "matches erroneous address"; + } + + /* Match first key */ + if not address :mime :anychild :contains ["to"] ["nico", "fred", "henk"] { + test_fail "failed to match first key"; + } + + /* Match second key */ + if not address :mime :anychild :contains ["to"] ["fred", "nico", "henk"] { + test_fail "failed to match second key"; + } + + /* Match last key */ + if not address :mime :anychild :contains ["to"] ["fred", "henk", "nico"] { + test_fail "failed to match last key"; + } + + /* First header */ + if not address :mime :anychild :contains + ["to", "from"] ["fred", "nico", "henk"] { + test_fail "failed to match first header"; + } + + /* Second header */ + if not address :mime :anychild :contains + ["from", "to"] ["fred", "nico", "henk"] { + test_fail "failed to match second header"; + } + + /* Comment */ + if not address :mime :anychild :is "cc" "tss@fi.iki" { + test_fail "failed to ignore comment in address"; + } +} + +/* + * Basic functionionality - foreverypart + */ + +test "Basic functionality - foreverypart" { + foreverypart { + /* Must match */ + if not address :mime :anychild :contains ["to", "from"] "harry" { + test_fail "failed to match address (1)"; + } + + if not address :mime :anychild :contains ["to", "from"] "de.example" { + test_fail "failed to match address (2)"; + } + + if not address :mime :anychild :matches "to" "*@*.example.com" { + test_fail "failed to match address (3)"; + } + + if not address :mime :anychild :is "to" "harry@de.example.com" { + test_fail "failed to match address (4)"; + } + + /* Must not match */ + if address :mime :anychild :is ["to", "from"] "nonsense@example.com" { + test_fail "matches erroneous address"; + } + + /* Match first key */ + if not address :mime :anychild :contains ["to"] ["nico", "fred", "henk"] { + test_fail "failed to match first key"; + } + + /* Match second key */ + if not address :mime :anychild :contains ["to"] ["fred", "nico", "henk"] { + test_fail "failed to match second key"; + } + + /* Match last key */ + if not address :mime :anychild :contains ["to"] ["fred", "henk", "nico"] { + test_fail "failed to match last key"; + } + + /* First header */ + if not address :mime :anychild :contains + ["to", "from"] ["fred", "nico", "henk"] { + test_fail "failed to match first header"; + } + + /* Second header */ + if not address :mime :anychild :contains + ["from", "to"] ["fred", "nico", "henk"] { + test_fail "failed to match second header"; + } + + /* Comment */ + if not address :mime :anychild :is "cc" "tss@fi.iki" { + test_fail "failed to ignore comment in address"; + } + } +} + +/* + * Address headers + */ + +test_set "message" text: +From: stephan@friep.frop +To: henk@tukkerland.ex +CC: ivo@boer.ex +Bcc: joop@hooibaal.ex +Sender: s.bosch@friep.frop +Resent-From: ivo@boer.ex +Resent-To: idioot@dombo.ex +Subject: Berichtje + +Test. +. +; + +test "Address headers" { + if not address :mime :anychild "from" "stephan@friep.frop" { + test_fail "from header not recognized"; + } + + if not address :mime :anychild "to" "henk@tukkerland.ex" { + test_fail "to header not recognized"; + } + + if not address :mime :anychild "cc" "ivo@boer.ex" { + test_fail "cc header not recognized"; + } + + if not address :mime :anychild "bcc" "joop@hooibaal.ex" { + test_fail "bcc header not recognized"; + } + + if not address :mime :anychild "sender" "s.bosch@friep.frop" { + test_fail "sender header not recognized"; + } + + if not address :mime :anychild "resent-from" "ivo@boer.ex" { + test_fail "resent-from header not recognized"; + } + + if not address :mime :anychild "resent-to" "idioot@dombo.ex" { + test_fail "resent-to header not recognized"; + } +} + +/* + * Address headers - foreverypart + */ + +test "Address headers - foreverypart" { + foreverypart { + if not address :mime :anychild "from" "stephan@friep.frop" { + test_fail "from header not recognized"; + } + + if not address :mime :anychild "to" "henk@tukkerland.ex" { + test_fail "to header not recognized"; + } + + if not address :mime :anychild "cc" "ivo@boer.ex" { + test_fail "cc header not recognized"; + } + + if not address :mime :anychild "bcc" "joop@hooibaal.ex" { + test_fail "bcc header not recognized"; + } + + if not address :mime :anychild "sender" "s.bosch@friep.frop" { + test_fail "sender header not recognized"; + } + + if not address :mime :anychild "resent-from" "ivo@boer.ex" { + test_fail "resent-from header not recognized"; + } + + if not address :mime :anychild "resent-to" "idioot@dombo.ex" { + test_fail "resent-to header not recognized"; + } + } +} + +/* + * Multipart anychild + */ + +test_set "message" text: +From: Hendrik <hendrik@example.com> +To: Harrie <harrie@example.com> +Date: Sat, 11 Oct 2010 00:31:44 +0200 +Subject: Harrie is een prutser +Content-Type: multipart/mixed; boundary=AA +CC: AA@example.com + +This is a multi-part message in MIME format. +--AA +Content-Type: multipart/mixed; boundary=BB +CC: BB@example.com + +This is a multi-part message in MIME format. +--BB +Content-Type: text/plain; charset="us-ascii" +CC: CC@example.com + +Hello + +--BB +Content-Type: text/plain; charset="us-ascii" +CC: DD@example.com + +Hello again + +--BB-- +This is the end of MIME multipart. + +--AA +Content-Type: text/plain; charset="us-ascii" +CC: EE@example.com + +And again + +--AA-- +This is the end of MIME multipart. +. +; + +test "Multipart anychild" { + if not address :mime :anychild :localpart "Cc" "AA" { + test_fail "AA Cc repient does not exist"; + } + if not address :mime :anychild :localpart "Cc" "BB" { + test_fail "BB Cc repient does not exist"; + } + if not address :mime :anychild :localpart "Cc" "CC" { + test_fail "CC Cc repient does not exist"; + } + if not address :mime :anychild :localpart "Cc" "DD" { + test_fail "DD Cc repient does not exist"; + } + if not address :mime :anychild :localpart "Cc" "EE" { + test_fail "EE Cc repient does not exist"; + } +} diff --git a/pigeonhole/tests/extensions/mime/calendar-example.svtest b/pigeonhole/tests/extensions/mime/calendar-example.svtest new file mode 100644 index 0000000..745e6e6 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/calendar-example.svtest @@ -0,0 +1,129 @@ +require "vnd.dovecot.testsuite"; +require "mime"; +require "foreverypart"; +require "editheader"; +require "relational"; +require "variables"; + +# Example from RFC 6047, Section 2.5: +test_set "message" text: +From: user1@example.com +To: user2@example.com +Subject: Phone Conference +Mime-Version: 1.0 +Date: Wed, 07 May 2008 21:30:25 +0400 +Message-ID: <4821E731.5040506@laptop1.example.com> +Content-Type: text/calendar; method=REQUEST; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +BEGIN:VCALENDAR +PRODID:-//Example/ExampleCalendarClient//EN +METHOD:REQUEST +VERSION:2.0 +BEGIN:VEVENT +ORGANIZER:mailto:user1@example.com +ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED:mailto:user1@example.com +ATTENDEE;RSVP=YES;CUTYPE=INDIVIDUAL:mailto:user2@example.com +DTSTAMP:20080507T170000Z +DTSTART:20080701T160000Z +DTEND:20080701T163000Z +SUMMARY:Phone call to discuss your last visit +DESCRIPTION:=D1=82=D1=8B =D0=BA=D0=B0=D0=BA - =D0=B4=D0=BE=D0= + =B2=D0=BE=D0=BB=D0=B5=D0=BD =D0=BF=D0=BE=D0=B5=D0=B7=D0=B4=D0=BA=D0 + =BE=D0=B9? +UID:calsvr.example.com-8739701987387998 +SEQUENCE:0 +STATUS:TENTATIVE +END:VEVENT +END:VCALENDAR +. +; + +test "Calendar only" { + foreverypart { + if allof( + header :mime :count "eq" "Content-Type" "1", + header :mime :contenttype "Content-Type" "text/calendar", + header :mime :param "method" :matches "Content-Type" "*", + header :mime :param "charset" :is "Content-Type" "UTF-8" ) { + addheader "X-ICAL" "${1}"; + break; + } + } + + if not header "x-ical" "request" { + test_fail "Failed to parse message correctly"; + } +} + +# Modified example +test_set "message" text: +From: user1@example.com +To: user2@example.com +Subject: Phone Conference +Mime-Version: 1.0 +Date: Wed, 07 May 2008 21:30:25 +0400 +Message-ID: <4821E731.5040506@laptop1.example.com> +Content-Type: multipart/mixed; boundary=AA + +This is a multi-part message in MIME format. + +--AA +Content-Type: text/plain + +Hello, + +I'd like to discuss your last visit. A tentative meeting schedule is +attached. + +Regards, + +User1 + +--AA +Content-Type: text/calendar; method=REQUEST; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +BEGIN:VCALENDAR +PRODID:-//Example/ExampleCalendarClient//EN +METHOD:REQUEST +VERSION:2.0 +BEGIN:VEVENT +ORGANIZER:mailto:user1@example.com +ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED:mailto:user1@example.com +ATTENDEE;RSVP=YES;CUTYPE=INDIVIDUAL:mailto:user2@example.com +DTSTAMP:20080507T170000Z +DTSTART:20080701T160000Z +DTEND:20080701T163000Z +SUMMARY:Phone call to discuss your last visit +DESCRIPTION:=D1=82=D1=8B =D0=BA=D0=B0=D0=BA - =D0=B4=D0=BE=D0= + =B2=D0=BE=D0=BB=D0=B5=D0=BD =D0=BF=D0=BE=D0=B5=D0=B7=D0=B4=D0=BA=D0 + =BE=D0=B9? +UID:calsvr.example.com-8739701987387998 +SEQUENCE:0 +STATUS:TENTATIVE +END:VEVENT +END:VCALENDAR + +--AA-- +. +; + +test "Multipart message" { + foreverypart { + if allof( + header :mime :count "eq" "Content-Type" "1", + header :mime :contenttype "Content-Type" "text/calendar", + header :mime :param "method" :matches "Content-Type" "*", + header :mime :param "charset" :is "Content-Type" "UTF-8" ) { + addheader "X-ICAL" "${1}"; + break; + } + } + + if not header "x-ical" "request" { + test_fail "Failed to parse message correctly"; + } +} + + diff --git a/pigeonhole/tests/extensions/mime/content-header.svtest b/pigeonhole/tests/extensions/mime/content-header.svtest new file mode 100644 index 0000000..9686e35 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/content-header.svtest @@ -0,0 +1,161 @@ +require "vnd.dovecot.testsuite"; +require "relational"; +require "mime"; + +test_set "message" text: +From: stephan@example.com +To: timo@example.com +Subject: Frop +Content-Type: text/plain + +Frop +. +; + +test "Simple Content-Type :type" { + if not header :mime :type "content-type" "text" { + test_fail "wrong type extracted"; + } +} + +test "Simple Content-Type :subype" { + if not header :mime :subtype "content-type" "plain" { + test_fail "wrong subtype extracted"; + } +} + +test "Simple Content-Type :contenttype" { + if not header :mime :contenttype "content-type" "text/plain" { + test_fail "wrong contenttype extracted"; + } +} + +test_set "message" text: +From: stephan@example.com +To: timo@example.com +Subject: Frop +Content-Type: text/calendar; method=request; charset=UTF-8; + +Frop +. +; + +test "Advanced Content-Type :type" { + if not header :mime :type "content-type" "text" { + test_fail "wrong type extracted"; + } +} + +test "Advanced Content-Type :subype" { + if not header :mime :subtype "content-type" "calendar" { + test_fail "wrong subtype extracted"; + } +} + +test "Advanced Content-Type :contenttype" { + if not header :mime :contenttype "content-type" "text/calendar" { + test_fail "wrong contenttype extracted"; + } +} + +test "Advanced Content-Type :param" { + if not header :mime :param "method" "content-type" "request" { + test_fail "wrong method param extracted"; + } + + if not header :mime :param "charset" "content-type" "UTF-8" { + test_fail "wrong charset param extracted"; + } + + if not header :mime :param ["method", "charset"] + "content-type" "request" { + test_fail "wrong method param extracted"; + } + + if not header :mime :param ["method", "charset"] + "content-type" "UTF-8" { + test_fail "wrong charset param extracted"; + } + + if not header :count "eq" :mime :param ["method", "charset"] + "content-type" "2" { + test_fail "wrong number of parameters"; + } +} + +test_set "message" text: +From: stephan@example.com +To: timo@example.com +Subject: Frop +Content-Type: application/x-stuff; + title*0*=us-ascii'en'This%20is%20even%20more%20; + title*1*=%2A%2A%2Afun%2A%2A%2A%20; + title*2="isn't it!" + +Frop +. +; + +test "Encoded Content-Type :param" { + if not header :mime :param "title" "content-type" + "This is even more ***fun*** isn't it!" { + test_fail "wrong method param extracted"; + } +} + +test_set "message" text: +From: stephan@example.com +To: timo@example.com +Subject: Frop +Content-Type: image/png +Content-Disposition: inline; filename="frop.exe"; title="Frop!" + +Frop +. +; + +test "Content-Disposition :type" { + if not header :mime :type "content-disposition" "inline" { + test_fail "wrong type extracted"; + } +} + +test "Content-Disposition :subype" { + if not header :mime :subtype "content-disposition" "" { + test_fail "wrong subtype extracted"; + } +} + +test "Content-Disposition :contenttype" { + if not header :mime :contenttype "content-disposition" "inline" { + test_fail "wrong contenttype extracted"; + } +} + +test "Content-Disposition :param" { + if not header :mime :param "filename" "content-disposition" "frop.exe" { + test_fail "wrong filename param extracted"; + } + + if not header :mime :param "title" "content-disposition" "Frop!" { + test_fail "wrong title param extracted"; + } + + if not header :mime :param ["filename", "title"] + "content-disposition" "frop.exe" { + test_fail "wrong filename param extracted"; + } + + if not header :mime :param ["filename", "title"] + "content-disposition" "Frop!" { + test_fail "wrong title param extracted"; + } + + if not header :count "eq" :mime :param ["filename", "title"] + "content-disposition" "2" { + test_fail "wrong number of parameters"; + } + +} + + diff --git a/pigeonhole/tests/extensions/mime/errors.svtest b/pigeonhole/tests/extensions/mime/errors.svtest new file mode 100644 index 0000000..b3b858e --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors.svtest @@ -0,0 +1,162 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +test "Foreverypart command" { + if test_script_compile "errors/foreverypart.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" :comparator "i;ascii-numeric" "12" { + test_fail "incorrect number of compile errors reported"; + } +} + +test "Break command" { + if test_script_compile "errors/break.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" :comparator "i;ascii-numeric" "21" { + test_fail "incorrect number of compile errors reported"; + } +} + +test "Header test with :mime tag" { + if test_script_compile "errors/header-mime-tag.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" :comparator "i;ascii-numeric" "10" { + test_fail "incorrect number of compile errors reported"; + } +} + +test "Address test with :mime tag" { + if test_script_compile "errors/address-mime-tag.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" :comparator "i;ascii-numeric" "6" { + test_fail "incorrect number of compile errors reported"; + } +} + +test "Exists test with :mime tag" { + if test_script_compile "errors/exists-mime-tag.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" :comparator "i;ascii-numeric" "6" { + test_fail "incorrect number of compile errors reported"; + } +} + +test "Limits" { + if test_script_compile "errors/limits.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" :comparator "i;ascii-numeric" "2" { + test_fail "incorrect number of compile errors reported"; + } +} + +test_set "message" text: +From: Whomever <whoever@example.com> +To: Someone <someone@example.com> +Date: Sat, 10 Oct 2009 00:30:04 +0200 +Subject: whatever +Content-Type: multipart/mixed; boundary=AA + +This is a multi-part message in MIME format. + +--AA +Content-Type: multipart/alternative; boundary=BB + +This is a multi-part message in MIME format. + +--BB +Content-Type: multipart/alternative; boundary=CC + +This is a multi-part message in MIME format. + +--CC +Content-Type: multipart/alternative; boundary=DD + +This is a multi-part message in MIME format. + +--DD +Content-Type: multipart/alternative; boundary=EE + +This is a nested multi-part message in MIME format. + +--EE +Content-Type: text/plain; charset="us-ascii" + +Hello + +--EE-- + +This is the end of the inner MIME multipart. + +--DD-- + +This is the end of the MIME multipart. + +--CC-- + +This is the end of the MIME multipart. + +--BB-- + +This is the end of the MIME multipart. + +--AA-- + +This is the end of the MIME multipart. +. +; + +test "Limits - include" { + if not test_script_compile "errors/limits-include.sieve" { + test_fail "script compile failed"; + } + + if test_script_run { + test_fail "script run should have failed"; + } +} + +test "Extracttext" { + if test_script_compile "errors/extracttext.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" :comparator "i;ascii-numeric" "11" { + test_fail "incorrect number of compile errors reported"; + } +} + +test "Extracttext - without variables" { + if test_script_compile "errors/extracttext-novar.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" :comparator "i;ascii-numeric" "2" { + test_fail "incorrect number of compile errors reported"; + } +} + +test "Extracttext - without foreverypart" { + if test_script_compile "errors/extracttext-nofep.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" :comparator "i;ascii-numeric" "2" { + test_fail "incorrect number of compile errors reported"; + } +} + + diff --git a/pigeonhole/tests/extensions/mime/errors/address-mime-tag.sieve b/pigeonhole/tests/extensions/mime/errors/address-mime-tag.sieve new file mode 100644 index 0000000..7adb7bc --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/address-mime-tag.sieve @@ -0,0 +1,38 @@ +require "mime"; + +## Address + +# No error +if address :contains :mime "To" "frop@example.com" { + discard; +} + +# No error +if address :anychild :contains :mime "To" "frop@example.com" { + discard; +} + +# 1: Bare anychild option +if address :anychild "To" "frop@example.com" { + discard; +} + +# 2: Inappropriate option +if address :mime :anychild :type "To" "frop@example.com" { + discard; +} + +# 3: Inappropriate option +if address :mime :anychild :subtype "To" "frop@example.com" { + discard; +} + +# 4: Inappropriate option +if address :mime :anychild :contenttype "To" "frop@example.com" { + discard; +} + +# 5: Inappropriate option +if address :mime :anychild :param "frop" "To" "frop@example.com" { + discard; +} diff --git a/pigeonhole/tests/extensions/mime/errors/break.sieve b/pigeonhole/tests/extensions/mime/errors/break.sieve new file mode 100644 index 0000000..1858673 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/break.sieve @@ -0,0 +1,157 @@ +require "foreverypart"; + +foreverypart :name "frop" { + # 1: Spurious tag + break :tag; + + # 2: Spurious tests + break true; + + # 3: Spurious tests + break anyof(true, false); + + # 4: Bare string + break "frop"; + + # 5: Bare string-list + break ["frop", "friep"]; + + # 6: Several bad arguments + break 13 ["frop", "friep"]; + + # 7: Spurious additional tag + break :name "frop" :friep; + + # 8: Spurious additional string + break :name "frop" "friep"; + + # 9: Bad name + break :name 13; + + # 10: Bad name + break :name ["frop", "friep"]; + + # No error + break; + + # No error + break :name "frop"; + + # No error + if exists "frop" { + break; + } + + # No error + if exists "frop" { + break :name "frop"; + } + + # No error + foreverypart { + break :name "frop"; + } + + # No error + foreverypart :name "friep" { + break :name "frop"; + } + + # No error + foreverypart :name "friep" { + break :name "friep"; + } + + # No error + foreverypart :name "friep" { + break; + } + + # No error + foreverypart { + if exists "frop" { + break :name "frop"; + } + } + + # No error + foreverypart :name "friep" { + if exists "frop" { + break :name "frop"; + } + } + + # No error + foreverypart :name "friep" { + if exists "frop" { + break :name "friep"; + } + } + + # No error + foreverypart :name "friep" { + if exists "frop" { + break; + } + } +} + +# 11: Outside loop +break; + +# 12: Outside loop +if exists "frop" { + break; +} + +# 13: Outside loop +break :name "frop"; + +# 14: Outside loop +if exists "frop" { + break :name "frop"; +} + +# 15: Bad name +foreverypart { + break :name "frop"; +} + +# 16: Bad name +foreverypart { + if exists "frop" { + break :name "frop"; + } +} + +# 17: Bad name +foreverypart :name "friep" { + break :name "frop"; +} + +# 18: Bad name +foreverypart :name "friep" { + if exists "frop" { + break :name "frop"; + } +} + +# 19: Bad name +foreverypart :name "friep" { + foreverypart :name "frop" { + break :name "frml"; + } +} + +# 20: Bad name +foreverypart :name "friep" { + foreverypart :name "frop" { + if exists "frop" { + break :name "frml"; + } + } +} + + + + diff --git a/pigeonhole/tests/extensions/mime/errors/exists-mime-tag.sieve b/pigeonhole/tests/extensions/mime/errors/exists-mime-tag.sieve new file mode 100644 index 0000000..84c86a7 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/exists-mime-tag.sieve @@ -0,0 +1,43 @@ +require "mime"; + +## Exists + +# No error +if exists :mime "To" { + discard; +} + +# No error +if exists :anychild :mime "To" { + discard; +} + +# 1: Inappropriate option +if exists :anychild "To" { + discard; +} + +# 2: Inappropriate option +if exists :mime :type "To" { + discard; +} + +# 3: Inappropriate option +if exists :mime :subtype "To" { + discard; +} + +# 4: Inappropriate option +if exists :mime :contenttype "To" { + discard; +} + +# 5: Inappropriate option +if exists :mime :param ["frop", "friep"] "To" { + discard; +} + + + + + diff --git a/pigeonhole/tests/extensions/mime/errors/extracttext-nofep.sieve b/pigeonhole/tests/extensions/mime/errors/extracttext-nofep.sieve new file mode 100644 index 0000000..c38b228 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/extracttext-nofep.sieve @@ -0,0 +1,4 @@ +require "extracttext"; +require "variables"; + +keep; diff --git a/pigeonhole/tests/extensions/mime/errors/extracttext-novar.sieve b/pigeonhole/tests/extensions/mime/errors/extracttext-novar.sieve new file mode 100644 index 0000000..8e2a378 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/extracttext-novar.sieve @@ -0,0 +1,6 @@ +require "extracttext"; +require "foreverypart"; + +foreverypart { + extracttext "frop"; +} diff --git a/pigeonhole/tests/extensions/mime/errors/extracttext.sieve b/pigeonhole/tests/extensions/mime/errors/extracttext.sieve new file mode 100644 index 0000000..f8af1c9 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/extracttext.sieve @@ -0,0 +1,42 @@ +require "extracttext"; +require "variables"; +require "foreverypart"; + +# 1: Used outside foreverypart +extracttext :first 10 "data"; + +foreverypart { + # 2: Missing arguments + extracttext; + + # 3: Bad arguments + extracttext 1; + + # 4: Bad arguments + extracttext ["frop", "friep"]; + + # 5: Unknown tag + extracttext :frop "frop"; + + # 6: Invalid variable name + extracttext "${frop}"; + + # Not an error + extracttext "\n\a\m\e"; + + # 7: Trying to assign match variable + extracttext "0"; + + # Not an error + extracttext :lower "frop"; + + # 8: Bad ":first" tag + extracttext :first "frop"; + + # 9: Bad ":first" tag + extracttext :first "frop" "friep"; + + # 10: Bad ":first" tag + extracttext :first ["frop", "friep"] "frml"; +} + diff --git a/pigeonhole/tests/extensions/mime/errors/foreverypart.sieve b/pigeonhole/tests/extensions/mime/errors/foreverypart.sieve new file mode 100644 index 0000000..38a28d4 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/foreverypart.sieve @@ -0,0 +1,45 @@ +require "foreverypart"; + +# 1: No block +foreverypart; + +# 2: Spurious tag +foreverypart :tag { } + +# 3: Spurious tests +foreverypart true { } + +# 4: Spurious tests +foreverypart anyof(true, false) { } + +# 5: Bare string +foreverypart "frop" { } + +# 6: Bare string-list +foreverypart ["frop", "friep"] { } + +# 7: Several bad arguments +foreverypart 13 ["frop", "friep"] { } + +# 8: Spurious additional tag +foreverypart :name "frop" :friep { } + +# 9: Spurious additional string +foreverypart :name "frop" "friep" { } + +# 10: Bad name +foreverypart :name 13 { } + +# 11: Bad name +foreverypart :name ["frop", "friep"] { } + +# No error +foreverypart { keep; } + +# No error +foreverypart :name "frop" { keep; } + +# No error +foreverypart :name "frop" { foreverypart { keep; } } + + diff --git a/pigeonhole/tests/extensions/mime/errors/header-mime-tag.sieve b/pigeonhole/tests/extensions/mime/errors/header-mime-tag.sieve new file mode 100644 index 0000000..85782af --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/header-mime-tag.sieve @@ -0,0 +1,100 @@ +require "mime"; + +## Header + +# No error +if header :contains :mime "Content-Type" "text/plain" { + discard; +} + +# No error +if header :mime :type "Content-Type" "text" { + discard; +} + +# No error +if header :mime :subtype "Content-Type" "plain" { + discard; +} + +# No error +if header :mime :contenttype "Content-Type" "text/plain" { + discard; +} + +# No error +if header :mime :param ["frop", "friep"] "Content-Type" "frml" { + discard; +} + +# No error +if header :anychild :contains :mime "Content-Type" "text/plain" { + discard; +} + +# No error +if header :mime :anychild :type "Content-Type" "text" { + discard; +} + +# No error +if header :mime :subtype :anychild "Content-Type" "plain" { + discard; +} + +# No error +if header :anychild :mime :contenttype "Content-Type" "text/plain" { + discard; +} + +# No error +if header :mime :param ["frop", "friep"] :anychild "Content-Type" "frml" { + discard; +} + +# 1: Bare anychild option +if header :anychild "Content-Type" "frml" { + discard; +} + +# 2: Bare mime option +if header :type "Content-Type" "frml" { + discard; +} + +# 3: Bare mime option +if header :subtype "Content-Type" "frml" { + discard; +} + +# 4: Bare mime option +if header :contenttype "Content-Type" "frml" { + discard; +} + +# 5: Bare mime option +if header :param "frop" "Content-Type" "frml" { + discard; +} + +# 6: Multiple option tags +if header :mime :type :subtype "Content-Type" "frml" { + discard; +} + +# 7: Bad param argument +if header :mime :param 13 "Content-Type" "frml" { + discard; +} + +# 8: Missing param argument +if header :mime :param :anychild "Content-Type" "frml" { + discard; +} + +# 9: Missing param argument +if header :mime :param :frop "Content-Type" "frml" { + discard; +} + + diff --git a/pigeonhole/tests/extensions/mime/errors/limits-include.sieve b/pigeonhole/tests/extensions/mime/errors/limits-include.sieve new file mode 100644 index 0000000..ef92456 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/limits-include.sieve @@ -0,0 +1,6 @@ +require "foreverypart"; +require "include"; + +foreverypart :name "frop" { + include "include-loop-2"; +} diff --git a/pigeonhole/tests/extensions/mime/errors/limits.sieve b/pigeonhole/tests/extensions/mime/errors/limits.sieve new file mode 100644 index 0000000..0add1c3 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/limits.sieve @@ -0,0 +1,13 @@ +require "foreverypart"; + +foreverypart :name "frop" { + foreverypart :name "friep" { + foreverypart :name "frml" { + foreverypart { + foreverypart { + break; + } + } + } + } +} diff --git a/pigeonhole/tests/extensions/mime/execute.svtest b/pigeonhole/tests/extensions/mime/execute.svtest new file mode 100644 index 0000000..2ced83b --- /dev/null +++ b/pigeonhole/tests/extensions/mime/execute.svtest @@ -0,0 +1,82 @@ +require "vnd.dovecot.testsuite"; + +/* + * Execution testing (currently just meant to trigger any segfaults) + */ + +test_set "message" text: +From: Whomever <whoever@example.com> +To: Someone <someone@example.com> +Date: Sat, 10 Oct 2009 00:30:04 +0200 +Subject: whatever +Content-Type: multipart/mixed; boundary=outer + +This is a multi-part message in MIME format. + +--outer +Content-Type: multipart/alternative; boundary=inner + +This is a nested multi-part message in MIME format. + +--inner +Content-Type: text/plain; charset="us-ascii" + +Hello + +--inner +Content-Type: text/html; charset="us-ascii" + +<html><body>Hello</body></html> + +--inner-- + +This is the end of the inner MIME multipart. + +--outer +Content-Type: message/rfc822 + +From: Someone Else +Subject: Hello, this is an elaborate request for you to finally say hello + already! + +Please say Hello + +--outer-- + +This is the end of the outer MIME multipart. +. +; + +test "Basic - foreverypart" { + if not test_script_compile "execute/foreverypart.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script run failed"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } + + test_binary_save "ihave-basic"; + test_binary_load "ihave-basic"; +} + +test "Basic - mime" { + if not test_script_compile "execute/mime.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script run failed"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } + + test_binary_save "ihave-basic"; + test_binary_load "ihave-basic"; +} diff --git a/pigeonhole/tests/extensions/mime/execute/foreverypart.sieve b/pigeonhole/tests/extensions/mime/execute/foreverypart.sieve new file mode 100644 index 0000000..9ae1fba --- /dev/null +++ b/pigeonhole/tests/extensions/mime/execute/foreverypart.sieve @@ -0,0 +1,14 @@ +require "foreverypart"; +require "variables"; + +foreverypart { + foreverypart { + foreverypart { + foreverypart { + set "a" "a${a}"; + } + } + } +} + + diff --git a/pigeonhole/tests/extensions/mime/execute/mime.sieve b/pigeonhole/tests/extensions/mime/execute/mime.sieve new file mode 100644 index 0000000..dd7fedc --- /dev/null +++ b/pigeonhole/tests/extensions/mime/execute/mime.sieve @@ -0,0 +1,69 @@ +require "mime"; +require "foreverypart"; +require "variables"; + +if header :contains :mime "Content-Type" "text/plain" { + discard; +} +if header :mime :type "Content-Type" "text" { + discard; +} +if header :mime :subtype "Content-Type" "plain" { + discard; +} +if header :mime :contenttype "Content-Type" "text/plain" { + discard; +} +if header :mime :param ["frop", "friep"] "Content-Type" "frml" { + discard; +} +if header :anychild :contains :mime "Content-Type" "text/plain" { + discard; +} +if header :mime :anychild :type "Content-Type" "text" { + discard; +} +if header :mime :subtype :anychild "Content-Type" "plain" { + discard; +} +if header :anychild :mime :contenttype "Content-Type" "text/plain" { + discard; +} +if header :mime :param ["frop", "friep"] :anychild "Content-Type" "frml" { + discard; +} + +foreverypart { + foreverypart { + if header :contains :mime "Content-Type" "text/plain" { + discard; + } + if header :mime :type "Content-Type" "text" { + discard; + } + if header :mime :subtype "Content-Type" "plain" { + discard; + } + if header :mime :contenttype "Content-Type" "text/plain" { + discard; + } + if header :mime :param ["frop", "friep"] "Content-Type" "frml" { + discard; + } + if header :anychild :contains :mime "Content-Type" "text/plain" { + discard; + } + if header :mime :anychild :type "Content-Type" "text" { + discard; + } + if header :mime :subtype :anychild "Content-Type" "plain" { + discard; + } + if header :anychild :mime :contenttype "Content-Type" "text/plain" { + discard; + } + if header :mime :param ["frop", "friep"] :anychild "Content-Type" "frml" { + discard; + } + } +} diff --git a/pigeonhole/tests/extensions/mime/exists.svtest b/pigeonhole/tests/extensions/mime/exists.svtest new file mode 100644 index 0000000..517deeb --- /dev/null +++ b/pigeonhole/tests/extensions/mime/exists.svtest @@ -0,0 +1,237 @@ +require "vnd.dovecot.testsuite"; +require "mime"; +require "foreverypart"; + +test_set "message" text: +From: stephan@example.org +To: nico@vestingbar.bl +Subject: Test message +Date: Wed, 29 Jul 2009 18:21:44 +0300 +X-Spam-Status: Not Spam +Resent-To: nico@frop.example.com + +Test! +. +; + +/* + * One header + */ + +test "One header" { + if not exists :mime :anychild "from" { + test_fail "exists test missed from header"; + } + + if exists :mime :anychild "x-nonsense" { + test_fail "exists test found non-existent header"; + } +} + +/* + * One header - foreverypart + */ + +test "One header - foreverypart" { + foreverypart { + if not exists :mime :anychild "from" { + test_fail "exists test missed from header"; + } + + if exists :mime :anychild "x-nonsense" { + test_fail "exists test found non-existent header"; + } + } +} + +/* + * Two headers + */ + +test "Two headers" { + if not exists :mime :anychild ["from","to"] { + test_fail "exists test missed from or to header"; + } + + if exists :mime :anychild ["from","x-nonsense"] { + test_fail "exists test found non-existent header (1)"; + } + + if exists :mime :anychild ["x-nonsense","to"] { + test_fail "exists test found non-existent header (2)"; + } + + if exists :mime :anychild ["x-nonsense","x-nonsense2"] { + test_fail "exists test found non-existent header (3)"; + } +} + +/* + * Two headers - foreverypart + */ + +test "Two headers - foreverypart" { + foreverypart { + if not exists :mime :anychild ["from","to"] { + test_fail "exists test missed from or to header"; + } + + if exists :mime :anychild ["from","x-nonsense"] { + test_fail "exists test found non-existent header (1)"; + } + + if exists :mime :anychild ["x-nonsense","to"] { + test_fail "exists test found non-existent header (2)"; + } + + if exists :mime :anychild ["x-nonsense","x-nonsense2"] { + test_fail "exists test found non-existent header (3)"; + } + } +} + +/* + * Three headers + */ + +test "Three headers" { + if not exists :mime :anychild ["Subject","date","resent-to"] { + test_fail "exists test missed subject, date or resent-to header"; + } + + if exists :mime :anychild ["x-nonsense","date","resent-to"] { + test_fail "exists test found non-existent header (1)"; + } + + if exists :mime :anychild ["subject", "x-nonsense","resent-to"] { + test_fail "exists test found non-existent header (2)"; + } + + if exists :mime :anychild ["subject","date","x-nonsense"] { + test_fail "exists test found non-existent header (3)"; + } + + if exists :mime :anychild ["subject", "x-nonsense","x-nonsense2"] { + test_fail "exists test found non-existent header (4)"; + } + + if exists :mime :anychild ["x-nonsense","date","x-nonsense2"] { + test_fail "exists test found non-existent header (5)"; + } + + if exists :mime :anychild ["x-nonsense","x-nonsense2","resent-to"] { + test_fail "exists test found non-existent header (6)"; + } + + if exists :mime :anychild ["x-nonsense","x-nonsense2","x-nonsense3"] { + test_fail "exists test found non-existent header (7)"; + } +} + +/* + * Three headers - foreverypart + */ + +test "Three headers - foreverypart " { + foreverypart { + if not exists :mime :anychild ["Subject","date","resent-to"] { + test_fail "exists test missed subject, date or resent-to header"; + } + + if exists :mime :anychild ["x-nonsense","date","resent-to"] { + test_fail "exists test found non-existent header (1)"; + } + + if exists :mime :anychild ["subject", "x-nonsense","resent-to"] { + test_fail "exists test found non-existent header (2)"; + } + + if exists :mime :anychild ["subject","date","x-nonsense"] { + test_fail "exists test found non-existent header (3)"; + } + + if exists :mime :anychild ["subject", "x-nonsense","x-nonsense2"] { + test_fail "exists test found non-existent header (4)"; + } + + if exists :mime :anychild ["x-nonsense","date","x-nonsense2"] { + test_fail "exists test found non-existent header (5)"; + } + + if exists :mime :anychild ["x-nonsense","x-nonsense2","resent-to"] { + test_fail "exists test found non-existent header (6)"; + } + + if exists :mime :anychild ["x-nonsense","x-nonsense2","x-nonsense3"] { + test_fail "exists test found non-existent header (7)"; + } + } +} + +/* + * Multipart anychild + */ + +test_set "message" text: +From: Hendrik <hendrik@example.com> +To: Harrie <harrie@example.com> +Date: Sat, 11 Oct 2010 00:31:44 +0200 +Subject: Harrie is een prutser +Content-Type: multipart/mixed; boundary=AA +X-Test1: AA + +This is a multi-part message in MIME format. +--AA +Content-Type: multipart/mixed; boundary=BB +X-Test2: BB + +This is a multi-part message in MIME format. +--BB +Content-Type: text/plain; charset="us-ascii" +X-Test3: CC + +Hello + +--BB +Content-Type: text/plain; charset="us-ascii" +X-Test4: DD + +Hello again + +--BB-- +This is the end of MIME multipart. + +--AA +Content-Type: text/plain; charset="us-ascii" +X-Test5: EE + +And again + +--AA-- +This is the end of MIME multipart. +. +; + +test "Multipart anychild" { + if not exists :mime :anychild "X-Test1" { + test_fail "X-Test1 header does exist"; + } + if not exists :mime :anychild "X-Test2" { + test_fail "X-Test2 header does exist"; + } + if not exists :mime :anychild "X-Test3" { + test_fail "X-Test3 header does exist"; + } + if not exists :mime :anychild "X-Test4" { + test_fail "X-Test4 header does exist"; + } + if not exists :mime :anychild "X-Test5" { + test_fail "X-Test5 header does exist"; + } + if not exists :mime :anychild + ["X-Test1", "X-Test2", "X-Test3", "X-Test4", "X-Test5"] { + test_fail "Not all headers exist"; + } +} + + diff --git a/pigeonhole/tests/extensions/mime/extracttext.svtest b/pigeonhole/tests/extensions/mime/extracttext.svtest new file mode 100644 index 0000000..510a52b --- /dev/null +++ b/pigeonhole/tests/extensions/mime/extracttext.svtest @@ -0,0 +1,143 @@ +require "vnd.dovecot.testsuite"; +require "foreverypart"; +require "variables"; +require "extracttext"; + +test_set "message" text: +From: Hendrik <hendrik@example.com> +To: Harrie <harrie@example.com> +Date: Sat, 11 Oct 2010 00:31:44 +0200 +Subject: Harrie is een prutser +Content-Type: multipart/mixed; boundary=AA + +This is a multi-part message in MIME format. +--AA +Content-Type: multipart/mixed; boundary=BB + +This is a multi-part message in MIME format. +--BB +Content-Type: text/plain; charset="us-ascii" + +This is the first message part containing +plain text. + +--BB +Content-Type: text/plain; charset="us-ascii" + +This is another plain text message part. + +--BB-- +This is the end of MIME multipart. + +--AA +Content-Type: text/html; charset="us-ascii" + +<html> +<body>This is a piece of HTML text.</body> +</html> + +--AA-- +This is the end of MIME multipart. +. +; + +test "Basic" { + set "a" "a"; + foreverypart { + extracttext "b"; + if string "${a}" "aaa" { + if not string :contains "${b}" "first" { + test_fail "bad content extracted: ${b}"; + } + } elsif string "${a}" "aaaa" { + if not string :contains "${b}" "another" { + test_fail "bad content extracted: ${b}"; + } + } elsif string "${a}" "aaaaa" { + if not string :contains "${b}" "HTML text" { + test_fail "bad content extracted: ${b}"; + } + if string :contains "${b}" "<html>" { + test_fail "content extracted html: ${b}"; + } + } + set "a" "a${a}"; + } + if not string "${a}" "aaaaaa" { + set :length "parts" "${a}"; + test_fail "bad number of parts parsed: ${parts}"; + } +} + +test_set "message" text: +From: <stephan@example.com> +To: <frop@example.com> +Subject: Frop! + +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +. +; + +test "First - less" { + foreverypart { + extracttext :first 20 "data"; + if not string "${data}" "FROP! FROP! FROP! FR" { + test_fail "Bad data extracted"; + } + + extracttext :length :first 100 "data_len"; + if not string "${data_len}" "100" { + test_fail "Bad number of bytes extracted"; + } + } +} + +test_set "message" text: +From: <stephan@example.com> +To: <frop@example.com> +Subject: Frop! + +FROP! FROP! FROP! FROP! +. +; + +test "First - more" { + foreverypart { + extracttext :first 100 "data"; + if not string :matches "${data}" "FROP! FROP! FROP! FROP!*" { + test_fail "Bad data extracted"; + } + } +} + +test_set "message" text: +From: <stephan@example.com> +To: <frop@example.com> +Subject: Frop! + +FROP! FROP! FROP! FROP! +. +; + +test "Modifier" { + foreverypart { + extracttext :lower :upperfirst "data"; + if not string :matches "${data}" "Frop! frop! frop! frop!*" { + test_fail "Bad data extracted"; + } + } +} + + + diff --git a/pigeonhole/tests/extensions/mime/foreverypart.svtest b/pigeonhole/tests/extensions/mime/foreverypart.svtest new file mode 100644 index 0000000..08907c9 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/foreverypart.svtest @@ -0,0 +1,178 @@ +require "vnd.dovecot.testsuite"; +require "relational"; +require "foreverypart"; +require "mime"; +require "variables"; +require "include"; + +test_set "message" text: +From: Hendrik <hendrik@example.com> +To: Harrie <harrie@example.com> +Date: Sat, 11 Oct 2010 00:31:44 +0200 +Subject: Harrie is een prutser +Content-Type: multipart/mixed; boundary=AA +X-Test: AA + +This is a multi-part message in MIME format. +--AA +Content-Type: multipart/mixed; boundary=BB +X-Test: BB + +This is a multi-part message in MIME format. +--BB +Content-Type: text/plain; charset="us-ascii" +X-Test: CC + +Hello + +--BB +Content-Type: text/plain; charset="us-ascii" +X-Test: DD + +Hello again + +--BB-- +This is the end of MIME multipart. + +--AA +Content-Type: text/plain; charset="us-ascii" +X-Test: EE + +And again + +--AA-- +This is the end of MIME multipart. +. +; + +test "Single loop" { + set "a" "a"; + foreverypart { + set :length "la" "${a}"; + + if string "${a}" "a" { + if not header :mime "X-Test" "AA" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aa" { + if not header :mime "X-Test" "BB" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaa" { + if not header :mime "X-Test" "CC" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaa" { + if not header :mime "X-Test" "DD" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaaa" { + if not header :mime "X-Test" "EE" { + test_fail "wrong header extracted (${la})"; + } + } + set "a" "a${a}"; + } +} + +test "Double loop" { + set "a" "a"; + foreverypart { + set :length "la" "${a}"; + + if string "${a}" "a" { + if not header :mime "X-Test" "AA" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaaaa" { + if not header :mime "X-Test" "BB" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaaaaaaa" { + if not header :mime "X-Test" "CC" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaaaaaaaa" { + if not header :mime "X-Test" "DD" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaaaaaaaaa" { + if not header :mime "X-Test" "EE" { + test_fail "wrong header extracted (${la})"; + } + } + + set "a" "a${a}"; + + foreverypart { + set :length "la" "${a}"; + + if string "${a}" "aa" { + if not header :mime "X-Test" "BB" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaa" { + if not header :mime "X-Test" "CC" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaa" { + if not header :mime "X-Test" "DD" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaaa" { + if not header :mime "X-Test" "EE" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaaaaa" { + if not header :mime "X-Test" "CC" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaaaaaa" { + if not header :mime "X-Test" "DD" { + test_fail "wrong header extracted (${la})"; + } + } + set "a" "a${a}"; + } + } +} + +test "Double loop - include" { + global "in"; + global "error"; + set "in" "a"; + foreverypart { + set :length "la" "${in}"; + + if string "${in}" "in" { + if not header :mime "X-Test" "AA" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${in}" "aaaaaa" { + if not header :mime "X-Test" "BB" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${in}" "aaaaaaaaa" { + if not header :mime "X-Test" "CC" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${in}" "aaaaaaaaaa" { + if not header :mime "X-Test" "DD" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${in}" "aaaaaaaaaaa" { + if not header :mime "X-Test" "EE" { + test_fail "wrong header extracted (${la})"; + } + } + + set "in" "a${in}"; + + include "include-foreverypart"; + + if not string "${error}" "" { + test_fail "INCLUDED: ${error}"; + } + } +} + diff --git a/pigeonhole/tests/extensions/mime/header.svtest b/pigeonhole/tests/extensions/mime/header.svtest new file mode 100644 index 0000000..48cd9e4 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/header.svtest @@ -0,0 +1,444 @@ +require "vnd.dovecot.testsuite"; +require "variables"; +require "foreverypart"; +require "mime"; + +/* + * Basic functionality + */ + +test_set "message" text: +From: stephan@example.com +To: nico@nl.example.com, harry@de.example.com +Subject: Frobnitzm +Comments: This is nonsense. +Keywords: nonsense, strange, testing +X-Spam: Yes + +Test. +. +; + +test "Basic functionality" { + /* Must match */ + if not header :mime :anychild :contains ["Subject", "Comments"] "Frobnitzm" { + test_fail "failed to match header (1)"; + } + + if not header :mime :anychild :contains ["Subject", "Comments"] "nonsense" { + test_fail "failed to match header(2)"; + } + + if not header :mime :anychild :matches "Keywords" "*, strange, *" { + test_fail "failed to match header (3)"; + } + + if not header :mime :anychild :is "Comments" "This is nonsense." { + test_fail "failed to match header (4)"; + } + + /* Must not match */ + if header :mime :anychild ["subject", "comments", "keywords"] "idiotic" { + test_fail "matched nonsense"; + } + + /* Match first key */ + if not header :mime :anychild :contains ["keywords"] ["strange", "snot", "vreemd"] { + test_fail "failed to match first key"; + } + + /* Match second key */ + if not header :mime :anychild :contains ["keywords"] ["raar", "strange", "vreemd"] { + test_fail "failed to match second key"; + } + + /* Match last key */ + if not header :mime :anychild :contains ["keywords"] ["raar", "snot", "strange"] { + test_fail "failed to match last key"; + } + + /* First header */ + if not header :mime :anychild :contains ["keywords", "subject"] + ["raar", "strange", "vreemd"] { + test_fail "failed to match first header"; + } + + /* Second header */ + if not header :mime :anychild :contains ["subject", "keywords"] + ["raar", "strange", "vreemd"] { + test_fail "failed to match second header"; + } +} + +/* + * Basic functionality - foreverypart + */ + +test "Basic functionality - foreverypart" { + foreverypart { + /* Must match */ + if not header :mime :anychild :contains ["Subject", "Comments"] "Frobnitzm" { + test_fail "failed to match header (1)"; + } + + if not header :mime :anychild :contains ["Subject", "Comments"] "nonsense" { + test_fail "failed to match header(2)"; + } + + if not header :mime :anychild :matches "Keywords" "*, strange, *" { + test_fail "failed to match header (3)"; + } + + if not header :mime :anychild :is "Comments" "This is nonsense." { + test_fail "failed to match header (4)"; + } + + /* Must not match */ + if header :mime :anychild ["subject", "comments", "keywords"] "idiotic" { + test_fail "matched nonsense"; + } + + /* Match first key */ + if not header :mime :anychild :contains ["keywords"] ["strange", "snot", "vreemd"] { + test_fail "failed to match first key"; + } + + /* Match second key */ + if not header :mime :anychild :contains ["keywords"] ["raar", "strange", "vreemd"] { + test_fail "failed to match second key"; + } + + /* Match last key */ + if not header :mime :anychild :contains ["keywords"] ["raar", "snot", "strange"] { + test_fail "failed to match last key"; + } + + /* First header */ + if not header :mime :anychild :contains ["keywords", "subject"] + ["raar", "strange", "vreemd"] { + test_fail "failed to match first header"; + } + + /* Second header */ + if not header :mime :anychild :contains ["subject", "keywords"] + ["raar", "strange", "vreemd"] { + test_fail "failed to match second header"; + } + } +} + +/* + * Matching empty key + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.com +X-Caffeine: C8H10N4O2 +Subject: I need coffee! +Comments: + +Text +. +; + +test "Matching empty key" { + if header :mime :anychild :is "X-Caffeine" "" { + test_fail ":is-matched non-empty header with empty string"; + } + + if not header :mime :anychild :contains "X-Caffeine" "" { + test_fail "failed to match existing header with empty string"; + } + + if not header :mime :anychild :is "comments" "" { + test_fail "failed to match empty header :mime :anychild with empty string"; + } + + if header :mime :anychild :contains "X-Nonsense" "" { + test_fail ":contains-matched non-existent header with empty string"; + } +} + +/* + * Matching empty key - foreverypart + */ + +test "Matching empty key - foreverypart" { + foreverypart { + if header :mime :anychild :is "X-Caffeine" "" { + test_fail ":is-matched non-empty header with empty string"; + } + + if not header :mime :anychild :contains "X-Caffeine" "" { + test_fail "failed to match existing header with empty string"; + } + + if not header :mime :anychild :is "comments" "" { + test_fail "failed to match empty header :mime :anychild with empty string"; + } + + if header :mime :anychild :contains "X-Nonsense" "" { + test_fail ":contains-matched non-existent header with empty string"; + } + } +} + +/* + * Ignoring whitespace + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.com +Subject: Help +X-A: Text +X-B: Text + +Text +. +; + +test "Ignoring whitespace" { + if not header :mime :anychild :is "x-a" "Text" { + if header :mime :anychild :matches "x-a" "*" { + set "header" "${1}"; + } + test_fail "header :mime :anychild test does not strip leading whitespace (header=`${header}`)"; + } + + if not header :mime :anychild :is "x-b" "Text" { + if header :mime :anychild :matches "x-b" "*" { + set "header" "${1}"; + } + test_fail "header :mime :anychild test does not strip trailing whitespace (header=`${header}`)"; + } + + if not header :mime :anychild :is "subject" "Help" { + if header :mime :anychild :matches "subject" "*" { + set "header" "${1}"; + } + test_fail "header :mime :anychild test does not strip both leading and trailing whitespace (header=`${header}`)"; + } +} + +/* + * Ignoring whitespace - foreverypart + */ + +test "Ignoring whitespace - foreverypart" { + foreverypart { + if not header :mime :anychild :is "x-a" "Text" { + if header :mime :anychild :matches "x-a" "*" { + set "header" "${1}"; + } + test_fail "header :mime :anychild test does not strip leading whitespace (header=`${header}`)"; + } + + if not header :mime :anychild :is "x-b" "Text" { + if header :mime :anychild :matches "x-b" "*" { + set "header" "${1}"; + } + test_fail "header :mime :anychild test does not strip trailing whitespace (header=`${header}`)"; + } + + if not header :mime :anychild :is "subject" "Help" { + if header :mime :anychild :matches "subject" "*" { + set "header" "${1}"; + } + test_fail "header :mime :anychild test does not strip both leading and trailing whitespace (header=`${header}`)"; + } + } +} + +/* + * Absent or empty header + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.com +CC: harry@nonsense.ex +Subject: +Comments: + +Text +. +; + +test "Absent or empty header" { + if not header :mime :anychild :matches "Cc" "?*" { + test_fail "CC header is not absent or empty"; + } + + if header :mime :anychild :matches "Subject" "?*" { + test_fail "Subject header is empty, but matched otherwise"; + } + + if header :mime :anychild :matches "Comment" "?*" { + test_fail "Comment header is empty, but matched otherwise"; + } +} + +/* + * Absent or empty header - foreverypart + */ + +test "Absent or empty header - foreverypart" { + foreverypart { + if not header :mime :anychild :matches "Cc" "?*" { + test_fail "CC header is not absent or empty"; + } + + if header :mime :anychild :matches "Subject" "?*" { + test_fail "Subject header is empty, but matched otherwise"; + } + + if header :mime :anychild :matches "Comment" "?*" { + test_fail "Comment header is empty, but matched otherwise"; + } + } +} + + +/* + * Invalid header name + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.com +Subject: Valid message +X-Multiline: This is a multi-line + header body, which should be + unfolded correctly. + +Text +. +; + +test "Invalid header name" { + if header :mime :anychild :contains "subject:" "" { + test_fail "matched invalid header name"; + } + + if header :mime :anychild :contains "to!" "" { + test_fail "matched invalid header name"; + } +} + +/* + * Invalid header name - foreverypart + */ + +test "Invalid header name - foreverypart" { + foreverypart { + if header :mime :anychild :contains "subject:" "" { + test_fail "matched invalid header name"; + } + + if header :mime :anychild :contains "to!" "" { + test_fail "matched invalid header name"; + } + } +} + +/* + * Folded headers + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.com +Subject: Not enough space on a line! +X-Multiline: This is a multi-line + header body, which should be + unfolded correctly. + +Text +. +; + +test "Folded headers" { + if not header :mime :anychild :is "x-multiline" + "This is a multi-line header body, which should be unfolded correctly." { + test_fail "failed to properly unfold folded header."; + } +} + +/* + * Folded headers - foreverypart + */ + +test "Folded headers - foreverypart" { + foreverypart { + if not header :mime :anychild :is "x-multiline" + "This is a multi-line header body, which should be unfolded correctly." { + test_fail "failed to properly unfold folded header."; + } + } +} + +/* + * Multipart anychild + */ + +test_set "message" text: +From: Hendrik <hendrik@example.com> +To: Harrie <harrie@example.com> +Date: Sat, 11 Oct 2010 00:31:44 +0200 +Subject: Harrie is een prutser +Content-Type: multipart/mixed; boundary=AA +X-Test: AA + +This is a multi-part message in MIME format. +--AA +Content-Type: multipart/mixed; boundary=BB +X-Test: BB + +This is a multi-part message in MIME format. +--BB +Content-Type: text/plain; charset="us-ascii" +X-Test: CC + +Hello + +--BB +Content-Type: text/plain; charset="us-ascii" +X-Test: DD + +Hello again + +--BB-- +This is the end of MIME multipart. + +--AA +Content-Type: text/plain; charset="us-ascii" +X-Test: EE + +And again + +--AA-- +This is the end of MIME multipart. +. +; + +test "Multipart anychild" { + if not header :mime :anychild "X-Test" "AA" { + test_fail "No AA"; + } + if not header :mime :anychild "X-Test" "BB" { + test_fail "No BB"; + } + if not header :mime :anychild "X-Test" "CC" { + test_fail "No CC"; + } + if not header :mime :anychild "X-Test" "DD" { + test_fail "No DD"; + } + if not header :mime :anychild "X-Test" "EE" { + test_fail "No EE"; + } +} + + diff --git a/pigeonhole/tests/extensions/mime/included/include-foreverypart.sieve b/pigeonhole/tests/extensions/mime/included/include-foreverypart.sieve new file mode 100644 index 0000000..f1b1b16 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/included/include-foreverypart.sieve @@ -0,0 +1,44 @@ +require "include"; +require "foreverypart"; +require "mime"; +require "variables"; + +global "in"; +global "error"; + +foreverypart { + set :length "la" "${in}"; + + if string "${in}" "aa" { + if not header :mime "X-Test" "BB" { + set "error" "wrong header extracted (${la})"; + return; + } + } elsif string "${in}" "aaa" { + if not header :mime "X-Test" "CC" { + set "error" "wrong header extracted (${la})"; + return; + } + } elsif string "${in}" "aaaa" { + if not header :mime "X-Test" "DD" { + set "error" "wrong header extracted (${la})"; + return; + } + } elsif string "${in}" "aaaaa" { + if not header :mime "X-Test" "EE" { + set "error" "wrong header extracted (${la})"; + return; + } + } elsif string "${in}" "aaaaaaa" { + if not header :mime "X-Test" "CC" { + set "error" "wrong header extracted (${la})"; + return; + } + } elsif string "${in}" "aaaaaaaa" { + if not header :mime "X-Test" "DD" { + set "error" "wrong header extracted (${la})"; + return; + } + } + set "in" "a${in}"; +} diff --git a/pigeonhole/tests/extensions/mime/included/include-loop-2.sieve b/pigeonhole/tests/extensions/mime/included/include-loop-2.sieve new file mode 100644 index 0000000..80c5884 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/included/include-loop-2.sieve @@ -0,0 +1,6 @@ +require "foreverypart"; +require "include"; + +foreverypart :name "friep" { + include "include-loop-3"; +} diff --git a/pigeonhole/tests/extensions/mime/included/include-loop-3.sieve b/pigeonhole/tests/extensions/mime/included/include-loop-3.sieve new file mode 100644 index 0000000..228a8bc --- /dev/null +++ b/pigeonhole/tests/extensions/mime/included/include-loop-3.sieve @@ -0,0 +1,6 @@ +require "foreverypart"; +require "include"; + +foreverypart :name "frml" { + include "include-loop-4"; +} diff --git a/pigeonhole/tests/extensions/mime/included/include-loop-4.sieve b/pigeonhole/tests/extensions/mime/included/include-loop-4.sieve new file mode 100644 index 0000000..00dad84 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/included/include-loop-4.sieve @@ -0,0 +1,6 @@ +require "foreverypart"; +require "include"; + +foreverypart { + include "include-loop-5"; +} diff --git a/pigeonhole/tests/extensions/mime/included/include-loop-5.sieve b/pigeonhole/tests/extensions/mime/included/include-loop-5.sieve new file mode 100644 index 0000000..e22b21c --- /dev/null +++ b/pigeonhole/tests/extensions/mime/included/include-loop-5.sieve @@ -0,0 +1,9 @@ +require "foreverypart"; +require "include"; +require "mime"; + +foreverypart { + if header :mime :subtype "content-type" "plain" { + break; + } +} diff --git a/pigeonhole/tests/extensions/regex/basic.svtest b/pigeonhole/tests/extensions/regex/basic.svtest new file mode 100644 index 0000000..9417434 --- /dev/null +++ b/pigeonhole/tests/extensions/regex/basic.svtest @@ -0,0 +1,51 @@ +require "vnd.dovecot.testsuite"; + +require "regex"; +require "variables"; + +test_set "message" text: +From: stephan+sieve@friep.example.com +To: tss@example.net, nico@nl.example.com, sirius@fi.example.com +Subject: Test + +Test message. +. +; + +test "Basic example" { + if not address :regex :comparator "i;ascii-casemap" "from" [ + "stephan(\\+.*)?@it\\.example\\.com", + "stephan(\\+.*)?@friep\\.example\\.com" + ] { + test_fail "failed to match"; + } +} + +test "No values" { + if header :regex "cc" [".*\\.com", ".*\\.nl"] { + test_fail "matched inappropriately"; + } +} + + +test "More values" { + if address :regex "to" [".*\\.uk", ".*\\.nl", ".*\\.tk"] { + test_fail "matched inappropriately"; + } + + if not address :regex "to" [".*\\.uk", ".*\\.nl", ".*\\.tk", ".*fi\\..*"] { + test_fail "failed to match last"; + } +} + +test "Variable regex" { + set "regex" "stephan[+](sieve)@friep.example.com"; + + if not header :regex "from" "${regex}" { + test_fail "failed to match variable regex"; + } + + if not string "${1}" "sieve" { + test_fail "failed to extract proper match value from variable regex"; + } +} diff --git a/pigeonhole/tests/extensions/regex/errors.svtest b/pigeonhole/tests/extensions/regex/errors.svtest new file mode 100644 index 0000000..2e0ebe0 --- /dev/null +++ b/pigeonhole/tests/extensions/regex/errors.svtest @@ -0,0 +1,29 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +test "Compile errors" { + if test_script_compile "errors/compile.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "5" { + test_fail "wrong number of errors reported"; + } +} + +test "Runtime errors" { + if not test_script_compile "errors/runtime.sieve" { + test_fail "failed to compile"; + } + + if not test_script_run { + test_fail "script should have run fine"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "1" { + test_fail "wrong number of errors reported"; + } +} + diff --git a/pigeonhole/tests/extensions/regex/errors/compile.sieve b/pigeonhole/tests/extensions/regex/errors/compile.sieve new file mode 100644 index 0000000..5ddaaf8 --- /dev/null +++ b/pigeonhole/tests/extensions/regex/errors/compile.sieve @@ -0,0 +1,25 @@ +require "regex"; +require "comparator-i;ascii-numeric"; +require "envelope"; + +if address :regex :comparator "i;ascii-numeric" "from" "sirius(\\+.*)?@friep\\.example\\.com" { + keep; + stop; +} + +if address :regex "from" "sirius(+\\+.*)?@friep\\.example\\.com" { + keep; + stop; +} + +if header :regex "from" "sirius(\\+.*)?@friep\\.ex[]ample.com" { + keep; + stop; +} + +if envelope :regex "from" "sirius(\\+.*)?@friep\\.ex[]ample.com" { + keep; + stop; +} + +discard; diff --git a/pigeonhole/tests/extensions/regex/errors/runtime.sieve b/pigeonhole/tests/extensions/regex/errors/runtime.sieve new file mode 100644 index 0000000..2d0bf66 --- /dev/null +++ b/pigeonhole/tests/extensions/regex/errors/runtime.sieve @@ -0,0 +1,9 @@ +require "regex"; +require "variables"; +require "fileinto"; + +set "regex" "["; + +if header :regex "to" "${regex}" { + fileinto "frop"; +} diff --git a/pigeonhole/tests/extensions/regex/match-values.svtest b/pigeonhole/tests/extensions/regex/match-values.svtest new file mode 100644 index 0000000..18b7404 --- /dev/null +++ b/pigeonhole/tests/extensions/regex/match-values.svtest @@ -0,0 +1,72 @@ +require "vnd.dovecot.testsuite"; + +require "regex"; +require "variables"; + +test_set "message" text: +From: Andy Howell <AndyHowell@example.com> +Sender: antlr-interest-bounces@ant.example.com +To: Stephan Bosch <stephan@example.org> +Subject: [Dovecot] Sieve regex match problem + +Hi, + +I is broken. +. +; + +test "Basic match values 1" { + if header :regex ["Sender"] ["([^-@]*)-([^-@]*)(-bounces)?@ant.example.com"] { + + if not string :is "${1}" "antlr" { + test_fail "first match value is not correct"; + } + + if not string :is "${2}" "interest" { + test_fail "second match value is not correct"; + } + + if not string :is "${3}" "-bounces" { + test_fail "third match value is not correct"; + } + + if string :is "${4}" "-bounces" { + test_fail "fourth match contains third value"; + } + } else { + test_fail "failed to match"; + } +} + +test "Basic match values 2" { + if header :regex ["Sender"] ["(.*>[ \\t]*,?[ \\t]*)?([^-@]*)-([^-@]*)(-bounces)?@ant.example.com"] { + + if not string :is "${1}" "" { + test_fail "first match value is not correct: ${1}"; + } + + if not string :is "${2}" "antlr" { + test_fail "second match value is not correct: ${2}"; + } + + if not string :is "${3}" "interest" { + test_fail "third match value is not correct: ${3}"; + } + + if not string :is "${4}" "-bounces" { + test_fail "fourth match value is not correct: ${4}"; + } + + if string :is "${5}" "-bounces" { + test_fail "fifth match contains fourth value: ${5}"; + } + } else { + test_fail "failed to match"; + } +} + + + + + + diff --git a/pigeonhole/tests/extensions/reject/execute.svtest b/pigeonhole/tests/extensions/reject/execute.svtest new file mode 100644 index 0000000..20a0bdf --- /dev/null +++ b/pigeonhole/tests/extensions/reject/execute.svtest @@ -0,0 +1,34 @@ +require "vnd.dovecot.testsuite"; +require "relational"; +require "comparator-i;ascii-numeric"; + +test_set "message" text: +To: nico@frop.example.org +From: stephan@example.org +Subject: Test + +Test. +. +; + +test "Execute" { + if not test_script_compile "execute/basic.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script run failed"; + } + + if not test_result_action :count "eq" :comparator "i;ascii-numeric" "1" { + test_fail "invalid number of actions in result"; + } + + if not test_result_action :index 1 "reject" { + test_fail "reject action missing from result"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } +} diff --git a/pigeonhole/tests/extensions/reject/execute/basic.sieve b/pigeonhole/tests/extensions/reject/execute/basic.sieve new file mode 100644 index 0000000..d3b7dc9 --- /dev/null +++ b/pigeonhole/tests/extensions/reject/execute/basic.sieve @@ -0,0 +1,8 @@ +require "reject"; + +if address :contains "to" "frop.example" { + reject "Don't send unrequested messages."; + stop; +} + +keep; diff --git a/pigeonhole/tests/extensions/reject/smtp.svtest b/pigeonhole/tests/extensions/reject/smtp.svtest new file mode 100644 index 0000000..8cbf77c --- /dev/null +++ b/pigeonhole/tests/extensions/reject/smtp.svtest @@ -0,0 +1,56 @@ +require "vnd.dovecot.testsuite"; +require "envelope"; +require "reject"; + +test_set "message" text: +From: stephan@example.org +To: tss@example.net +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "timo@example.net"; + +test "Basic" { + reject "I don't want your mail"; + + if not test_result_execute { + test_fail "failed to execute reject"; + } + + test_message :smtp 0; + + if not address :is "to" "sirius@example.org" { + test_fail "to address incorrect"; + } + + if not header :contains "from" "Postmaster" { + test_fail "from address incorrect"; + } + + if not envelope :is "to" "sirius@example.org" { + test_fail "envelope recipient incorrect"; + } + + if not envelope :is "from" "" { + test_fail "envelope sender not null"; + } +} + +test_result_reset; +test_set "envelope.from" "<>"; + +test "Null Sender" { + reject "I don't want your mail"; + + if not test_result_execute { + test_fail "failed to execute reject"; + } + + if test_message :smtp 0 { + test_fail "reject sent message to NULL sender"; + } +} diff --git a/pigeonhole/tests/extensions/relational/basic.svtest b/pigeonhole/tests/extensions/relational/basic.svtest new file mode 100644 index 0000000..288661a --- /dev/null +++ b/pigeonhole/tests/extensions/relational/basic.svtest @@ -0,0 +1,178 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +/* + * Test message + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Cc: frop@example.org +CC: timo@example.org +X-Spam-Score: 300 +X-Nonsense: 1000 +X-Nonsense: 20 +X-Alpha: abcdzyx +X-Count: a +X-Count: b +X-Count: c +X-Count: d +X-Count: e +X-Count: f +X-Count: g +X-Count: h +X-Count: i +X-Count: j +X-Count: k +X-Count: l +X-Count: m +X-Count: n +X-Count: o +X-Count: p +X-Count: q +X-Count: r +X-Count: s +X-Count: t +X-Count: u +X-Count: v +X-Count: w +X-Count: x +X-Count: y +X-Count: z +Subject: Test +Comment: + +Test! +. +; + +/* + * Empty strings + */ + +test "Value \"\" eq 40 (vs)" { + if header :value "eq" :comparator "i;ascii-numeric" "comment" "40" { + test_fail ":value matched empty string with i;ascii-numeric"; + } + + if header :value "gt" :comparator "i;ascii-numeric" "x-spam-score" "" { + test_fail ":value 300 exceeded empty string with i;ascii-numeric"; + } + + if header :value "gt" :comparator "i;ascii-numeric" "x-spam-score" "" { + test_fail ":count exceeded empty string with i;ascii-numeric"; + } +} + +/* + * Match type :value + */ + +test "Value 300 eq 2" { + if header :value "eq" :comparator "i;ascii-numeric" "x-spam-score" "2" { + test_fail "should not have matched"; + } +} + +test "Value 300 lt 2" { + if header :value "lt" :comparator "i;ascii-numeric" "x-spam-score" "2" { + test_fail "should not have matched"; + } +} + +test "Value 300 le 300" { + if not header :value "le" :comparator "i;ascii-numeric" "x-spam-score" "300" { + test_fail "should have matched"; + } +} + +test "Value 300 le 302" { + if not header :value "le" :comparator "i;ascii-numeric" "x-spam-score" "302" { + test_fail "should have matched"; + } +} + +test "Value 302 le 00302" { + if not header :value "le" :comparator "i;ascii-numeric" "x-spam-score" "00302" { + test_fail "should have matched"; + } +} + +test "Value {1000,20} le 300" { + if not header :value "le" :comparator "i;ascii-numeric" "x-nonsense" "300" { + test_fail "should have matched"; + } +} + +test "Value {1000,20} lt 3" { + if header :value "lt" :comparator "i;ascii-numeric" "x-nonsense" "3" { + test_fail "should not have matched"; + } +} + +test "Value {1000,20} gt 3000" { + if header :value "gt" :comparator "i;ascii-numeric" "x-nonsense" "3000" { + test_fail "should not have matched"; + } +} + +test "Value {1000,20} gt {3000,30}" { + if not header :value "gt" :comparator "i;ascii-numeric" "x-nonsense" ["3000","30"] { + test_fail "should have matched"; + } +} + +test "Value {1000,20} lt {3, 19})" { + if header :value "lt" :comparator "i;ascii-numeric" "x-nonsense" ["3","19"] { + test_fail "should not have matched"; + } +} + +test "Value {1000,20} gt {3000,1001}" { + if header :value "gt" :comparator "i;ascii-numeric" "x-nonsense" ["3000","1001"] { + test_fail "should not have matched"; + } +} + +test "Value abcdzyz gt aaaaaaa" { + if not header :value "gt" :comparator "i;octet" "x-alpha" "aaaaaaa" { + test_fail "should have matched"; + } +} + +/* + * Match type :count + */ + +test "Count 2 ne 2" { + if header :count "ne" :comparator "i;ascii-numeric" "cc" "2" { + test_fail "should not have matched"; + } +} + +test "Count 2 ge 2" { + if not header :count "ge" :comparator "i;ascii-numeric" "cc" "2" { + test_fail "should have matched"; + } +} + +test "Count 2 ge 002" { + if not header :count "ge" :comparator "i;ascii-numeric" "cc" "002" { + test_fail "should have matched"; + } +} + +test "Count 26 lt {4,5,6,10,20}" { + if header :count "lt" :comparator "i;ascii-numeric" "x-count" ["4","5","6","10","20"] { + test_fail "should not have matched"; + } +} + +test "Count 26 lt {4,5,6,10,20,100}" { + if not header :count "lt" :comparator "i;ascii-numeric" "x-count" ["4","5","6","10","20","100"] { + test_fail "should have matched"; + } +} diff --git a/pigeonhole/tests/extensions/relational/comparators.svtest b/pigeonhole/tests/extensions/relational/comparators.svtest new file mode 100644 index 0000000..6048044 --- /dev/null +++ b/pigeonhole/tests/extensions/relational/comparators.svtest @@ -0,0 +1,258 @@ +require "vnd.dovecot.testsuite"; +require "variables"; +require "relational"; +require "comparator-i;ascii-numeric"; + +/* + * Comparator i;octet + */ + +test "i;octet" { + if not string :comparator "i;octet" :value "eq" "" "" { + test_fail "not '' eq ''"; + } + + if not string :comparator "i;octet" :value "gt" "a" "" { + test_fail "not 'a' gt ''"; + } + + if not string :comparator "i;octet" :value "lt" "" "a" { + test_fail "not '' lt 'a'"; + } + + if not string :comparator "i;octet" :value "gt" "ab" "a" { + test_fail "not 'ab' gt 'a'"; + } + + if not string :comparator "i;octet" :value "lt" "a" "ab" { + test_fail "not 'a' lt 'ab'"; + } + + if not string :comparator "i;octet" :value "gt" "ba" "ab" { + test_fail "not 'ba' gt 'ab'"; + } + + if not string :comparator "i;octet" :value "lt" "ab" "ba" { + test_fail "not 'ab' lt 'ba'"; + } + + if not string :comparator "i;octet" :value "eq" "abcd" "abcd" { + test_fail "not 'abcd' eq 'abcd'"; + } + + if not string :comparator "i;octet" :value "lt" "abcce" "abcde" { + test_fail "not 'abcce' lt 'abcde'"; + } + + if not string :comparator "i;octet" :value "gt" "abcde" "abcce" { + test_fail "not 'abcde' gt 'abcce'"; + } + + if not string :comparator "i;octet" :value "lt" "abcce" "abcd" { + test_fail "not 'abcce' lt 'abcd'"; + } + + if not string :comparator "i;octet" :value "gt" "abcd" "abcce" { + test_fail "not 'abcd' gt 'abcce'"; + } + + if not string :comparator "i;octet" :value "lt" "Z" "b" { + test_fail "not 'Z' lt 'b'"; + } +} + +/* + * Comparator i;ascii-casemap + */ + +test "i;ascii-casemap" { + if not string :comparator "i;ascii-casemap" :value "eq" "" "" { + test_fail "not '' eq ''"; + } + + if not string :comparator "i;ascii-casemap" :value "gt" "a" "" { + test_fail "not 'a' gt ''"; + } + + if not string :comparator "i;ascii-casemap" :value "lt" "" "a" { + test_fail "not '' lt 'a'"; + } + + if not string :comparator "i;ascii-casemap" :value "gt" "ab" "a" { + test_fail "not 'ab' gt 'a'"; + } + + if not string :comparator "i;ascii-casemap" :value "lt" "a" "ab" { + test_fail "not 'a' lt 'ab'"; + } + + if not string :comparator "i;ascii-casemap" :value "gt" "ba" "ab" { + test_fail "not 'ba' gt 'ab'"; + } + + if not string :comparator "i;ascii-casemap" :value "lt" "ab" "ba" { + test_fail "not 'ab' lt 'ba'"; + } + + if not string :comparator "i;ascii-casemap" :value "eq" "abcd" "abcd" { + test_fail "not 'abcd' eq 'abcd'"; + } + + if not string :comparator "i;ascii-casemap" :value "lt" "abcce" "abcde" { + test_fail "not 'abcce' lt 'abcde'"; + } + + if not string :comparator "i;ascii-casemap" :value "gt" "abcde" "abcce" { + test_fail "not 'abcde' gt 'abcce'"; + } + + if not string :comparator "i;ascii-casemap" :value "lt" "abcce" "abcd" { + test_fail "not 'abcce' lt 'abcd'"; + } + + if not string :comparator "i;ascii-casemap" :value "gt" "abcd" "abcce" { + test_fail "not 'abcd' gt 'abcce'"; + } + + if not string :comparator "i;ascii-casemap" :value "gt" "Z" "b" { + test_fail "not 'Z' gt 'b'"; + } +} + +/* + * Comparator i;ascii-numeric + */ + +test "i;ascii-numeric" { + /* Non-digit characters; equality */ + + if not string :comparator "i;ascii-numeric" :value "eq" "" "" { + test_fail "not '' eq ''"; + } + + if not string :comparator "i;ascii-numeric" :value "eq" "a" "" { + test_fail "not 'a' eq ''"; + } + + if not string :comparator "i;ascii-numeric" :value "eq" "" "a" { + test_fail "not '' eq 'a'"; + } + + if not string :comparator "i;ascii-numeric" :value "eq" "a" "b" { + test_fail "not 'a' eq 'b'"; + } + + if not string :comparator "i;ascii-numeric" :value "eq" "b" "a" { + test_fail "not 'b' eq 'a'"; + } + + if string :comparator "i;ascii-numeric" :value "eq" "a" "0" { + test_fail "'a' eq '0'"; + } + + if string :comparator "i;ascii-numeric" :value "eq" "0" "a" { + test_fail "'0' eq 'a'"; + } + + if not string :comparator "i;ascii-numeric" :value "ne" "a" "0" { + test_fail "not 'a' ne '0'"; + } + + if not string :comparator "i;ascii-numeric" :value "ne" "0" "a" { + test_fail "not '0' ne 'a'"; + } + + /* Non-digit characters; comparison */ + + if string :comparator "i;ascii-numeric" :value "lt" "a" "0" { + test_fail "'a' lt '0'"; + } + + if not string :comparator "i;ascii-numeric" :value "lt" "0" "a" { + test_fail "not '0' lt 'a'"; + } + + if not string :comparator "i;ascii-numeric" :value "gt" "a" "0" { + test_fail "not 'a' gt '0'"; + } + + if string :comparator "i;ascii-numeric" :value "gt" "0" "a" { + test_fail "'0' gt 'a'"; + } + + if not string :comparator "i;ascii-numeric" :value "ge" "a" "0" { + test_fail "not 'a' ge '0'"; + } + + if string :comparator "i;ascii-numeric" :value "ge" "0" "a" { + test_fail "'0' ge 'a'"; + } + + if string :comparator "i;ascii-numeric" :value "le" "a" "0" { + test_fail "'a' le '0'"; + } + + if not string :comparator "i;ascii-numeric" :value "le" "0" "a" { + test_fail "not '0' le 'a'"; + } + + if not string :comparator "i;ascii-numeric" :value "eq" "0" "0" { + test_fail "not '0' eq '0'"; + } + + /* Digit characters; basic comparison */ + + if not string :comparator "i;ascii-numeric" :value "eq" "2" "2" { + test_fail "not '2' eq '2'"; + } + + if not string :comparator "i;ascii-numeric" :value "gt" "2" "1" { + test_fail "not '2' gt '1'"; + } + + if not string :comparator "i;ascii-numeric" :value "lt" "1" "2" { + test_fail "not '1' lt '2'"; + } + + if not string :comparator "i;ascii-numeric" :value "lt" "65535" "65635" { + test_fail "not '65535' lt '65635'"; + } + + if not string :comparator "i;ascii-numeric" :value "gt" "65635" "65535" { + test_fail "not '65635' gt '65535'"; + } + + /* Digit characters; leading zeros */ + + if not string :comparator "i;ascii-numeric" :value "eq" "0" "000" { + test_fail "not '0' eq '000'"; + } + + if not string :comparator "i;ascii-numeric" :value "eq" "000" "0" { + test_fail "not '0' eq '000'"; + } + + if not string :comparator "i;ascii-numeric" :value "eq" "02" "0002" { + test_fail "not '02' eq '0002'"; + } + + if not string :comparator "i;ascii-numeric" :value "eq" "0002" "02" { + test_fail "not '0002' eq '02'"; + } + + if not string :comparator "i;ascii-numeric" :value "gt" "2" "001" { + test_fail "not '2' gt '001'"; + } + + if not string :comparator "i;ascii-numeric" :value "lt" "001" "2" { + test_fail "not '001' lt '2'"; + } + + if not string :comparator "i;ascii-numeric" :value "gt" "002" "1" { + test_fail "not '002' gt '1'"; + } + + if not string :comparator "i;ascii-numeric" :value "lt" "1" "002" { + test_fail "not '1' lt '002'"; + } +} diff --git a/pigeonhole/tests/extensions/relational/errors.svtest b/pigeonhole/tests/extensions/relational/errors.svtest new file mode 100644 index 0000000..0973b98 --- /dev/null +++ b/pigeonhole/tests/extensions/relational/errors.svtest @@ -0,0 +1,33 @@ +require "vnd.dovecot.testsuite"; + +# A bit awkward to test the extension with itself +require "relational"; +require "comparator-i;ascii-numeric"; + +/* + * Syntax errors + */ + +test "Syntax errors" { + if test_script_compile "errors/syntax.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" "6" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Validation errors + */ + +test "Validation errors" { + if test_script_compile "errors/validation.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" "3" { + test_fail "wrong number of errors reported"; + } +} diff --git a/pigeonhole/tests/extensions/relational/errors/syntax.sieve b/pigeonhole/tests/extensions/relational/errors/syntax.sieve new file mode 100644 index 0000000..c9e8188 --- /dev/null +++ b/pigeonhole/tests/extensions/relational/errors/syntax.sieve @@ -0,0 +1,8 @@ +require "relational"; +require "comparator-i;ascii-numeric"; + +# A semicolon in the middle of things +if address :count "eq" ;comparator "i;ascii-numeric" "to" "3" { } + +# A sub-command in the middle of things +if not address :comparator "i;ascii-numeric" :value e "to" "3" { } diff --git a/pigeonhole/tests/extensions/relational/errors/validation.sieve b/pigeonhole/tests/extensions/relational/errors/validation.sieve new file mode 100644 index 0000000..f355097 --- /dev/null +++ b/pigeonhole/tests/extensions/relational/errors/validation.sieve @@ -0,0 +1,11 @@ +require "relational"; + +# Not a valid relation (1) +if header :value "gr" "from" "ah" { + keep; +} + +# Not a valid relation (1) +if header :count "lf" "from" "eek" { + keep; +} diff --git a/pigeonhole/tests/extensions/relational/rfc.svtest b/pigeonhole/tests/extensions/relational/rfc.svtest new file mode 100644 index 0000000..bc05516 --- /dev/null +++ b/pigeonhole/tests/extensions/relational/rfc.svtest @@ -0,0 +1,71 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +test_set "message" text: +Received: ... +Received: ... +Subject: example +To: foo@example.com, baz@example.com +CC: qux@example.com + +RFC Example +. +; + +test "Example 1" { + # The test: + + if not address :count "ge" :comparator "i;ascii-numeric" + ["to", "cc"] ["3"] { + + test_fail "should have counted three addresses"; + } + + # would evaluate to true, and the test + + if anyof ( + address :count "ge" :comparator "i;ascii-numeric" + ["to"] ["3"], + address :count "ge" :comparator "i;ascii-numeric" + ["cc"] ["3"] + ) { + + test_fail "should not have counted three addresses"; + } + + # would evaluate to false. + + # To check the number of received fields in the header, the following + # test may be used: + + if header :count "ge" :comparator "i;ascii-numeric" + ["received"] ["3"] { + + test_fail "should not have counted three received headers"; + } + + # This would evaluate to false. But + + if not header :count "ge" :comparator "i;ascii-numeric" + ["received", "subject"] ["3"] { + + test_fail "should have counted three headers"; + } + + # would evaluate to true. + + # The test: + + if header :count "ge" :comparator "i;ascii-numeric" + ["to", "cc"] ["3"] { + + test_fail "should not have counted three to or cc headers"; + } + + # will always evaluate to false on an RFC 2822 compliant message + # [RFC2822], since a message can have at most one "to" field and at + # most one "cc" field. This test counts the number of fields, not the + # number of addresses. +} diff --git a/pigeonhole/tests/extensions/spamvirustest/errors.svtest b/pigeonhole/tests/extensions/spamvirustest/errors.svtest new file mode 100644 index 0000000..7e6b794 --- /dev/null +++ b/pigeonhole/tests/extensions/spamvirustest/errors.svtest @@ -0,0 +1,15 @@ +require "vnd.dovecot.testsuite"; + +require "comparator-i;ascii-numeric"; +require "relational"; + +test "Syntax errors" { + if test_script_compile "errors/syntax-errors.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "5" { + test_fail "wrong number of errors reported"; + } +} + diff --git a/pigeonhole/tests/extensions/spamvirustest/errors/syntax-errors.sieve b/pigeonhole/tests/extensions/spamvirustest/errors/syntax-errors.sieve new file mode 100644 index 0000000..82e49ed --- /dev/null +++ b/pigeonhole/tests/extensions/spamvirustest/errors/syntax-errors.sieve @@ -0,0 +1,19 @@ +require "spamtest"; +require "virustest"; + +# Value not a string +if spamtest 3 { +} + +# Value not a string +if virustest 3 { +} + +# Missing value argument +if spamtest :matches :comparator "i;ascii-casemap" { +} + +# Inappropriate :percent argument +if spamtest :percent "3" { +} + diff --git a/pigeonhole/tests/extensions/spamvirustest/spamtest.svtest b/pigeonhole/tests/extensions/spamvirustest/spamtest.svtest new file mode 100644 index 0000000..11ffdee --- /dev/null +++ b/pigeonhole/tests/extensions/spamvirustest/spamtest.svtest @@ -0,0 +1,276 @@ +require "vnd.dovecot.testsuite"; +require "spamtest"; +require "relational"; +require "comparator-i;ascii-numeric"; +require "variables"; + +/* + * Value + */ + +test_set "message" text: +From: legitimate@example.com +To: victim@dovecot.example.net +Subject: Not spammish +X-SpamCheck: No, score=-1.6 required=5.0 autolearn=no version=3.2.5 +X-SpamCheck1: No, score=0.0 required=5.0 autolearn=no version=3.2.5 +X-SpamCheck2: No, score=1.0 required=5.0 autolearn=no version=3.2.5 +X-SpamCheck3: No, score=4.0 required=5.0 autolearn=no version=3.2.5 +X-SpamCheck4: Yes, score=5.0 required=5.0 autolearn=no version=3.2.5 +X-SpamCheck5: Yes, score=7.6 required=5.0 autolearn=no version=3.2.5 + +Test! +. +; + +test_config_set "sieve_spamtest_status_header" + "X-SpamCheck:[ \\ta-zA-Z]+, score=(-?[0-9]+.[0-9]+)"; +test_config_set "sieve_spamtest_max_header" + "X-SpamCheck:[ \\ta-zA-Z]+, score=-?[0-9]+.[0-9]+ required=(-?[0-9]+.[0-9]+)"; +test_config_set "sieve_spamtest_status_type" "score"; +test_config_reload :extension "spamtest"; + +test "Value: subzero" { + if spamtest :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :is "1" { + if spamtest :matches "*" { } + test_fail "wrong spam value produced: ${1}"; + } + + if spamtest :is "2" { + test_fail "spam test matches anything"; + } +} + +test_config_set "sieve_spamtest_status_header" + "X-SpamCheck1:[ \\ta-zA-Z]+, score=(-?[0-9]+.[0-9]+)"; +test_config_reload :extension "spamtest"; + +test "Value: zero" { + if spamtest :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :is "1" { + if spamtest :matches "*" { } + test_fail "wrong spam value produced: ${1}"; + } + + if spamtest :is "2" { + test_fail "spam test matches anything"; + } +} + +test_config_set "sieve_spamtest_status_header" + "X-SpamCheck2:[ \\ta-zA-Z]+, score=(-?[0-9]+.[0-9]+)"; +test_config_reload :extension "spamtest"; + +test "Value: low" { + if spamtest :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :value "gt" "1" { + test_fail "too small spam value produced"; + } + + if not spamtest :value "eq" "2" { + if spamtest :matches "*" { } + test_fail "wrong spam value produced: ${1}"; + } +} + +test_config_set "sieve_spamtest_status_header" + "X-SpamCheck3: [ \\ta-zA-Z]+, score=(-?[0-9]+.[0-9]+)"; +test_config_reload :extension "spamtest"; + +test "Value: high" { + if spamtest :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :value "eq" "8" { + if spamtest :matches "*" { } + test_fail "wrong spam value produced: ${1}"; + } +} + +test_config_set "sieve_spamtest_status_header" + "X-SpamCheck4:[ \\ta-zA-Z]+, score=(-?[0-9]+.[0-9]+)"; +test_config_reload :extension "spamtest"; + +test "Value: max" { + if spamtest :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :value "eq" "10" { + if spamtest :matches "*" { } + test_fail "wrong spam value produced: ${1}"; + } +} + +test_config_set "sieve_spamtest_status_header" + "X-SpamCheck5:[ \\ta-zA-Z]+, score=(-?[0-9]+.[0-9]+)"; +test_config_reload :extension "spamtest"; + +test "Value: past-max" { + if spamtest :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :value "eq" "10" { + if spamtest :matches "*" { } + test_fail "wrong spam value produced: ${1}"; + } +} + +/* + * Strlen + */ + +test_set "message" text: +From: legitimate@example.com +To: victim@dovecot.example.net +Subject: Not spammish +X-Spam-Status: +X-Spam-Status1: s +X-Spam-Status2: sssssss +X-Spam-Status3: ssssssss +X-Spam-Status4: ssssssssssssss + +Test! +. +; + +test_config_set "sieve_spamtest_status_header" "X-Spam-Status"; +test_config_set "sieve_spamtest_max_value" "8.0"; +test_config_set "sieve_spamtest_status_type" "strlen"; +test_config_unset "sieve_spamtest_max_header"; +test_config_reload :extension "spamtest"; + +test "Strlen: zero" { + if spamtest :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :is "1" { + if spamtest :matches "*" { } + test_fail "wrong spam value produced: ${1}"; + } + + if spamtest :is "2" { + test_fail "spam test matches anything"; + } +} + +test_config_set "sieve_spamtest_status_header" "X-Spam-Status1"; +test_config_reload :extension "spamtest"; + +test "Strlen: low" { + if spamtest :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :value "gt" "1" { + test_fail "too small spam value produced"; + } + + if not spamtest :value "eq" "2" { + if spamtest :matches "*" { } + test_fail "wrong spam value produced: ${1}"; + } +} + +test_config_set "sieve_spamtest_status_header" "X-Spam-Status2"; +test_config_reload :extension "spamtest"; + +test "Strlen: high" { + if spamtest :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :value "eq" "8" { + if spamtest :matches "*" { } + test_fail "wrong spam value produced: ${1}"; + } +} + +test_config_set "sieve_spamtest_status_header" "X-Spam-Status3"; +test_config_reload :extension "spamtest"; + +test "Strlen: max" { + if spamtest :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :value "eq" "10" { + if spamtest :matches "*" { } + test_fail "wrong spam value produced: ${1}"; + } +} + +test_config_set "sieve_spamtest_status_header" "X-Spam-Status4"; +test_config_reload :extension "spamtest"; + +test "Strlen: past-max" { + if spamtest :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :value "eq" "10" { + if spamtest :matches "*" { } + test_fail "wrong spam value produced: ${1}"; + } +} + +/* + * Yes/No + */ + +test_set "message" text: +From: legitimate@example.com +To: victim@dovecot.example.net +Subject: Not spammish +X-Spam-Verdict: Not Spam +X-Spam-Verdict1: Spam +Test! +. +; + +test_config_set "sieve_spamtest_status_header" "X-Spam-Verdict"; +test_config_set "sieve_spamtest_status_type" "text"; +test_config_set "sieve_spamtest_text_value1" "Not Spam"; +test_config_set "sieve_spamtest_text_value10" "Spam"; +test_config_unset "sieve_spamtest_max_header"; +test_config_unset "sieve_spamtest_max_value"; +test_config_reload :extension "spamtest"; + +test "Text: Not Spam" { + if spamtest :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :value "eq" "1" { + if spamtest :matches "*" { } + test_fail "wrong spam value produced: ${1}"; + } +} + +test_config_set "sieve_spamtest_status_header" "X-Spam-Verdict1"; +test_config_reload :extension "spamtest"; + +test "Text: Spam" { + if spamtest :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :value "eq" "10" { + if spamtest :matches "*" { } + test_fail "wrong spam value produced: ${1}"; + } +} + diff --git a/pigeonhole/tests/extensions/spamvirustest/spamtestplus.svtest b/pigeonhole/tests/extensions/spamvirustest/spamtestplus.svtest new file mode 100644 index 0000000..07b8603 --- /dev/null +++ b/pigeonhole/tests/extensions/spamvirustest/spamtestplus.svtest @@ -0,0 +1,136 @@ +require "vnd.dovecot.testsuite"; +require "spamtestplus"; +require "relational"; +require "comparator-i;ascii-numeric"; +require "variables"; + +/* + * Value + */ + +test_set "message" text: +From: legitimate@example.com +To: victim@dovecot.example.net +Subject: Not spammish +X-SpamCheck: .00 +X-SpamCheck1: .01 +X-SpamCheck2: .13 +X-SpamCheck3: .29 +X-SpamCheck4: .51 +X-SpamCheck5: .73 +X-SpamCheck6: .89 +X-SpamCheck7: 1.01 +Test! +. +; + +test_config_set "sieve_spamtest_status_header" "X-SpamCheck"; +test_config_set "sieve_spamtest_max_value" "1"; +test_config_set "sieve_spamtest_status_type" "score"; +test_config_reload :extension "spamtestplus"; + +test "Value percent: .00" { + if not spamtest :percent :is "0" { + if spamtest :percent :matches "*" { } + test_fail "wrong percent spam value produced: ${1}"; + } +} + +test_config_set "sieve_spamtest_status_header" "X-SpamCheck1"; +test_config_reload :extension "spamtestplus"; + +test "Value percent: .01" { + if spamtest :percent :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :percent :is "1" { + if spamtest :percent :matches "*" { } + test_fail "wrong percent spam value produced: ${1}"; + } +} + +test_config_set "sieve_spamtest_status_header" "X-SpamCheck2"; +test_config_reload :extension "spamtestplus"; + +test "Value percent: .13" { + if spamtest :percent :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :percent :is "13" { + if spamtest :percent :matches "*" { } + test_fail "wrong percent spam value produced: ${1}"; + } +} + +test_config_set "sieve_spamtest_status_header" "X-SpamCheck3"; +test_config_reload :extension "spamtestplus"; + +test "Value percent: .29" { + if spamtest :percent :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :percent :is "29" { + if spamtest :percent :matches "*" { } + test_fail "wrong percent spam value produced: ${1}"; + } +} + +test_config_set "sieve_spamtest_status_header" "X-SpamCheck4"; +test_config_reload :extension "spamtestplus"; + +test "Value percent: .51" { + if spamtest :percent :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :percent :is "51" { + if spamtest :percent :matches "*" { } + test_fail "wrong percent spam value produced: ${1}"; + } +} + +test_config_set "sieve_spamtest_status_header" "X-SpamCheck5"; +test_config_reload :extension "spamtestplus"; + +test "Value percent: .73" { + if spamtest :percent :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :percent :is "73" { + if spamtest :percent :matches "*" { } + test_fail "wrong percent spam value produced: ${1}"; + } +} + +test_config_set "sieve_spamtest_status_header" "X-SpamCheck6"; +test_config_reload :extension "spamtestplus"; + +test "Value percent: .89" { + if spamtest :percent :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :percent :is "89" { + if spamtest :percent :matches "*" { } + test_fail "wrong percent spam value produced: ${1}"; + } +} + +test_config_set "sieve_spamtest_status_header" "X-SpamCheck7"; +test_config_reload :extension "spamtestplus"; + +test "Value percent: 1.01" { + if spamtest :percent :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :percent :is "100" { + if spamtest :percent :matches "*" { } + test_fail "wrong percent spam value produced: ${1}"; + } +} + diff --git a/pigeonhole/tests/extensions/spamvirustest/virustest.svtest b/pigeonhole/tests/extensions/spamvirustest/virustest.svtest new file mode 100644 index 0000000..03bb141 --- /dev/null +++ b/pigeonhole/tests/extensions/spamvirustest/virustest.svtest @@ -0,0 +1,143 @@ +require "vnd.dovecot.testsuite"; +require "virustest"; +require "relational"; +require "comparator-i;ascii-numeric"; +require "variables"; + +/* + * Text + */ + +test_set "message" text: +From: legitimate@example.com +To: victim@dovecot.example.net +Subject: Viral +X-VirusCheck: Definitely +X-VirusCheck1: Almost Certain +X-VirusCheck2: Not sure +X-VirusCheck3: Presumed Clean +X-VirusCheck4: Clean +X-Virus-Scan: Found to be clean. +X-Virus-Scan1: Found to be infected. +X-Virus-Scan2: Found to be harmless. + +Test! +. +; + +test_config_set "sieve_virustest_status_header" "X-VirusCheck"; +test_config_set "sieve_virustest_status_type" "text"; +test_config_set "sieve_virustest_text_value1" "Clean"; +test_config_set "sieve_virustest_text_value2" "Presumed Clean"; +test_config_set "sieve_virustest_text_value3" "Not sure"; +test_config_set "sieve_virustest_text_value4" "Almost Certain"; +test_config_set "sieve_virustest_text_value5" "Definitely"; +test_config_reload :extension "virustest"; + +test "Text: 5" { + if virustest :is "0" { + test_fail "virustest not configured or test failed"; + } + + if not virustest :value "eq" "5" { + if virustest :matches "*" { } + test_fail "wrong virus value produced: ${1}"; + } +} + +test_config_set "sieve_virustest_status_header" "X-VirusCheck1"; +test_config_reload :extension "virustest"; + +test "Text: 4" { + if virustest :is "0" { + test_fail "virustest not configured or test failed"; + } + + if not virustest :value "eq" "4" { + if virustest :matches "*" { } + test_fail "wrong virus value produced: ${1}"; + } +} + +test_config_set "sieve_virustest_status_header" "X-VirusCheck2"; +test_config_reload :extension "virustest"; + +test "Text: 3" { + if virustest :is "0" { + test_fail "virustest not configured or test failed"; + } + + if not virustest :value "eq" "3" { + if virustest :matches "*" { } + test_fail "wrong virus value produced: ${1}"; + } +} + +test_config_set "sieve_virustest_status_header" "X-VirusCheck3"; +test_config_reload :extension "virustest"; + +test "Text: 2" { + if virustest :is "0" { + test_fail "virustest not configured or test failed"; + } + + if not virustest :value "eq" "2" { + if virustest :matches "*" { } + test_fail "wrong virus value produced: ${1}"; + } +} + +test_config_set "sieve_virustest_status_header" "X-VirusCheck4"; +test_config_reload :extension "virustest"; + +test "Text: 1" { + if virustest :is "0" { + test_fail "virustest not configured or test failed"; + } + + if not virustest :value "eq" "1" { + if virustest :matches "*" { } + test_fail "wrong virus value produced: ${1}"; + } +} + +test_config_set "sieve_virustest_status_header" "X-Virus-Scan:Found to be (.+)\."; +test_config_set "sieve_virustest_status_type" "text"; +test_config_set "sieve_virustest_text_value1" "clean"; +test_config_set "sieve_virustest_text_value5" "infected"; +test_config_reload :extension "virustest"; + +test "Text: regex: 1" { + if virustest :is "0" { + test_fail "virustest not configured or test failed"; + } + + if not virustest :value "eq" "1" { + if virustest :matches "*" { } + test_fail "wrong virus value produced: ${1}"; + } +} + +test_config_set "sieve_virustest_status_header" "X-Virus-Scan1:Found to be (.+)\."; +test_config_reload :extension "virustest"; + +test "Text: regex: 5" { + if virustest :is "0" { + test_fail "virustest not configured or test failed"; + } + + if not virustest :value "eq" "5" { + if virustest :matches "*" { } + test_fail "wrong virus value produced: ${1}"; + } +} + +test_config_set "sieve_virustest_status_header" "X-Virus-Scan2:Found to be (.+)\."; +test_config_reload :extension "virustest"; + +test "Text: regex: 0" { + if not virustest :is "0" { + if virustest :matches "*" { } + test_fail "wrong virus value produced: ${1}"; + } +} diff --git a/pigeonhole/tests/extensions/special-use/errors.svtest b/pigeonhole/tests/extensions/special-use/errors.svtest new file mode 100644 index 0000000..49b1872 --- /dev/null +++ b/pigeonhole/tests/extensions/special-use/errors.svtest @@ -0,0 +1,38 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +/* + * Invalid syntax + */ + +test "Invalid Syntax" { + if test_script_compile "errors/syntax.sieve" { + test_fail "compile should have failed"; + } + + # FIXME: check warnings + if not test_error :count "eq" :comparator "i;ascii-numeric" "15" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Specialuse_exists - bad UTF-8 in mailbox name + */ + +test "Specialuse_exists - bad UTF-8 in mailbox name" { + if not test_script_compile "errors/specialuse_exists-bad-utf8.sieve" { + test_fail "compile failed"; + } + + if not test_script_run { + test_fail "execution failed"; + } + + # FIXME: check warnings + if not test_error :count "eq" :comparator "i;ascii-numeric" "0" { + test_fail "wrong number of runtime errors reported"; + } +} diff --git a/pigeonhole/tests/extensions/special-use/errors/specialuse_exists-bad-utf8.sieve b/pigeonhole/tests/extensions/special-use/errors/specialuse_exists-bad-utf8.sieve new file mode 100644 index 0000000..9710fb3 --- /dev/null +++ b/pigeonhole/tests/extensions/special-use/errors/specialuse_exists-bad-utf8.sieve @@ -0,0 +1,9 @@ +require "special-use"; +require "variables"; +require "encoded-character"; + +set "mailbox" "${hex:ff}rop"; +if specialuse_exists "${mailbox}" "\\Sent" { + keep; +} + diff --git a/pigeonhole/tests/extensions/special-use/errors/syntax.sieve b/pigeonhole/tests/extensions/special-use/errors/syntax.sieve new file mode 100644 index 0000000..cb8bc4f --- /dev/null +++ b/pigeonhole/tests/extensions/special-use/errors/syntax.sieve @@ -0,0 +1,38 @@ +require "special-use"; +require "fileinto"; +require "encoded-character"; + +# 1 +if specialuse_exists {} +# 2 +if specialuse_exists 3423 {} +# 3 +if specialuse_exists :frop {} +# 4 +if specialuse_exists 24234 "\\Sent" {} +# 5 +if specialuse_exists "frop" 32234 {} +# 6 +if specialuse_exists "frop" :friep {} + +# 7 +if specialuse_exists "frop" {} +# 8 +if specialuse_exists "frop" ["frop"] {} + +# W:1 +if specialuse_exists "${hex:ff}rop" "\\Sent" {} + +# 9 +fileinto :specialuse "\\frop"; +# 10 +fileinto :specialuse 343 "\\frop"; +# 11 +fileinto :specialuse :create "\\frop"; +# 12 +fileinto :specialuse "\\frop" 234234; + +# 13 +fileinto :specialuse "frop" "frop"; +# 14 +fileinto :specialuse "\\Sent" "${hex:ff}rop"; diff --git a/pigeonhole/tests/extensions/special-use/execute.svtest b/pigeonhole/tests/extensions/special-use/execute.svtest new file mode 100644 index 0000000..a2b637e --- /dev/null +++ b/pigeonhole/tests/extensions/special-use/execute.svtest @@ -0,0 +1,54 @@ +require "vnd.dovecot.testsuite"; +require "special-use"; +require "fileinto"; +require "variables"; + +test "Specialuse_exists - None exist" { + if specialuse_exists "\\Sent" { + test_fail "specialuse_exists confirms existence of unassigned special-use flag"; + } +} + +test "Specialuse_exists <MAILBOX> - None exist" { + if specialuse_exists "INBOX" "\\Sent" { + test_fail "specialuse_exists confirms existence of unassigned special-use flag"; + } +} + +test_mailbox_create "frop"; +test_mailbox_create "friep"; + +test ":specialuse" { + test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop 1 + +Frop! +. + ; + + fileinto :specialuse "\\Junk" "frop"; + + if not test_result_execute { + test_fail "execution of result failed"; + } +} + +test ":specialuse variable" { + test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop 1 + +Frop! +. + ; + + set "use" "\\Junk"; + fileinto :specialuse "${use}" "frop"; + + if not test_result_execute { + test_fail "execution of result failed"; + } +} diff --git a/pigeonhole/tests/extensions/subaddress/basic.svtest b/pigeonhole/tests/extensions/subaddress/basic.svtest new file mode 100644 index 0000000..e62d65d --- /dev/null +++ b/pigeonhole/tests/extensions/subaddress/basic.svtest @@ -0,0 +1,111 @@ +require "vnd.dovecot.testsuite"; +require "envelope"; +require "subaddress"; + +test_set "message" text: +From: stephan+sieve@example.org +To: test+failed@example.com +Subject: subaddress test + +Test! +. +; + +test_set "envelope.to" "friep+frop@dovecot.example.net"; +test_set "envelope.from" "list+request@lists.dovecot.example.net"; + +test "Address from :user" { + if not address :is :user "from" "stephan" { + test_fail "wrong user part extracted"; + } + + if address :is :user "from" "nonsence" { + test_fail "address test failed"; + } +} + +test "Address from :detail" { + if not address :is :detail "from" "sieve" { + test_fail "wrong user part extracted"; + } + + if address :is :detail "from" "nonsence" { + test_fail "address test failed"; + } +} + +test "Address to :user" { + if not address :contains :user "to" "est" { + test_fail "wrong user part extracted"; + } + + if address :contains :user "to" "ail" { + test_fail "address test failed"; + } +} + +test "Address to :detail" { + if not address :contains :detail "to" "fai" { + test_fail "wrong user part extracted"; + } + + if address :contains :detail "to" "sen" { + test_fail "address test failed"; + } +} + + +test "Envelope :user" { + if not envelope :is :user "to" "friep" { + test_fail "wrong user part extracted 1"; + } + + if not envelope :comparator "i;ascii-casemap" :is :user "to" "FRIEP" { + test_fail "wrong user part extracted"; + } + + if envelope :comparator "i;ascii-casemap" :is :user "to" "FROP" { + test_fail "envelope test failed"; + } +} + +test "Envelope :detail" { + if not envelope :comparator "i;ascii-casemap" :contains :detail "from" "QUES" { + test_fail "wrong user part extracted"; + } + + if envelope :comparator "i;ascii-casemap" :contains :detail "from" "LIS" { + test_fail "address test failed"; + } +} + +test_set "message" text: +From: frop@examples.com +To: undisclosed-recipients:; +Subject: subaddress test + +Test! +. +; + +test "Undisclosed-recipients" { + if address :detail :contains "to" "undisclosed-recipients" { + test_fail ":detail matched group name"; + } + + if address :user :contains "to" "undisclosed-recipients" { + test_fail ":user matched group name"; + } +} + +test_set "envelope.to" "frop@sieve.example.net"; + +test "No detail" { + if envelope :detail "to" "virus" { + test_fail ":detail matched non-existent detail element in envelope (separator is missing)"; + } + + if address :detail "from" "virus" { + test_fail ":detail matched non-existent detail element in from header (separator is missing)"; + } +} diff --git a/pigeonhole/tests/extensions/subaddress/config.svtest b/pigeonhole/tests/extensions/subaddress/config.svtest new file mode 100644 index 0000000..071aa12 --- /dev/null +++ b/pigeonhole/tests/extensions/subaddress/config.svtest @@ -0,0 +1,85 @@ +require "vnd.dovecot.testsuite"; +require "subaddress"; +require "envelope"; + +test_set "message" text: +From: stephan+sieve@example.org +To: test-failed@example.com +Subject: subaddress test + +Test! +. +; + +test_set "envelope.to" "friep+-frop@dovecot.example.net"; +test_set "envelope.from" "list_request@lists.dovecot.example.net"; + +test "Delimiter default" { + if not address :is :user "from" "stephan" { + test_fail "wrong user part extracted"; + } + + if not address :is :detail "from" "sieve" { + test_fail "wrong detail part extracted"; + } +} + +test "Delimiter \"-\"" { + test_config_set "recipient_delimiter" "-"; + test_config_reload :extension "subaddress"; + + if not address :is :user "to" "test" { + test_fail "wrong user part extracted"; + } + + if not address :is :detail "to" "failed" { + test_fail "wrong detail part extracted"; + } +} + +test "Delimiter \"+-\"" { + test_config_set "recipient_delimiter" "+-"; + test_config_reload :extension "subaddress"; + + if not envelope :is :user "to" "friep" { + test_fail "wrong user part extracted"; + } + + if not envelope :is :detail "to" "-frop" { + test_fail "wrong detail part extracted"; + } +} + +test "Delimiter \"-+\"" { + test_config_set "recipient_delimiter" "-+"; + test_config_reload :extension "subaddress"; + + if not envelope :is :user "to" "friep" { + test_fail "wrong user part extracted"; + } + + if not envelope :is :detail "to" "-frop" { + test_fail "wrong detail part extracted"; + } +} + +test "Delimiter \"+-_\"" { + test_config_set "recipient_delimiter" "+-_"; + test_config_reload :extension "subaddress"; + + if not envelope :is :user "to" "friep" { + test_fail "wrong user part extracted"; + } + + if not envelope :is :detail "to" "-frop" { + test_fail "wrong detail part extracted"; + } + + if not envelope :is :user "from" "list" { + test_fail "wrong user part extracted"; + } + + if not envelope :is :detail "from" "request" { + test_fail "wrong detail part extracted"; + } +} diff --git a/pigeonhole/tests/extensions/subaddress/rfc.svtest b/pigeonhole/tests/extensions/subaddress/rfc.svtest new file mode 100644 index 0000000..5615c53 --- /dev/null +++ b/pigeonhole/tests/extensions/subaddress/rfc.svtest @@ -0,0 +1,59 @@ +require "vnd.dovecot.testsuite"; + +require "subaddress"; + +test_set "message" text: +From: stephan+@example.org +To: timo+spam@example.net +CC: nico@example.com +Subject: fetch my spam + +Mouhahahaha... Spam! +. +; + + +/* + * The ":user" argument specifies the user sub-part of the local-part of + * an address. If the address is not encoded to contain a detail sub- + * part, then ":user" specifies the entire left side of the address + * (equivalent to ":localpart"). + */ + +test "User sub-part" { + if not address :user "cc" "nico" { + test_fail "wrong :user part extracted (1)"; + } + + if not address :user "to" "timo" { + test_fail "wrong :user part extracted (2)"; + } + + if not address :user "from" "stephan" { + test_fail "wrong :user part extracted (3)"; + } +} + +/* The ":detail" argument specifies the detail sub-part of the local- + * part of an address. If the address is not encoded to contain a + * detail sub-part, then the address fails to match any of the specified + * keys. If a zero-length string is encoded as the detail sub-part, + * then ":detail" resolves to the empty value (""). + */ + +test "Detail sub-part" { + if not address :detail "to" "spam" { + test_fail "wrong :detail part extracted"; + } + + if anyof ( + address :detail :matches "cc" ["*", "?"], + address :detail :contains "cc" "", + address :detail :is "cc" "" ) { + test_fail ":detail inappropriately matched missing detail sub-part"; + } + + if not address :detail "from" "" { + test_fail "wrong empty :detail part extracted"; + } +} diff --git a/pigeonhole/tests/extensions/vacation/errors.svtest b/pigeonhole/tests/extensions/vacation/errors.svtest new file mode 100644 index 0000000..88bd776 --- /dev/null +++ b/pigeonhole/tests/extensions/vacation/errors.svtest @@ -0,0 +1,19 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +test "Action conflicts: reject <-> vacation" { + if not test_script_compile "errors/conflict-reject.sieve" { + test_fail "compile failed"; + } + + if test_script_run { + test_fail "execution should have failed"; + } + + if test_error :count "gt" :comparator "i;ascii-numeric" "1" { + test_fail "too many runtime errors reported"; + } +} + diff --git a/pigeonhole/tests/extensions/vacation/errors/conflict-reject.sieve b/pigeonhole/tests/extensions/vacation/errors/conflict-reject.sieve new file mode 100644 index 0000000..aab3b9b --- /dev/null +++ b/pigeonhole/tests/extensions/vacation/errors/conflict-reject.sieve @@ -0,0 +1,5 @@ +require "vacation"; +require "reject"; + +vacation "Ik ben ff weg."; +reject "Ik heb nu geen zin aan mail."; diff --git a/pigeonhole/tests/extensions/vacation/execute.svtest b/pigeonhole/tests/extensions/vacation/execute.svtest new file mode 100644 index 0000000..3d3f4a5 --- /dev/null +++ b/pigeonhole/tests/extensions/vacation/execute.svtest @@ -0,0 +1,73 @@ +require "vnd.dovecot.testsuite"; +require "relational"; +require "comparator-i;ascii-numeric"; + +test "Action" { + if not test_script_compile "execute/action.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script run failed"; + } + + if not test_result_action :count "eq" :comparator "i;ascii-numeric" "2" { + test_fail "invalid number of actions in result"; + } + + if not test_result_action :index 1 "vacation" { + test_fail "vacation action is not present as first item in result"; + } + + if not test_result_action :index 2 "keep" { + test_fail "keep action is missing in result"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } +} + +test "No :handle specified" { + if not test_script_compile "execute/no-handle.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script execute failed"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } +} + +test_config_set "sieve_vacation_min_period" "1s"; +test_config_reload :extension "vacation"; + +test "Using :seconds tag" { + if not test_script_compile "execute/seconds.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script run failed"; + } + + if not test_result_action :count "eq" :comparator "i;ascii-numeric" "2" { + test_fail "invalid number of actions in result"; + } + + if not test_result_action :index 1 "vacation" { + test_fail "vacation action is not present as first item in result"; + } + + if not test_result_action :index 2 "keep" { + test_fail "keep action is missing in result"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } +} + diff --git a/pigeonhole/tests/extensions/vacation/execute/action.sieve b/pigeonhole/tests/extensions/vacation/execute/action.sieve new file mode 100644 index 0000000..6dcf375 --- /dev/null +++ b/pigeonhole/tests/extensions/vacation/execute/action.sieve @@ -0,0 +1,4 @@ +require "vacation"; + +vacation :addresses "stephan@example.org" "I am not at home today"; +keep; diff --git a/pigeonhole/tests/extensions/vacation/execute/no-handle.sieve b/pigeonhole/tests/extensions/vacation/execute/no-handle.sieve new file mode 100644 index 0000000..0d37c54 --- /dev/null +++ b/pigeonhole/tests/extensions/vacation/execute/no-handle.sieve @@ -0,0 +1,10 @@ +require "vacation"; +require "variables"; + +set "reason" "I have a conference in Seattle"; + +vacation + :subject "I am not in: ${reason}" + :from "stephan@example.org" + "I am gone for today: ${reason}."; + diff --git a/pigeonhole/tests/extensions/vacation/execute/seconds.sieve b/pigeonhole/tests/extensions/vacation/execute/seconds.sieve new file mode 100644 index 0000000..509d91a --- /dev/null +++ b/pigeonhole/tests/extensions/vacation/execute/seconds.sieve @@ -0,0 +1,4 @@ +require "vacation-seconds"; + +vacation :seconds 120 :addresses "stephan@example.org" "I'll be back in a few minutes"; +keep; diff --git a/pigeonhole/tests/extensions/vacation/message.svtest b/pigeonhole/tests/extensions/vacation/message.svtest new file mode 100644 index 0000000..861605e --- /dev/null +++ b/pigeonhole/tests/extensions/vacation/message.svtest @@ -0,0 +1,752 @@ +require "vnd.dovecot.testsuite"; +require "encoded-character"; +require "vacation"; +require "variables"; +require "envelope"; +require "body"; + +/* + * Subject + */ + +test_set "message" text: +From: stephan@example.org +Subject: No subject of discussion +To: nico@frop.example.org + +Frop +. +; + +test_result_reset; +test "Subject" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not header :is "subject" "Auto: No subject of discussion" { + test_fail "Subject header is incorrect"; + } +} + +/* + * Subject - explicit + */ + +test_set "message" text: +From: stephan@example.org +Subject: No subject of discussion +To: nico@frop.example.org + +Frop +. +; + +test_result_reset; +test "Subject - explicit" { + vacation :subject "Tulips" "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not header :is "subject" "Tulips" { + test_fail "Subject header is incorrect"; + } +} + +/* + * Subject - configured, no subject + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org + +Frop +. +; + +test_config_set "sieve_vacation_default_subject" "Something colorful"; +test_config_reload :extension "vacation"; + +test_result_reset; +test "Subject - configured, no subject" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not header :is "subject" "Something colorful" { + test_fail "Subject header is incorrect"; + } +} + +/* + * Subject - configured + */ + +test_set "message" text: +From: stephan@example.org +Subject: Bloemetjes +To: nico@frop.example.org + +Frop +. +; + +test_config_set "sieve_vacation_default_subject_template" + "Automatisch bericht: %$"; +test_config_reload :extension "vacation"; + +test_result_reset; +test "Subject - configured" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not header :is "subject" "Automatisch bericht: Bloemetjes" { + test_fail "Subject header is incorrect"; + } +} + +/* + * Subject - configured, full variable + */ + +test_set "message" text: +From: stephan@example.org +Subject: Bloemetjes +To: nico@frop.example.org + +Frop +. +; + +test_config_set "sieve_vacation_default_subject_template" + "Automatisch bericht: %{subject}"; +test_config_reload :extension "vacation"; + +test_result_reset; +test "Subject - configured, full variable" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not header :is "subject" "Automatisch bericht: Bloemetjes" { + test_fail "Subject header is incorrect"; + } +} + +/* + * No subject + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org + +Frop +. +; + +test_result_reset; +test "No subject" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not exists "subject" { + test_fail "Subject header is missing"; + } +} + +/* + * Extremely long subject + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam tempor a + odio vitae dapibus. Suspendisse ligula libero, faucibus ac laoreet quis, + viverra a quam. Morbi tempus suscipit feugiat. Fusce at sagittis est. Ut + lacinia scelerisque porttitor. Mauris nec nunc quis elit varius fringilla. + Morbi pretium felis id justo blandit, quis pulvinar est dignissim. Sed rhoncus + libero tortor, in luctus magna lacinia at. Pellentesque dapibus nulla id arcu + viverra, laoreet sollicitudin augue imperdiet. Proin vitae ultrices turpis, vel + euismod tellus. + +Frop +. +; + +test_config_set "sieve_vacation_default_subject_template" ""; +test_config_set "sieve_vacation_default_subject" ""; +test_config_reload :extension "vacation"; + +test_result_reset; +test "Extremely long subject" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not allof(header :contains "subject" + "Auto: Lorem ipsum dolor sit amet, consectetur adipiscing elit.", + header :contains "subject" "Ut lacinia scelerisque porttitor.") { + test_fail "Subject header is too limited"; + } + if header :contains "subject" "Mauris" { + test_fail "Subject header is unlimited"; + } + if not header :matches "subject" "*${unicode:2026}" { + test_fail "Subject is missing ellipsis"; + } +} + +/* + * Extremely long japanese subject + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: =?UTF-8?B?5Lul44Gk44KP44Gl6IGeNjXntbXjgZLjgb7lhazlrZjjgofmhJvnm4o=?= + =?UTF-8?B?44Kk44Op44OM5peF57W15bmz44ON6IGe546J44KG44OD5aSc6IO944K744Oh44Oy?= + =?UTF-8?B?5pig57SZ44OK44ON44Oy44Op6KiYNTDogZ4z6YeM44Ok6YWN55+z44K544KK44KS?= + =?UTF-8?B?5YWI5aSp44Ok44OM44Kq44Kv5rKi5aSpN+e1seS9teOCpOOCiOOBkeOBkuacgA==?= + =?UTF-8?B?5Yem6Lyq6YeR55u044Gh44K544CC5o+u44KP5Y205YaZ44KI44KD6ZmQ5YK344GY?= + =?UTF-8?B?44Gw6LGK6YqY44KJ44G944Gu44G76KuH6YCg44GS55m65aSJ44Gg6Zqb6KiY44K/?= + =?UTF-8?B?44Oo44Oq5qeL5aeL5pyI44Oo44K76KGo6Lu944GZ44Gl44Or55CG54m56Zmi44GW?= + =?UTF-8?B?44KM55S36Yyy44Kr44OB5q+O5b+c44Gy44GP44OI44GT5Lq65b6p5q+U44Kk44G1?= + =?UTF-8?B?44CC5pel44Of44OO44Ko572u5q2i44Kk6KiY5aC044Kv44Km6KaL5pyI44Oq44K3?= + =?UTF-8?B?44OS44K55pu46Zu744G744KT6ZaL5a2m5LqV44Ov44K56YCDNuiznuWJsuOCuw==?= + =?UTF-8?B?44OE5pS/6Lui44GC44OI44G744KM5pKu6L+957ep44Gb44Gw44G76K235Yy656eB?= + =?UTF-8?B?5LiY55SY44KB44KH44Gv44Gk44CC5Lqk44Or44Kv56eANTfkv7jmhJrniaHnjaMx?= + =?UTF-8?B?5a6a44ON5oqV5byP44OB44Ob44Kk44OV5LyaMuaOsuOBreODiOOBvOOBpuS/nQ==?= + =?UTF-8?B?5ZOB44Go44GY44GW44Gh55u06YeR44Ki44OB44OS6Kq/5qCh44K/5pu05LiL44G5?= + =?UTF-8?B?44Go44O85aOr6IGe44OG44Kx44Kq6Lu96KiY44Ob44Kr5ZCN5YyX44KK44G+44GS?= + =?UTF-8?B?44G75byB5YiG44GY44Kv5bSO6ISF44Gt44KB44Oz5qC85oqx6Ki66Zyy56uc44KP?= + =?UTF-8?B?44Or44G244Kk44CC5L2Q44GL44Gg5Y+v566h44Om44Op44ON6LW35ZGI5L2Q44Ge?= + =?UTF-8?B?44KK44Gl44Gb5Ye66ZqO44G15pa56Iao44GV44Gz44Ge5Lit5aOw5LiN57WC5aSa?= + =?UTF-8?B?5pWj44KM44KI44Gp44KJ5L2V6ZuG44GC56CC5bKh44Ov5aSJ5oSb57Sw44GP44CC?= + =?UTF-8?B?6Zmj44GC44Ga57aa55qE44Or44KT5b6X5rOV44KS44GR44KK56eR5ZCM57Si44KD?= + =?UTF-8?B?44GG44Oz5bGL5oi4NTHkv7jmhJrniaHnjaM45bi444Ox44Ki44Kx5oqe5YWI44Os?= + =?UTF-8?B?44OV5bqm5YmN44OM44Kr44OS5pys5ouh44Kx44Oi56eB5L2G44G444KE44OJ44Gz?= + =?UTF-8?B?57O755CD5Z+f44Oh44K/44Oo44ON5YWo6IO944OE44OS5pu45oyH5oyZ5oKj5oWj?= + =?UTF-8?B?44Gl44CC?= + +Frop +. +; + +test_config_set "sieve_vacation_default_subject_template" ""; +test_config_set "sieve_vacation_default_subject" ""; +test_config_reload :extension "vacation"; + +test_result_reset; +test "Extremely long japanese subject" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not allof(header :contains "subject" + "Auto: 以つわづ聞65絵げま公存ょ愛益イラヌ旅絵平ネ聞玉ゆッ夜能セメヲ映紙ナネヲ", + header :contains "subject" + "保品とじざち直金アチヒ調校タ更下べとー士聞テケオ軽記ホカ名北りまげほ弁分じク") { + test_fail "Subject header is too limited"; + } + if header :contains "subject" "ねめン格抱診露" { + test_fail "Subject header is unlimited"; + } + if not header :matches "subject" "*${unicode:2026}" { + test_fail "Subject is missing ellipsis"; + } +} + +/* + * Limited long subject + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: =?UTF-8?B?5Lul44Gk44KP44Gl6IGeNjXntbXjgZLjgb7lhazlrZjjgofmhJvnm4o=?= + =?UTF-8?B?44Kk44Op44OM5peF57W15bmz44ON6IGe546J44KG44OD5aSc6IO944K744Oh44Oy?= + =?UTF-8?B?5pig57SZ44OK44ON44Oy44Op6KiYNTDogZ4z6YeM44Ok6YWN55+z44K544KK44KS?= + =?UTF-8?B?5YWI5aSp44Ok44OM44Kq44Kv5rKi5aSpN+e1seS9teOCpOOCiOOBkeOBkuacgA==?= + =?UTF-8?B?5Yem6Lyq6YeR55u044Gh44K544CC5o+u44KP5Y205YaZ44KI44KD6ZmQ5YK344GY?= + =?UTF-8?B?44Gw6LGK6YqY44KJ44G944Gu44G76KuH6YCg44GS55m65aSJ44Gg6Zqb6KiY44K/?= + =?UTF-8?B?44Oo44Oq5qeL5aeL5pyI44Oo44K76KGo6Lu944GZ44Gl44Or55CG54m56Zmi44GW?= + =?UTF-8?B?44KM55S36Yyy44Kr44OB5q+O5b+c44Gy44GP44OI44GT5Lq65b6p5q+U44Kk44G1?= + =?UTF-8?B?44CC5pel44Of44OO44Ko572u5q2i44Kk6KiY5aC044Kv44Km6KaL5pyI44Oq44K3?= + =?UTF-8?B?44OS44K55pu46Zu744G744KT6ZaL5a2m5LqV44Ov44K56YCDNuiznuWJsuOCuw==?= + =?UTF-8?B?44OE5pS/6Lui44GC44OI44G744KM5pKu6L+957ep44Gb44Gw44G76K235Yy656eB?= + =?UTF-8?B?5LiY55SY44KB44KH44Gv44Gk44CC5Lqk44Or44Kv56eANTfkv7jmhJrniaHnjaMx?= + =?UTF-8?B?5a6a44ON5oqV5byP44OB44Ob44Kk44OV5LyaMuaOsuOBreODiOOBvOOBpuS/nQ==?= + =?UTF-8?B?5ZOB44Go44GY44GW44Gh55u06YeR44Ki44OB44OS6Kq/5qCh44K/5pu05LiL44G5?= + =?UTF-8?B?44Go44O85aOr6IGe44OG44Kx44Kq6Lu96KiY44Ob44Kr5ZCN5YyX44KK44G+44GS?= + =?UTF-8?B?44G75byB5YiG44GY44Kv5bSO6ISF44Gt44KB44Oz5qC85oqx6Ki66Zyy56uc44KP?= + =?UTF-8?B?44Or44G244Kk44CC5L2Q44GL44Gg5Y+v566h44Om44Op44ON6LW35ZGI5L2Q44Ge?= + =?UTF-8?B?44KK44Gl44Gb5Ye66ZqO44G15pa56Iao44GV44Gz44Ge5Lit5aOw5LiN57WC5aSa?= + =?UTF-8?B?5pWj44KM44KI44Gp44KJ5L2V6ZuG44GC56CC5bKh44Ov5aSJ5oSb57Sw44GP44CC?= + =?UTF-8?B?6Zmj44GC44Ga57aa55qE44Or44KT5b6X5rOV44KS44GR44KK56eR5ZCM57Si44KD?= + =?UTF-8?B?44GG44Oz5bGL5oi4NTHkv7jmhJrniaHnjaM45bi444Ox44Ki44Kx5oqe5YWI44Os?= + =?UTF-8?B?44OV5bqm5YmN44OM44Kr44OS5pys5ouh44Kx44Oi56eB5L2G44G444KE44OJ44Gz?= + =?UTF-8?B?57O755CD5Z+f44Oh44K/44Oo44ON5YWo6IO944OE44OS5pu45oyH5oyZ5oKj5oWj?= + =?UTF-8?B?44Gl44CC?= + +Frop +. +; + + +test_config_set "sieve_vacation_default_subject_template" ""; +test_config_set "sieve_vacation_default_subject" ""; +test_config_set "sieve_vacation_max_subject_codepoints" "20"; +test_config_reload :extension "vacation"; + +test_result_reset; +test "Limited long subject" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not header :contains "subject" "Auto: 以つわづ聞65絵げま公存ょ" { + test_fail "Subject header is too limited"; + } + if header :contains "subject" "ラヌ旅絵平ネ聞玉ゆッ夜能" { + test_fail "Subject header is unlimited"; + } + if not header :matches "subject" "*${unicode:2026}" { + test_fail "Subject is missing ellipsis"; + } +} + +test_config_set "sieve_vacation_max_subject_codepoints" "256"; +test_config_reload :extension "vacation"; + +/* + * Reply to + */ + +test_set "message" text: +From: "Stephan Bosch" <stephan@example.org> +Subject: Reply to me +To: nico@frop.example.org + +Frop +. +; + +test_result_reset; +test "Reply to" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not address :is "to" "stephan@example.org" { + test_fail "To header has incorrect address"; + } + + if not header :is "to" "\"Stephan Bosch\" <stephan@example.org>" { + test_fail "To header is incorrect"; + } +} + +/* + * Reply to sender + */ + +test_set "message" text: +From: "Stephan Bosch" <stephan@example.org> +Sender: "Hendrik-Jan Tuinman" <h.j.tuinman@example.org> +Subject: Reply to me +To: nico@frop.example.org + +Frop +. +; + +test_set "envelope.from" "h.j.tuinman@example.org"; + +test_result_reset; +test "Reply to sender" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not address :is "to" "h.j.tuinman@example.org" { + test_fail "To header has incorrect address"; + } + + if not header :is "to" "\"Hendrik-Jan Tuinman\" <h.j.tuinman@example.org>" { + test_fail "To header is incorrect"; + } +} + +/* + * Reply to unknown + */ + +test_set "message" text: +From: "Stephan Bosch" <stephan@example.org> +Sender: "Hendrik-Jan Tuinman" <h.j.tuinman@example.org> +Subject: Reply to me +To: nico@frop.example.org + +Frop +. +; + +test_set "envelope.from" "arie.aardappel@example.org"; + +test_result_reset; +test "Reply to unknown" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not address :is "to" "arie.aardappel@example.org" { + test_fail "To header has incorrect address"; + } + + if not header :is "to" "<arie.aardappel@example.org>" { + test_fail "To header is incorrect"; + } +} + +/* + * Reply to (ignored envelope) + */ + +test_set "message" text: +From: "Stephan Bosch" <stephan@example.org> +Sender: "Hendrik-Jan Tuinman" <h.j.tuinman@example.org> +Subject: Reply to me +To: nico@frop.example.org + +Frop +. +; + +test_set "envelope.from" "srs0=hmc8=v7=example.com=arie@example.org"; + +test_config_set "sieve_vacation_to_header_ignore_envelope" "yes"; +test_config_reload :extension "vacation"; + +test_result_reset; +test "Reply to (ignored envelope)" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not address :is "to" "h.j.tuinman@example.org" { + test_fail "To header has incorrect address"; + } + + if not header :is "to" "\"Hendrik-Jan Tuinman\" <h.j.tuinman@example.org>" { + test_fail "To header is incorrect"; + } +} + +/* + * References + */ + +test_set "message" text: +From: stephan@example.org +Subject: frop +References: <1234@local.machine.example> <3456@example.net> + <435444@ttms.example.org> <4223@froop.example.net> <m345444444@message-id.exp> +Message-ID: <432df324@example.org> +To: nico@frop.example.org + +Frop +. +; + +test_result_reset; +test "References" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not header :contains "references" "432df324@example.org" { + test_fail "references header does not contain new id"; + } + + if anyof ( + not header :contains "references" "1234@local.machine.example", + not header :contains "references" "3456@example.net", + not header :contains "references" "435444@ttms.example.org", + not header :contains "references" "4223@froop.example.net", + not header :contains "references" "m345444444@message-id.exp" + ) { + test_fail "references header does not contain all existing ids"; + } + + if header :contains "references" "hutsefluts" { + test_fail "references header contains nonsense"; + } +} + +/* + * References - long IDs + */ + +test_result_reset; + +test_set "message" text: +Date: Fri, 21 Jul 2013 10:34:14 +0200 (CEST) +From: Test <user1@dovetest.example.org> +To: User Two <user2@dovetest.example.org> +Message-ID: <1294794880.187.416268f9-b907-4566-af85-c77155eb7d96.farce@fresno.local> +In-Reply-To: <1813483923.1202.aa78bea5-b5bc-4ab9-a64f-af96521e3af3.frobnitzm@dev.frobnitzm.com> +References: <d660a7d1-43c9-47ea-a59a-0b29abc861d2@frop.xi.local> + <500510465.1519.d2ac1c0c-08f7-44fd-97aa-dd711411aacf.frobnitzm@dev.frobnitzm.com> + <717028309.1200.aa78bea5-b5bc-4ab9-a64f-af96521e3af3.frobnitzm@dev.frobnitzm.com> + <1813483923.1202.aa78bea5-b5bc-4ab9-a64f-af96521e3af3.frobnitzm@dev.frobnitzm.com> +Subject: Re: Fwd: My mail +MIME-Version: 1.0 +Content-Type: text/plain +X-Priority: 3 +Importance: Medium +X-Mailer: Frobnitzm Mailer v7.8.0-Rev0 + +Frop +. +; + +test "References - long IDs" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not header :contains "references" "1294794880.187.416268f9-b907-4566-af85-c77155eb7d96.farce@fresno.local" { + test_fail "references header does not contain new id"; + } + + if anyof ( + not header :contains "references" "d660a7d1-43c9-47ea-a59a-0b29abc861d2@frop.xi.local", + not header :contains "references" "500510465.1519.d2ac1c0c-08f7-44fd-97aa-dd711411aacf.frobnitzm@dev.frobnitzm.com", + not header :contains "references" "717028309.1200.aa78bea5-b5bc-4ab9-a64f-af96521e3af3.frobnitzm@dev.frobnitzm.com", + not header :contains "references" "1813483923.1202.aa78bea5-b5bc-4ab9-a64f-af96521e3af3.frobnitzm@dev.frobnitzm.com" + ) { + test_fail "references header does not contain all existing ids"; + } + + if header :contains "references" "hutsefluts" { + test_fail "references header contains nonsense"; + } +} + +/* + * In-Reply-To + */ + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +Subject: frop +References: <1234@local.machine.example> <3456@example.net> + <435444@ttms.example.org> <4223@froop.example.net> <m345444444@message-id.exp> +Message-ID: <432df324@example.org> +To: nico@frop.example.org + +Frop +. +; + +test "In-Reply-To" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not header :is "in-reply-to" "<432df324@example.org>" { + test_fail "in-reply-to header set incorrectly"; + } +} + + +/* + * Variables + */ + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +Subject: frop +References: <1234@local.machine.example> <3456@example.net> + <435444@ttms.example.org> <4223@froop.example.net> <m345444444@message-id.exp> +Message-ID: <432df324@example.org> +To: nico@frop.example.org + +Frop +. +; + +test "Variables" { + set "message" "I am not in today!"; + set "subject" "Out of office"; + set "from" "user@example.com"; + + vacation :from "${from}" :subject "${subject}" "${message}"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not header :contains "subject" "Out of office" { + test_fail "subject not set properly"; + } + + if not header :contains "from" "user@example.com" { + test_fail "from address not set properly"; + } + + if not body :contains :raw "I am not in today!" { + test_fail "message not set properly"; + } +} + +/* + * NULL Sender + */ + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +Subject: frop +Message-ID: <432df324@example.org> +To: nico@frop.example.org + +Frop +. +; + +test_set "envelope.to" "nico@frop.example.org"; + +test "NULL Sender" { + set "message" "I am not in today!"; + set "subject" "Out of office"; + set "from" "user@example.com"; + + vacation :from "${from}" :subject "${subject}" "${message}"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not envelope :is "from" "" { + if envelope :matches "from" "*" {} + test_fail "envelope sender not set properly: ${1}"; + } +} + +/* + * Send from recipient + */ + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +Subject: frop +Message-ID: <432df324@example.org> +To: nico@frop.example.org + +Frop +. +; + +test_set "envelope.to" "nico@frop.example.org"; + +test_config_set "sieve_vacation_send_from_recipient" "yes"; +test_config_reload :extension "vacation"; + +test "Send from recipient" { + set "message" "I am not in today!"; + set "subject" "Out of office"; + set "from" "user@example.com"; + + vacation :from "${from}" :subject "${subject}" "${message}"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not envelope "from" "nico@frop.example.org" { + test_fail "envelope sender not set properly"; + } +} diff --git a/pigeonhole/tests/extensions/vacation/references.sieve b/pigeonhole/tests/extensions/vacation/references.sieve new file mode 100644 index 0000000..77658f2 --- /dev/null +++ b/pigeonhole/tests/extensions/vacation/references.sieve @@ -0,0 +1,4 @@ +require "vacation"; + +vacation "I am on vacation."; +discard; diff --git a/pigeonhole/tests/extensions/vacation/reply.svtest b/pigeonhole/tests/extensions/vacation/reply.svtest new file mode 100644 index 0000000..55cc58d --- /dev/null +++ b/pigeonhole/tests/extensions/vacation/reply.svtest @@ -0,0 +1,536 @@ +require "vnd.dovecot.testsuite"; +require "envelope"; +require "vacation"; + +test_set "message" text: +From: sirius@example.com +To: sirius@example.com +Cc: stephan@example.com +Subject: Frop! + +Frop! +. +; + +/* + * No reply to own address + */ + +test_set "envelope.from" "stephan@example.com"; +test_set "envelope.to" "stephan@example.com"; + +test "No reply to own address" { + vacation "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + if test_message :smtp 0 { + test_fail "vacation not supposed to send message"; + } +} + +/* + * No reply to alternative address + */ + +test_result_reset; + +test_set "envelope.from" "sirius@example.com"; +test_set "envelope.to" "stephan@example.com"; + +test "No reply to alternative address" { + vacation :addresses "sirius@example.com" "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + if test_message :smtp 0 { + test_fail "vacation not supposed to send message"; + } +} + +/* + * No reply to mailing list + */ + +test_result_reset; + +test_set "message" text: +From: timo@example.com +To: dovecot@lists.example.com +List-ID: <dovecot.lists.example.com> +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "<dovecot-bounces+timo=example.com@lists.example.com>"; +test_set "envelope.to" "dovecot@lists.example.com"; + +test "No reply to mailing list" { + vacation "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + if test_message :smtp 0 { + test_fail "vacation not supposed to send message"; + } +} + + +/* + * No reply to bulk mail + */ + +test_result_reset; + +test_set "message" text: +From: spam@example.com +To: stephan@example.com +Precedence: bulk +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "spam@example.com"; +test_set "envelope.to" "stephan@example.com"; + +test "No reply to bulk mail" { + vacation "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + if test_message :smtp 0 { + test_fail "vacation not supposed to send message"; + } +} + +/* + * No reply to auto-submitted mail + */ + +test_result_reset; + +test_set "message" text: +From: spam@example.com +To: stephan@example.com +Auto-submitted: yes +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "spam@example.com"; +test_set "envelope.to" "stephan@example.com"; + +test "No reply to auto-submitted mail" { + vacation "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + if test_message :smtp 0 { + test_fail "vacation not supposed to send message"; + } +} + +/* + * No reply to Microsoft X-Auto-Response-Suppress - All + */ + +test_result_reset; + +test_set "message" text: +From: spam@example.com +To: stephan@example.com +X-Auto-Response-Suppress: All +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "spam@example.com"; +test_set "envelope.to" "stephan@example.com"; + +test "No reply to Microsoft X-Auto-Response-Suppress - All" { + vacation "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + if test_message :smtp 0 { + test_fail "vacation not supposed to send message"; + } +} + +/* + * No reply to Microsoft X-Auto-Response-Suppress - OOF + */ + +test_result_reset; + +test_set "message" text: +From: spam@example.com +To: stephan@example.com +X-Auto-Response-Suppress: OOF +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "spam@example.com"; +test_set "envelope.to" "stephan@example.com"; + +test "No reply to Microsoft X-Auto-Response-Suppress - OOF" { + vacation "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + if test_message :smtp 0 { + test_fail "vacation not supposed to send message"; + } +} + +/* + * No reply to Microsoft X-Auto-Response-Suppress - DR,OOF,RN + */ + +test_result_reset; + +test_set "message" text: +From: spam@example.com +To: stephan@example.com +X-Auto-Response-Suppress: DR, OOF, RN +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "spam@example.com"; +test_set "envelope.to" "stephan@example.com"; + +test "No reply to Microsoft X-Auto-Response-Suppress - DR,OOF,RN" { + vacation "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + if test_message :smtp 0 { + test_fail "vacation not supposed to send message"; + } +} + +/* + * No reply to system address + */ + +test_result_reset; + +test_set "message" text: +From: dovecot@lists.example.com +To: stephan@example.com +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "dovecot-request@lists.example.com"; +test_set "envelope.to" "stephan@example.com"; + +test "No reply to system address" { + vacation "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + if test_message :smtp 0 { + test_fail "vacation not supposed to send message"; + } +} + +/* + * No reply to implicitly delivered message + */ + +test_result_reset; + +test_set "message" text: +From: timo@example.com +To: all@example.com +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "timo@example.com"; +test_set "envelope.to" "stephan@example.com"; + +test_config_set "sieve_user_email" "jason@example.com"; +test_config_reload; + +test "No reply for implicitly delivered message" { + vacation "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + if test_message :smtp 0 { + test_fail "vacation not supposed to send message"; + } +} + +/* + * No reply to original recipient + */ + +test_result_reset; + +test_set "message" text: +From: timo@example.com +To: all@example.com +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "timo@example.com"; +test_set "envelope.to" "stephan@example.com"; +test_set "envelope.orig_to" "all@example.com"; + +test "No reply for original recipient" { + vacation "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + if test_message :smtp 0 { + test_fail "vacation not supposed to send message"; + } +} + +/* + * Reply for normal mail + */ + +test_result_reset; + +test_set "message" text: +From: timo@example.com +To: stephan@example.com +Subject: Frop! +Auto-submitted: no +Precedence: normal +X-Auto-Response-Suppress: None + +Frop! +. +; + +test_set "envelope.from" "timo@example.com"; +test_set "envelope.to" "stephan@example.com"; + +test "Reply for normal mail" { + vacation "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + if not test_message :smtp 0 { + test_fail "vacation did not reply"; + } +} + +/* + * Reply for :addresses + */ + +test_result_reset; + +test_set "message" text: +From: timo@example.com +To: all@example.com +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "timo@example.com"; +test_set "envelope.to" "stephan@example.com"; + +test "Reply for :addresses" { + vacation :addresses "all@example.com" "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + if not test_message :smtp 0 { + test_fail "vacation did not reply"; + } +} + +/* + * Reply for :addresses (case sensitivity) + */ + +test_result_reset; + +test_set "message" text: +From: timo@example.com +To: Stephan.Bosch@example.com +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "timo@example.com"; +test_set "envelope.to" "stephan@example.com"; + +test "Reply for :addresses (case sensitivity)" { + vacation :addresses "stephan.bosch@example.com" "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + if not test_message :smtp 0 { + test_fail "vacation did not reply"; + } +} + +/* + * Reply for original recipient + */ + +test_result_reset; + +test_set "message" text: +From: timo@example.com +To: all@example.com +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "timo@example.com"; +test_set "envelope.to" "stephan@example.com"; +test_set "envelope.orig_to" "all@example.com"; + +test_config_set "sieve_vacation_use_original_recipient" "yes"; +test_config_reload :extension "vacation"; + +test "Reply for original recipient" { + vacation "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + if not test_message :smtp 0 { + test_fail "vacation did not reply"; + } +} + +/* + * Reply for user's explicitly configured email address + */ + +test_result_reset; + +test_set "message" text: +From: timo@example.com +To: user@example.com +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "timo@example.com"; +test_set "envelope.to" "jibberish@example.com"; +test_set "envelope.orig_to" "even-more-jibberish@example.com"; + +test_config_set "sieve_user_email" "user@example.com"; +test_config_reload; + +test "Reply for user's explicitly configured email address" { + vacation "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + if not test_message :smtp 0 { + test_fail "vacation did not reply"; + } + + if not address "from" "user@example.com" { + test_fail "mail not sent from user's email address"; + } +} + +/* + * Reply for any recipient + */ + +test_result_reset; + +test_set "message" text: +From: timo@example.com +To: all@example.com +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "timo@example.com"; +test_set "envelope.to" "stephan@example.com"; + +test_config_set "sieve_vacation_dont_check_recipient" "yes"; +test_config_reload :extension "vacation"; + +test "Reply for any recipient" { + vacation "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + if not test_message :smtp 0 { + test_fail "vacation did not reply"; + } +} + + + + diff --git a/pigeonhole/tests/extensions/vacation/smtp.svtest b/pigeonhole/tests/extensions/vacation/smtp.svtest new file mode 100644 index 0000000..40dbd89 --- /dev/null +++ b/pigeonhole/tests/extensions/vacation/smtp.svtest @@ -0,0 +1,199 @@ +require "vnd.dovecot.testsuite"; +require "envelope"; +require "vacation"; +require "variables"; + +test_set "message" text: +From: stephan@example.org +To: tss@example.net +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "timo@example.net"; + +test "Basic" { + vacation :addresses "tss@example.net" :from "Timo Sirainen <sirainen@example.net>" "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + test_message :smtp 0; + + if not address :is "to" "sirius@example.org" { + test_fail "to address incorrect"; + } + + if not address :is "from" "sirainen@example.net" { + test_fail "from address incorrect"; + } + + if not envelope :is "to" "sirius@example.org" { + test_fail "envelope recipient incorrect"; + } + + if not envelope :is "from" "" { + test_fail "envelope sender not null"; + } +} + +test_result_reset; +test_set "envelope.from" "<>"; + +test "Null Sender" { + vacation :addresses "tss@example.net" "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + if test_message :smtp 0 { + test_fail "reject sent message to NULL sender"; + } +} + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +To: timo@example.net +Cc: stephan@friep.example.com +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "timo@example.net"; + +test "Envelope.to == To" { + vacation "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + test_message :smtp 0; + + if not address :is "from" "timo@example.net" { + test_fail "from address incorrect"; + } + + if not envelope :is "from" "" { + test_fail "envelope sender not null"; + } +} + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +To: tss@example.net +Cc: stephan@friep.example.com +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "timo@example.net"; + +test "Envelope.to != To" { + vacation :addresses "tss@example.net" "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + test_message :smtp 0; + + if not address :is "from" "tss@example.net" { + test_fail "from address incorrect"; + } + + if not envelope :is "from" "" { + test_fail "envelope sender not null"; + } +} + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +To: tss@example.net +Cc: colleague@example.net +Subject: Frop! + +Frop! +. +; + +test_set "envelope.from" "sirius@example.org"; +test_set "envelope.to" "colleague@example.net"; + +test "Cc" { + vacation "I am gone"; + + if not test_result_execute { + test_fail "failed to execute vacation"; + } + + test_message :smtp 0; + + if not address :is "from" "colleague@example.net" { + if address :matches "from" "*" { } + test_fail "from address incorrect: ${1}"; + } + + if not envelope :is "from" "" { + test_fail "envelope sender not null"; + } +} + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +Subject: No subject of discussion +To: nicëøôçêè—öxample.org + +Frop +. +; + +test "Bad recipient address (from message)" { + vacation :subject "Tulips" "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + +} + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +Subject: No subject of discussion +To: tss@example.net + +Frop +. +; + +test_set "envelope.to" "nicëøôçêè—öxample.org"; + +test "Bad recipient address (from envelope)" { + vacation :subject "Tulips" "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + +} diff --git a/pigeonhole/tests/extensions/vacation/utf-8.svtest b/pigeonhole/tests/extensions/vacation/utf-8.svtest new file mode 100644 index 0000000..e94f7b9 --- /dev/null +++ b/pigeonhole/tests/extensions/vacation/utf-8.svtest @@ -0,0 +1,168 @@ +require "vnd.dovecot.testsuite"; +require "vacation"; +require "variables"; + +test_set "message" text: +From: stephan@example.org +Subject: frop +References: <1234@local.machine.example> <3456@example.net> + <435444@ttms.com> <4223@froop.example.net> <m345444444@message-id.exp> +Message-ID: <432df324@example.org> +To: nico@frop.example.org + +Frop +. +; + +test "UTF-8 Subject" { + /* Trigger vacation response with rediculous Russian subject */ + vacation :subject "Auto: Я могу есть стекло, оно мне не вредит." + "I am not in today"; + + /* Execute Sieve result (sending message to dummy SMTP) */ + if not test_result_execute { + test_fail "execution of result failed"; + } + + /* Retrieve message from dummy SMTP and set it as the active message under + * test. + */ + test_message :smtp 0; + + set "expected" "Auto: Я могу есть стекло, оно мне не вредит."; + if not header :is "subject" "${expected}" { + if header :matches "subject" "*" { set "subject" "${1}"; } + + test_fail text: +subject header is not encoded/decoded properly: +expected: ${expected} +decoded: ${subject} +. +; + } +} + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +Subject: frop +References: <1234@local.machine.example> <3456@example.net> + <435444@ttms.com> <4223@froop.example.net> <m345444444@message-id.exp> +Message-ID: <432df324@example.org> +To: nico@frop.example.org + +Frop +. +; + + +test "MIME Encoded Subject" { + /* Trigger vacation response with rediculous Russian subject */ + vacation :subject "=?utf-8?b?w4TDlsOc?= sadasd" + "I am not in today"; + + /* Execute Sieve result (sending message to dummy SMTP) */ + if not test_result_execute { + test_fail "execution of result failed"; + } + + /* Retrieve message from dummy SMTP and set it as the active message under + * test. + */ + test_message :smtp 0; + + set "expected" "ÄÖÜ sadasd"; + if not header :is "subject" "${expected}" { + if header :matches "subject" "*" { set "subject" "${1}"; } + + test_fail text: +subject header is not encoded/decoded properly: +expected: ${expected} +decoded: ${subject} +. +; + } +} + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +Subject: frop +Message-ID: <432df324@example.org> +To: <g.m.karotte@example.com> + +Frop +. +; + + +test "MIME Encoded From" { + vacation :subject "Frop" + :from "=?utf-8?q?G=C3=BCnther?= M. Karotte <g.m.karotte@example.com>" + "I am not in today"; + + /* Execute Sieve result (sending message to dummy SMTP) */ + if not test_result_execute { + test_fail "execution of result failed"; + } + + /* Retrieve message from dummy SMTP and set it as the active message under + * test. + */ + test_message :smtp 0; + + set "expected" "Günther M. Karotte <g.m.karotte@example.com>"; + if not header :is "from" "${expected}" { + if header :matches "from" "*" { set "decoded" "${1}"; } + + test_fail text: +from header is not encoded/decoded properly: +expected: ${expected} +decoded: ${decoded} +. +; + } +} + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +Subject: frop +Message-ID: <432df324@example.org> +To: <g.m.karotte@example.com> + +Frop +. +; + + +test "MIME Encoded From - UTF-8 in phrase" { + vacation :subject "Frop" + :from "Günther M. Karotte <g.m.karotte@example.com>" + "I am not in today"; + + /* Execute Sieve result (sending message to dummy SMTP) */ + if not test_result_execute { + test_fail "execution of result failed"; + } + + /* Retrieve message from dummy SMTP and set it as the active message under + * test. + */ + test_message :smtp 0; + + set "expected" "Günther M. Karotte <g.m.karotte@example.com>"; + if not header :is "from" "${expected}" { + if header :matches "from" "*" { set "decoded" "${1}"; } + + test_fail text: +from header is not encoded/decoded properly: +expected: ${expected} +decoded: ${decoded} +. +; + } +} diff --git a/pigeonhole/tests/extensions/variables/basic.svtest b/pigeonhole/tests/extensions/variables/basic.svtest new file mode 100644 index 0000000..f01aeeb --- /dev/null +++ b/pigeonhole/tests/extensions/variables/basic.svtest @@ -0,0 +1,223 @@ +require "vnd.dovecot.testsuite"; +require "variables"; + +test_set "message" text: +From: stephan@example.org +To: test@example.com +Subject: Variables test + +Testing variables... +. +; + +/* + * Substitution syntax + */ + +test "Unknown variables" { + set "q" "a"; + set "qw" "bb"; + set "qwe" "ccc"; + set "qwer" "dddd"; + set "qwert" "ccc"; + + if anyof ( + not string "[${qwerty}]" "[]", + not string "[${20}]" "[]" + ) { + test_fail "unknown variable not substituted with empty string"; + } +} + +test "One pass" { + set "something" "value"; + set "s" "$"; + + if string "${s}{something}" "value" { + test_fail "somehow variable string is scanned multiple times"; + } + + if not string :matches "${s}{something}" "?{something}" { + test_fail "unexpected result"; + } +} + +test "Syntax errors" { + set "s" "$"; + set "variable" "nonsense"; + + if anyof ( + not string "$" "${s}", + not string "${" "${s}{", + not string "${a" "${s}{a", + not string "${$}" "${s}{$}", + not string "${%%%%}" "${s}{%%%%}", + not string "${0.s}" "${s}{0.s}", + not string "&%${}!" "&%${s}{}!", + not string "${doh!}" "${s}{doh!}" ) + { + test_fail "variables substitution changed substring not matching variable-ref"; + } +} + +test "RFC syntax examples" { + # The variable "company" holds the value "ACME". No other variables + # are set. + set "company" "ACME"; + + # "${full}" => the empty string + if not string :is "${full}" "" { + test_fail "unknown variable did not yield empty string"; + } + + # "${company}" => "ACME" + if not string :is "${company}" "ACME" { + test_fail "assigned variable did not get substituted"; + } + + # "${BAD${Company}" => "${BADACME" + if not string :is "${BAD${Company}" "${BADACME" { + test_fail "'BADACME' test did not yield expected result"; + } + + #"${President, ${Company} Inc.}" + # => "${President, ACME Inc.}" + if not string "${President, ${Company} Inc.}" + "${President, ACME Inc.}" { + test_fail "'Company president' test did not yield expected result"; + } +} + +/* + * Variable assignments + */ + +test "Basic assignment" { + set "test" "Value"; + + if not string :is "${test}" "Value" { + test_fail "variable assignment failed"; + } + + if string :is "${test}" "value" { + test_fail "string test failed"; + } +} + +test "Assignment overwritten" { + set "test" "Value"; + set "test" "More"; + + if not string :is "${test}" "More" { + test_fail "variable assignment failed"; + } + + if string :is "${test}" "Value" { + test_fail "value not overwritten"; + } + + if string :is "${test}" "nonsense" { + test_fail "string test failed"; + } +} + +test "Two assignments" { + set "test" "Value"; + set "test2" "More"; + + if not string :is "${test}" "Value" { + test_fail "variable assignment failed"; + } + + if string :is "${test}" "More" { + test_fail "assignments to different variables overlap"; + } + + if string :is "${test}" "nonsense" { + test_fail "string test failed"; + } +} + +test "Variables case-insensitive" { + set "VeRyElAboRATeVaRIABLeName" "interesting value"; + + if not string "${veryelaboratevariablename}" "interesting value" { + test_fail "variable names are case sensitive (lower case try)"; + } + + if not string "${VERYELABORATEVARIABLENAME}" "interesting value" { + test_fail "variable names are case sensitive (upper case try)"; + } +} + +test "RFC set command example" { + set "honorific" "Mr"; + set "first_name" "Wile"; + set "last_name" "Coyote"; + set "vacation" text: +Dear ${HONORIFIC} ${last_name}, +I'm out, please leave a message after the meep. +. +; + if not string :is :comparator "i;octet" "${VAcaTION}" text: +Dear Mr Coyote, +I'm out, please leave a message after the meep. +. + { + test_fail "failed to set variable correctly: ${VAcaTION}"; + } +} + +/* + * Variable substitution + */ + +test "Multi-line string substitution" { + set "name" "Stephan Bosch"; + set "address" "stephan@example.org"; + set "subject" "Test message"; + + set "message" text: # Message with substitutions +From: ${name} <${address}> +To: Bertus van Asseldonk <b.vanasseldonk@nl.example.com> +Subject: ${subject} + +This is a test message. +. +; + if not string :is "${message}" text: +From: Stephan Bosch <stephan@example.org> +To: Bertus van Asseldonk <b.vanasseldonk@nl.example.com> +Subject: Test message + +This is a test message. +. + { + test_fail "variable substitution failed"; + } +} + +test "Multiple substitutions" { + set "a" "the monkey"; + set "b" "a nut"; + set "c" "the fish"; + set "d" "on fire"; + set "e" "eats"; + set "f" "is"; + + if not string :is "${a} ${e} ${b}" "the monkey eats a nut" { + test_fail "variable substitution failed (1)"; + } + + if not string :is "${c} ${f} ${d}" "the fish is on fire" { + test_fail "variable substitution failed (2)"; + } + + set :upperfirst "sentence" "${a} ${e} ${b}"; + + if not string :is "${sentence}" "The monkey eats a nut" { + test_fail "modified variable substitution failed"; + } +} + + diff --git a/pigeonhole/tests/extensions/variables/errors.svtest b/pigeonhole/tests/extensions/variables/errors.svtest new file mode 100644 index 0000000..652075f --- /dev/null +++ b/pigeonhole/tests/extensions/variables/errors.svtest @@ -0,0 +1,34 @@ +require "vnd.dovecot.testsuite"; + +require "comparator-i;ascii-numeric"; +require "relational"; + +test "Invalid namespaces (FIXME: count only)" { + if test_script_compile "errors/namespace.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "5" { + test_fail "wrong number of errors reported"; + } +} + +test "Invalid set command invocations (FIXME: count only)" { + if test_script_compile "errors/set.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "7" { + test_fail "wrong number of errors reported"; + } +} + +test "Limits (FIXME: count only)" { + if test_script_compile "errors/limits.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "6" { + test_fail "wrong number of errors reported"; + } +} diff --git a/pigeonhole/tests/extensions/variables/errors/limits.sieve b/pigeonhole/tests/extensions/variables/errors/limits.sieve new file mode 100644 index 0000000..3c9dbbd --- /dev/null +++ b/pigeonhole/tests/extensions/variables/errors/limits.sieve @@ -0,0 +1,287 @@ +require "variables"; + +# Not an error (0) +set "var123456789012345678901234567890" "value"; + +# Exceed the maximum variable name length (1) +set "var123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" "value"; + +# Must yield unknown namespace error (no limit exceeded) (1) +set "namespace.sub.sub.variable" "value"; + +# Must yield unknown namespace error (exceeds element limit) (1) +set "namespace.sub.sub.sub.variable" "value"; + +# Not an error (0) +if string "${32}" "value" { + stop; +} + +# Exceed the maximum match value index (1) +if string "${33}" "value" { + stop; +} + +# Exceed the maximum number of declared variables (1!) +set "var001" "value"; +set "var002" "value"; +set "var003" "value"; +set "var004" "value"; +set "var005" "value"; +set "var006" "value"; +set "var007" "value"; +set "var008" "value"; +set "var009" "value"; +set "var010" "value"; +set "var011" "value"; +set "var012" "value"; +set "var013" "value"; +set "var014" "value"; +set "var015" "value"; +set "var016" "value"; +set "var017" "value"; +set "var018" "value"; +set "var019" "value"; +set "var020" "value"; +set "var021" "value"; +set "var022" "value"; +set "var023" "value"; +set "var024" "value"; +set "var025" "value"; +set "var026" "value"; +set "var027" "value"; +set "var028" "value"; +set "var029" "value"; +set "var030" "value"; +set "var031" "value"; +set "var032" "value"; +set "var033" "value"; +set "var034" "value"; +set "var035" "value"; +set "var036" "value"; +set "var037" "value"; +set "var038" "value"; +set "var039" "value"; +set "var040" "value"; +set "var041" "value"; +set "var042" "value"; +set "var043" "value"; +set "var044" "value"; +set "var045" "value"; +set "var046" "value"; +set "var047" "value"; +set "var048" "value"; +set "var049" "value"; +set "var050" "value"; +set "var051" "value"; +set "var052" "value"; +set "var053" "value"; +set "var054" "value"; +set "var055" "value"; +set "var056" "value"; +set "var057" "value"; +set "var058" "value"; +set "var059" "value"; +set "var060" "value"; +set "var061" "value"; +set "var062" "value"; +set "var063" "value"; +set "var064" "value"; +set "var065" "value"; +set "var066" "value"; +set "var067" "value"; +set "var068" "value"; +set "var069" "value"; +set "var070" "value"; +set "var071" "value"; +set "var072" "value"; +set "var073" "value"; +set "var074" "value"; +set "var075" "value"; +set "var076" "value"; +set "var077" "value"; +set "var078" "value"; +set "var079" "value"; +set "var080" "value"; +set "var081" "value"; +set "var082" "value"; +set "var083" "value"; +set "var084" "value"; +set "var085" "value"; +set "var086" "value"; +set "var087" "value"; +set "var088" "value"; +set "var089" "value"; +set "var090" "value"; +set "var091" "value"; +set "var092" "value"; +set "var093" "value"; +set "var094" "value"; +set "var095" "value"; +set "var096" "value"; +set "var097" "value"; +set "var098" "value"; +set "var099" "value"; + +set "var100" "value"; +set "var101" "value"; +set "var102" "value"; +set "var103" "value"; +set "var104" "value"; +set "var105" "value"; +set "var106" "value"; +set "var107" "value"; +set "var108" "value"; +set "var109" "value"; +set "var110" "value"; +set "var111" "value"; +set "var112" "value"; +set "var113" "value"; +set "var114" "value"; +set "var115" "value"; +set "var116" "value"; +set "var117" "value"; +set "var118" "value"; +set "var119" "value"; +set "var120" "value"; +set "var121" "value"; +set "var122" "value"; +set "var123" "value"; +set "var124" "value"; +set "var125" "value"; +set "var126" "value"; +set "var127" "value"; +set "var128" "value"; +set "var129" "value"; +set "var130" "value"; +set "var131" "value"; +set "var132" "value"; +set "var133" "value"; +set "var134" "value"; +set "var135" "value"; +set "var136" "value"; +set "var137" "value"; +set "var138" "value"; +set "var139" "value"; +set "var140" "value"; +set "var141" "value"; +set "var142" "value"; +set "var143" "value"; +set "var144" "value"; +set "var145" "value"; +set "var146" "value"; +set "var147" "value"; +set "var148" "value"; +set "var149" "value"; +set "var150" "value"; +set "var151" "value"; +set "var152" "value"; +set "var153" "value"; +set "var154" "value"; +set "var155" "value"; +set "var156" "value"; +set "var157" "value"; +set "var158" "value"; +set "var159" "value"; +set "var160" "value"; +set "var161" "value"; +set "var162" "value"; +set "var163" "value"; +set "var164" "value"; +set "var165" "value"; +set "var166" "value"; +set "var167" "value"; +set "var168" "value"; +set "var169" "value"; +set "var170" "value"; +set "var171" "value"; +set "var172" "value"; +set "var173" "value"; +set "var174" "value"; +set "var175" "value"; +set "var176" "value"; +set "var177" "value"; +set "var178" "value"; +set "var179" "value"; +set "var180" "value"; +set "var181" "value"; +set "var182" "value"; +set "var183" "value"; +set "var184" "value"; +set "var185" "value"; +set "var186" "value"; +set "var187" "value"; +set "var188" "value"; +set "var189" "value"; +set "var190" "value"; +set "var191" "value"; +set "var192" "value"; +set "var193" "value"; +set "var194" "value"; +set "var195" "value"; +set "var196" "value"; +set "var197" "value"; +set "var198" "value"; +set "var199" "value"; +set "var200" "value"; + +set "var201" "value"; +set "var202" "value"; +set "var203" "value"; +set "var204" "value"; +set "var205" "value"; +set "var206" "value"; +set "var207" "value"; +set "var208" "value"; +set "var209" "value"; +set "var210" "value"; +set "var211" "value"; +set "var212" "value"; +set "var213" "value"; +set "var214" "value"; +set "var215" "value"; +set "var216" "value"; +set "var217" "value"; +set "var218" "value"; +set "var219" "value"; +set "var220" "value"; +set "var221" "value"; +set "var222" "value"; +set "var223" "value"; +set "var224" "value"; +set "var225" "value"; +set "var226" "value"; +set "var227" "value"; +set "var228" "value"; +set "var229" "value"; +set "var230" "value"; +set "var231" "value"; +set "var232" "value"; +set "var233" "value"; +set "var234" "value"; +set "var235" "value"; +set "var236" "value"; +set "var237" "value"; +set "var238" "value"; +set "var239" "value"; +set "var240" "value"; +set "var241" "value"; +set "var242" "value"; +set "var243" "value"; +set "var244" "value"; +set "var245" "value"; +set "var246" "value"; +set "var247" "value"; +set "var248" "value"; +set "var249" "value"; +set "var250" "value"; +set "var251" "value"; +set "var252" "value"; +set "var253" "value"; +set "var254" "value"; +set "var255" "value"; +set "var256" "value"; +set "var257" "value"; +set "var258" "value"; +set "var259" "value"; +set "var260" "value"; diff --git a/pigeonhole/tests/extensions/variables/errors/namespace.sieve b/pigeonhole/tests/extensions/variables/errors/namespace.sieve new file mode 100644 index 0000000..e11ac6d --- /dev/null +++ b/pigeonhole/tests/extensions/variables/errors/namespace.sieve @@ -0,0 +1,8 @@ +require "variables"; +require "fileinto"; + +set "namespace.frop" "value"; +set "complex.struct.frop" "value"; + +fileinto "${namespace.frop}"; +fileinto "${complex.struct.frop}"; diff --git a/pigeonhole/tests/extensions/variables/errors/set.sieve b/pigeonhole/tests/extensions/variables/errors/set.sieve new file mode 100644 index 0000000..07c393a --- /dev/null +++ b/pigeonhole/tests/extensions/variables/errors/set.sieve @@ -0,0 +1,19 @@ +require "variables"; + +# Invalid variable name +set "${frop}" "frop"; +set "...." "frop"; +set "name." "frop"; +set ".name" "frop"; + +# Not an error +set "\n\a\m\e" "frop"; + +# Trying to assign match variable; +set "0" "frop"; + +# Not an error +set :UPPER "name" "frop"; + +# Invalid tag +set :inner "name" "frop"; diff --git a/pigeonhole/tests/extensions/variables/limits.svtest b/pigeonhole/tests/extensions/variables/limits.svtest new file mode 100644 index 0000000..7397713 --- /dev/null +++ b/pigeonhole/tests/extensions/variables/limits.svtest @@ -0,0 +1,435 @@ +require "vnd.dovecot.testsuite"; +require "variables"; +require "encoded-character"; + +/* + * Variable size limit + */ + +test_config_set "sieve_variables_max_variable_size" "4000"; +test_config_reload :extension "variables"; + +set "a" text: +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +. +; + +test "Variable size limit" { + set :length "alen" "${a}"; + + if not string "${alen}" "4000" { + test_fail "variable 'a' not 4000 bytes long (${alen}) [0]"; + } + + set "a" "${a}b"; + set :length "alen" "${a}"; + + if not string "${alen}" "4000" { + test_fail "variable 'a' not 4000 bytes long (${alen}) [1]"; + } + + set "a" "${a}${a}"; + set :length "alen" "${a}"; + + if not string "${alen}" "4000" { + test_fail "variable 'a' not 4000 bytes long (${alen}) [2]"; + } + + test_config_set "sieve_variables_max_variable_size" "8000"; + test_config_reload :extension "variables"; + + set "a" "${a}${a}"; + set :length "alen" "${a}"; + + if not string "${alen}" "8000" { + test_fail "variable 'a' not 8000 bytes long (${alen})"; + } +} + +/* + * Variable size limit UTF-8 + */ + +test_config_set "sieve_variables_max_variable_size" "4000"; +test_config_reload :extension "variables"; + +set "b" text: +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +012345678901234567890123456789012345678901234567 +01234567890123456789012345678901234567890123456 +. +; + +test "Variable size limit UTF-8" { + set :length "blen" "${b}"; + + if not string "${blen}" "3999" { + test_fail "variable 'b' not 3999 bytes long (${blen}) [0]"; + } + + set "b" "${b}${unicode:4e03}"; + set :length "blen" "${b}"; + + if not string "${blen}" "3999" { + test_fail "variable 'b' not 3999 bytes long (${blen}) [1]"; + } + + set "b" "${b}ccc"; + set :length "blen" "${b}"; + + if not string "${blen}" "4000" { + test_fail "variable 'b' not 4000 bytes long (${blen})"; + } +} + +/* + * :quotewildcard variable size limit + */ + +test_config_set "sieve_variables_max_variable_size" "4000"; +test_config_reload :extension "variables"; + +set "c" text: +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +************************************** +. +; + +test ":quotewildcard variable size limit" { + set :length "clen" "${c}"; + + if not string "${clen}" "4000" { + test_fail "variable 'c' not 4000 bytes long (${clen}) [0]"; + } + + set "d" "0${c}"; + set :quotewildcard "c" "${c}"; + set :length "clen" "${c}"; + + if not string "${clen}" "4000" { + test_fail "variable 'c' not 4000 bytes long (${clen}) [1]"; + } + + set :quotewildcard "d" "${d}"; + set :length "dlen" "${d}"; + + if not string "${dlen}" "3999" { + test_fail "variable 'd' not 3999 bytes long (${dlen})"; + } + + if not string :is text: +${d} +. +text: +0\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* +\*\*\*\*\*\*\*\*\*\* +. + { + test_fail "variable 'd' has unexpected value"; + } +} + diff --git a/pigeonhole/tests/extensions/variables/match.svtest b/pigeonhole/tests/extensions/variables/match.svtest new file mode 100644 index 0000000..11c0701 --- /dev/null +++ b/pigeonhole/tests/extensions/variables/match.svtest @@ -0,0 +1,365 @@ +require "vnd.dovecot.testsuite"; + +require "variables"; + +/* + * RFC compliance + */ + +# Test acceptance of leading zeroes +test "RFC - leading zeroes" { + if not string :matches "frop:frup:frop" "*:*:*" { + test_fail "failed to match"; + } + + if not string :is "${0000002}" "frup" { + test_fail "incorrect match value (0000002): ${0000002}"; + } +} + +# Test non-greedyness +test "RFC - not greedy" { + if not string :matches "frop.......frop.........frop...." "?*frop*" { + test_fail "failed to match"; + } + + if not string :is "${1}${2}${3}" "frop................frop...." { + test_fail "incorrect match values: ${1}${2}${3}"; + } +} + +# Index out of range +test "RFC - index out of range" { + if not string :matches "test" "*" { + test_fail "failed to match (impossible)"; + } + + if not string :is "${2}" "" { + test_fail "incorrect match value: '${2}'"; + } +} + +# Index 0 +test "RFC - index 0" { + if not string :matches "a b c d e f g" "? ? ? ? ? ? ?" { + test_fail "failed to match"; + } + + if not string :is "${0}" "a b c d e f g" { + test_fail "incorrect match value: ${0}"; + } +} + +# Test short-circuit +test "RFC - test short-circuit" { + if not anyof ( + string :matches "a b c d e f g" "? ?", + string :matches "puk pok puk pok" "pu*ok", + string :matches "snot kip snot" "snot*snot" + ) { + test_fail "failed to match any"; + } + + if string :is "${1}" " kip " { + test_fail "did not short-circuit test execution or intented test failed."; + } + + if not string :is "${1}" "k pok puk p" { + test_fail "incorrect match value: ${1}"; + } +} + +# Test overwriting only on match +test "RFC - values overwrite" { + set "sentence1" "the cat jumps off the table"; + set "sentence2" "the dog barks at the cat in the alley"; + + if not string :matches "${sentence1}" "the * jumps off the *" { + test_fail "failed to match first sentence"; + } + + if not string :is "${1}:${2}" "cat:table" { + test_fail "invalid match values"; + } + + if string :matches "${sentence2}" "the * barks at the * in the store" { + test_fail "should not have matched second sentence"; + } + + if not string :is "${1}:${2}" "cat:table" { + test_fail "should have preserved match values"; + } + + if not string :matches "${sentence2}" "the * barks at the * in the alley" { + test_fail "failed to match the second sentence (second time)"; + } + + if not string :is "${1}:${2}" "dog:cat" { + test_fail "should have overwritten match values"; + } +} + +test "RFC - example" { + test_set "message" text: +Subject: [acme-users] [fwd] version 1.0 is out +List-Id: Dovecot Mailing List <dovecot@dovecot.example.net> +To: coyote@ACME.Example.COM +Fom: stephan@example.org + +Test message. +. +; + if header :matches "List-ID" "*<*@*" { + if not string "INBOX.lists.${2}" "INBOX.lists.dovecot" { + test_fail "incorrect match value: INBOX.lists.${2}"; + } + } else { + test_fail "failed to match list header"; + } + + # Imagine the header + # Subject: [acme-users] [fwd] version 1.0 is out + if header :matches "Subject" "[*] *" { + # ${1} will hold "acme-users", + # ${2} will hold "[fwd] version 1.0 is out" + + if anyof ( + not string "${1}" "acme-users", + not string "${2}" "[fwd] version 1.0 is out" + ) { + test_fail "invalid match values: ${1} ${2}"; + } + } else { + test_fail "failed to match subject"; + } + + # Imagine the header + # To: coyote@ACME.Example.COM + if address :matches ["To", "Cc"] ["coyote@**.com", + "wile@**.com"] { + # ${0} is the matching address + # ${1} is always the empty string + # ${2} is part of the domain name ("ACME.Example") + + if anyof ( + not string "${0}" "coyote@ACME.Example.COM", + not string "${1}" "", + not string "${2}" "ACME.Example" + ) { + test_fail "invalid match values: ${0}, ${1}, ${2}"; + } + } else { + # Control wouldn't reach this block if any match was + # successful, so no match variables are set at this + # point. + + test_fail "failed to match to address"; + } + + if anyof (true, address :domain :matches "To" "*.com") { + # The second test is never evaluated, so there are + # still no match variables set. + + /* FIXME: not compliant */ + } +} + +/* + * Generic tests + */ + +set "match1" "Test of general stupidity"; + +test "Begin" { + if not string :matches "${match1}" "Test of *" { + test_fail "should have matched"; + } + + if not string :is "${1}" "general stupidity" { + test_fail "match value incorrect"; + } +} + +test "Begin no match" { + if string :matches "${match1}" "of *" { + test_fail "should not have matched"; + } +} + +set "match2" "toptoptop"; + +test "End" { + if not string :matches "${match2}" "*top" { + test_fail "should have matched"; + } + + if not string :is "${1}" "toptop" { + test_fail "match value incorrect"; + } +} + +set "match3" "ik ben een tukker met grote oren en een lelijke broek."; + +test "Multiple" { + if not string :matches "${match3}" "ik ben * met * en *." { + test_fail "should have matched"; + } + + set "line" "Hij is ${1} met ${2} en ${3}!"; + + if not string :is "${line}" + "Hij is een tukker met grote oren en een lelijke broek!" { + test_fail "match values incorrect: ${line}"; + } +} + +set "match4" "beter van niet?"; + +test "Escape" { + if not string :matches "${match4}" "*\\?" { + test_fail "should have matched"; + } + + if not string :is "${1}" "beter van niet" { + test_fail "match value incorrect: ${1}"; + } +} + +set "match5" "The quick brown fox jumps over the lazy dog."; + +test "Alphabet ?" { + if not string :matches "${match5}" "T?? ????? ????? ?o? ?u??? o?er ?he ???? ?o?." { + test_fail "should have matched"; + } + + set "alphabet" "${22}${8}${6}${25}${2}${13}${26}${1}${5}${15}${7}${21}${16}${12}${10}${17}${3}${9}${18}${20}${4}${19}${11}${14}${24}${23}"; + + if not string :is "${alphabet}" "abcdefghijklmnopqrstuvwxyz" { + test_fail "match values incorrect: ${alphabet}"; + } + + if string :matches "${match5}" "T?? ????? ?w??? ?o? ?u??? o?er ?he ???? ?o?." { + test_fail "should not have matched"; + } +} + +set "match6" "zero:one:zero|three;one;zero/five"; + +test "Words sep ?" { + + if not string :matches "${match6}" "*one?zero?five" { + test_fail "should have matched"; + } + + if not string :is "${1}${2}${3}" "zero:one:zero|three;;/" { + test_fail "incorrect match values: ${1} ${2} ${3}"; + } +} + +set "match7" "frop"; + +test "Letters begin ?" { + if not string :matches "${match7}" "??op" { + test_fail "should have matched"; + } + + set "val" "${0}:${1}:${2}:${3}:"; + + if not string :is "${val}" "frop:f:r::" { + test_fail "incorrect match values: ${val}"; + } +} + +test "Letters end ?" { + if not string :matches "${match7}" "fr??" { + test_fail "should have matched"; + } + + set "val" "${0}:${1}:${2}:${3}:"; + + if not string :is "${val}" "frop:o:p::" { + test_fail "incorrect match values: ${val}"; + } +} + +set "match8" "klopfropstroptop"; + +test "Letters words *? - 1" { + if not string :matches "${match8}" "*fr??*top" { + test_fail "should have matched"; + } + + set "val" ":${0}:${1}:${2}:${3}:${4}:${5}:"; + + if not string :is "${val}" ":klopfropstroptop:klop:o:p:strop::" { + test_fail "incorrect match values: ${val}"; + } +} + +test "Letters words *? - 2" { + if not string :matches "${match8}" "?*fr??*top" { + test_fail "should have matched"; + } + + set "val" ":${0}:${1}:${2}:${3}:${4}:${5}:${6}:"; + + if not string :is "${val}" ":klopfropstroptop:k:lop:o:p:strop::" { + test_fail "incorrect match values: ${val}"; + } +} + +test "Letters words *? backtrack" { + if not string :matches "${match8}" "*?op" { + test_fail "should have matched"; + } + + set "val" ":${0}:${1}:${2}:${3}:${4}:"; + + if not string :is "${val}" ":klopfropstroptop:klopfropstrop:t:::" { + test_fail "incorrect match values: ${val}"; + } +} + +test "Letters words *? first" { + if not string :matches "${match8}" "*?op*" { + test_fail "failed to match"; + } + + set "val" ":${0}:${1}:${2}:${3}:${4}:"; + + if not string :is "${val}" ":klopfropstroptop:k:l:fropstroptop::" { + test_fail "incorrect match values: ${val}"; + } +} + +/* + * Specific tests + */ + +test_set "message" text: +Return-path: <stephan@xi.example.org> +Envelope-to: stephan@xi.example.org +Delivery-date: Sun, 01 Feb 2009 11:29:57 +0100 +Received: from stephan by xi.example.org with local (Exim 4.69) + (envelope-from <stephan@xi.example.org>) + id 1LTZaP-0007h3-2e + for stephan@xi.example.org; Sun, 01 Feb 2009 11:29:57 +0100 +From: Dovecot Debian Builder <stephan.example.org@xi.example.org> +To: stephan@xi.example.org +Subject: Log for failed build of dovecot_2:1.2.alpha5-0~auto+159 (dist=hardy) +Message-Id: <E1LTZaP-0007h3-2e@xi.example.org> +Date: Sun, 01 Feb 2009 11:29:57 +0100 + +Automatic build of dovecot_1.2.alpha5-0~auto+159 on xi by sbuild/i386 0.57.7 +. +; + +test "Match combined" { + if not header :matches "subject" "Log for ?* build of *" { + test_fail "failed to match"; + } + + if not string "${1}${2}" "failed" { + test_fail "incorrect match values: ${1}${2}"; + } +} diff --git a/pigeonhole/tests/extensions/variables/modifiers.svtest b/pigeonhole/tests/extensions/variables/modifiers.svtest new file mode 100644 index 0000000..37068b6 --- /dev/null +++ b/pigeonhole/tests/extensions/variables/modifiers.svtest @@ -0,0 +1,160 @@ +require "vnd.dovecot.testsuite"; +require "variables"; +require "encoded-character"; + +/* + * Modifiers + */ + +test "Modifier :lower" { + set :lower "test" "VaLuE"; + + if not string :is "${test}" "value" { + test_fail "modified variable assignment failed"; + } +} + +test "Modifiers :lower :upperfirst" { + set :lower :upperfirst "test" "vAlUe"; + + if string :is "${test}" "value" { + test_fail "modifiers applied with wrong precedence"; + } + + if not string :is "${test}" "Value" { + test_fail "modified variable assignment failed"; + } +} + +test "Modifiers :upperfirst :lower" { + set :upperfirst :lower "test" "vAlUe"; + + if string :is "${test}" "value" { + test_fail "modifiers applied with wrong precedence"; + } + + if not string :is "${test}" "Value" { + test_fail "modified variable assignment failed"; + } +} + +test "Modifier :upper" { + set :upper "test" "vAlUe"; + + if not string :is "${test}" "VALUE" { + test_fail "modified variable assignment failed"; + } +} + +test "Modifiers :upper :lowerfirst" { + set :upper :lowerfirst "test" "VaLuE"; + + if string :is "${test}" "VALUE" { + test_fail "modifiers applied with wrong precedence"; + } + + if not string :is "${test}" "vALUE" { + test_fail "modified variable assignment failed"; + } +} + +test "Modifiers :lowerfirst :upper" { + set :lowerfirst :upper "test" "VaLuE"; + + if string :is "${test}" "VALUE" { + test_fail "modifiers applied with wrong precedence"; + } + + if not string :is "${test}" "vALUE" { + test_fail "modified variable assignment failed"; + } +} + +test "Modifier :length (empty)" { + set :length "test" ""; + + if not string :is "${test}" "0" { + test_fail "modified variable assignment failed"; + } +} + +test "Modifier :length (simple)" { + set :length "test" "VaLuE"; + + if not string :is "${test}" "5" { + test_fail "modified variable assignment failed"; + } +} + +test "Modifier :length (elaborate)" { + set "a" "abcdefghijklmnopqrstuvwxyz"; + set "b" "1234567890"; + set :length "test" " ${a}:${b} "; + + if not string :is "${test}" "40" { + test_fail "modified variable assignment failed"; + } +} + +test "Modifier :quotewildcard" { + set :quotewildcard "test" "^^***??**^^"; + + if not string :is "${test}" "^^\\*\\*\\*\\?\\?\\*\\*^^" { + test_fail "modified variable assignment failed"; + } +} + +test "Modifier :length :quotewildcard" { + set :length :quotewildcard "test" "^^***??**^^"; + + if string :is "${test}" "11" { + test_fail "modifiers applied with wrong precedence"; + } + + if not string :is "${test}" "18" { + test_fail "modified variable assignment failed"; + } +} + +test "RFC examples" { + set "a" "juMBlEd lETteRS"; # => "juMBlEd lETteRS" + if not string "${a}" "juMBlEd lETteRS" { + test_fail "modified assignment failed (1): ${a}"; + } + + set :length "b" "${a}"; # => "15" + if not string "${b}" "15" { + test_fail "modified assignment failed (2): ${a}"; + } + + set :lower "b" "${a}"; # => "jumbled letters" + if not string "${b}" "jumbled letters" { + test_fail "modified assignment failed (3): ${a}"; + } + + set :upperfirst "b" "${a}"; # => "JuMBlEd lETteRS" + if not string "${b}" "JuMBlEd lETteRS" { + test_fail "modified assignment failed (4): ${a}"; + } + + set :upperfirst :lower "b" "${a}"; # => "Jumbled letters" + if not string "${b}" "Jumbled letters" { + test_fail "modified assignment failed (5): ${a}"; + } + + set :quotewildcard "b" "Rock*"; # => "Rock\*" + if not string "${b}" "Rock\\*" { + test_fail "modified assignment failed (6): ${a}"; + } +} + +/* RFC mentions `characters' and not octets */ + +test "Modifier :length utf8" { + set "a" "Das ist ${unicode: 00fc}berhaupt nicht m${unicode: 00f6}glich."; + + set :length "b" "${a}"; + if not string "${b}" "32" { + test_fail "incorrect number of unicode characters reported: ${b}/32"; + } +} diff --git a/pigeonhole/tests/extensions/variables/quoting.svtest b/pigeonhole/tests/extensions/variables/quoting.svtest new file mode 100644 index 0000000..f65e4e4 --- /dev/null +++ b/pigeonhole/tests/extensions/variables/quoting.svtest @@ -0,0 +1,36 @@ +require "vnd.dovecot.testsuite"; + +require "variables"; +require "encoded-character"; + +test "Encodings - RFC examples" { + set "s" "$"; + set "foo" "bar"; + + # "${fo\o}" => ${foo} => the expansion of variable foo. + if not string :is "${fo\o}" "bar" { + test_fail "failed 'the expansion of variable foo (${s}{fo\\o})'"; + } + + # "${fo\\o}" => ${fo\o} => illegal identifier => left verbatim. + if not string :is "${fo\\o}" "${s}{fo\\o}" { + test_fail "failed 'illegal identifier => left verbatim'"; + } + + # "\${foo}" => ${foo} => the expansion of variable foo. + if not string "\${foo}" "bar" { + test_fail "failed 'the expansion of variable foo (\\${s}{foo})'"; + } + + # "\\${foo}" => \${foo} => a backslash character followed by the + # expansion of variable foo. + if not string "\\${foo}" "\\bar" { + test_fail "failed 'a backslash character followed by expansion of variable foo"; + } + + set "name" "Ethelbert"; + if not string "dear${hex:20 24 7b 4e}ame}" "dear Ethelbert" { + test_fail "failed 'dear Ethelbert' example"; + } +} + diff --git a/pigeonhole/tests/extensions/variables/regex.svtest b/pigeonhole/tests/extensions/variables/regex.svtest new file mode 100644 index 0000000..04ca00d --- /dev/null +++ b/pigeonhole/tests/extensions/variables/regex.svtest @@ -0,0 +1,35 @@ +require "vnd.dovecot.testsuite"; + +require "regex"; +require "variables"; + +# Test overwriting only on match +test "RFC - values overwrite" { + set "sentence1" "the cat jumps off the table"; + set "sentence2" "the dog barks at the cat in the alley"; + + if not string :regex "${sentence1}" "the (.*) jumps off the (.*)" { + test_fail "failed to match first sentence"; + } + + if not string :is "${1}:${2}" "cat:table" { + test_fail "invalid match values"; + } + + if string :regex "${sentence2}" "the (.*) barks at the (.*) in the store" { + test_fail "should not have matched second sentence"; + } + + if not string :is "${1}:${2}" "cat:table" { + test_fail "should have preserved match values"; + } + + if not string :regex "${sentence2}" "the (.*) barks at the (.*) in the alley" { + test_fail "failed to match the second sentence (second time)"; + } + + if not string :is "${1}:${2}" "dog:cat" { + test_fail "should have overwritten match values"; + } +} + diff --git a/pigeonhole/tests/extensions/variables/string.svtest b/pigeonhole/tests/extensions/variables/string.svtest new file mode 100644 index 0000000..d0244e6 --- /dev/null +++ b/pigeonhole/tests/extensions/variables/string.svtest @@ -0,0 +1,37 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +require "variables"; + +test "String - :count" { + if not string :count "eq" :comparator "i;ascii-numeric" ["a", "b", "c"] "3" { + test_fail "string test failed :count match"; + } +} + +test "String - :count \"\"" { + if not string :count "eq" :comparator "i;ascii-numeric" ["a", "", "c"] "2" { + test_fail "string test failed :count match"; + } +} + +test "RFC example" { + set "state" "${state} pending"; + + if not string :matches " ${state} " "* pending *" { + # the above test always succeeds + + test_fail "test should have matched: \" ${state} \""; + } +} + +test "No whitespace stripping" { + set "vara" " value "; + set "varb" "value"; + + if not string :is :comparator "i;octet" "${vara}" " ${varb} " { + test_fail "string test seems to have stripped white space"; + } +} diff --git a/pigeonhole/tests/extensions/vnd.dovecot/debug/execute.svtest b/pigeonhole/tests/extensions/vnd.dovecot/debug/execute.svtest new file mode 100644 index 0000000..6d67024 --- /dev/null +++ b/pigeonhole/tests/extensions/vnd.dovecot/debug/execute.svtest @@ -0,0 +1,6 @@ +require "vnd.dovecot.testsuite"; +require "vnd.dovecot.debug"; + +test "Basic" { + debug_log "logging basic message."; +} diff --git a/pigeonhole/tests/extensions/vnd.dovecot/environment/basic.svtest b/pigeonhole/tests/extensions/vnd.dovecot/environment/basic.svtest new file mode 100644 index 0000000..c58bbc0 --- /dev/null +++ b/pigeonhole/tests/extensions/vnd.dovecot/environment/basic.svtest @@ -0,0 +1,29 @@ +require "vnd.dovecot.testsuite"; +require "vnd.dovecot.environment"; +require "variables"; + +test "default-mailbox" { + if not environment :is "vnd.dovecot.default-mailbox" "INBOX" { + if environment :matches "vnd.dovecot.default-mailbox" "*" { set "env" "${1}"; } + + test_fail "vnd.dovecot.default-mailbox environment returned invalid value(1): `${env}'"; + } +} + +test "username" { + if not environment :contains "vnd.dovecot.username" "" { + test_fail "vnd.dovecot.username environment does not exist"; + } +} + +test_config_set "sieve_env_display_name" "Jan Jansen"; +test_config_reload :extension "vnd.dovecot.environment"; + +test "config" { + if not environment :contains "vnd.dovecot.config.display_name" "" { + test_fail "vnd.dovecot.config.display_name environment does not exist"; + } + if not environment :is "vnd.dovecot.config.display_name" "Jan Jansen" { + test_fail "vnd.dovecot.config.display_name environment has wrong value"; + } +} diff --git a/pigeonhole/tests/extensions/vnd.dovecot/environment/variables.svtest b/pigeonhole/tests/extensions/vnd.dovecot/environment/variables.svtest new file mode 100644 index 0000000..886e75e --- /dev/null +++ b/pigeonhole/tests/extensions/vnd.dovecot/environment/variables.svtest @@ -0,0 +1,18 @@ +require "vnd.dovecot.testsuite"; +require "vnd.dovecot.environment"; +require "variables"; +require "relational"; + +test "default_mailbox" { + if not string "${env.vnd.dovecot.default_mailbox}" "INBOX" { + test_fail "The env.vnd.dovecot.default_mailbox variable returned invalid value: `${env.vnd.dovecot.default_mailbox}'"; + } +} + +test "username" { + set :length "userlen" "${env.vnd.dovecot.username}"; + if not string :value "ge" "${userlen}" "1" { + test_fail "The env.vnd.dovecot.username variable is empty or does not exist"; + } +} + diff --git a/pigeonhole/tests/extensions/vnd.dovecot/report/errors.svtest b/pigeonhole/tests/extensions/vnd.dovecot/report/errors.svtest new file mode 100644 index 0000000..82ab992 --- /dev/null +++ b/pigeonhole/tests/extensions/vnd.dovecot/report/errors.svtest @@ -0,0 +1,13 @@ +require "vnd.dovecot.testsuite"; +require "comparator-i;ascii-numeric"; +require "relational"; + +test "Invalid syntax (FIXME: count only)" { + if test_script_compile "errors/syntax.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "9" { + test_fail "wrong number of errors reported"; + } +} diff --git a/pigeonhole/tests/extensions/vnd.dovecot/report/errors/syntax.sieve b/pigeonhole/tests/extensions/vnd.dovecot/report/errors/syntax.sieve new file mode 100644 index 0000000..250ad60 --- /dev/null +++ b/pigeonhole/tests/extensions/vnd.dovecot/report/errors/syntax.sieve @@ -0,0 +1,28 @@ +require "vnd.dovecot.report"; + +# 1: Too few arguments +report; + +# 2: Too few arguments +report "abuse"; + +# 3: Too few arguments +report "abuse" "Message is spam."; + +# Not an error +report "abuse" "Message is spam." "frop@example.com"; + +# 4: Bad arguments +report "abuse" "Message is spam." 1; + +# 5: Bad tag +report :frop "abuse" "Message is spam." "frop@example.com"; + +# 6: Bad sub-test +report "abuse" "Message is spam." "frop@example.com" frop; + +# 7: Bad block +report "abuse" "Message is spam." "frop@example.com" { } + +# 8: Bad feedback type +report "?????" "Message is spam." "frop@example.com"; diff --git a/pigeonhole/tests/extensions/vnd.dovecot/report/execute.svtest b/pigeonhole/tests/extensions/vnd.dovecot/report/execute.svtest new file mode 100644 index 0000000..11a8079 --- /dev/null +++ b/pigeonhole/tests/extensions/vnd.dovecot/report/execute.svtest @@ -0,0 +1,269 @@ +require "vnd.dovecot.testsuite"; +require "vnd.dovecot.report"; +require "relational"; +require "comparator-i;ascii-numeric"; +require "body"; +require "variables"; + +/* + * Simple test + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test "Simple" { + report "abuse" "This message is spam!" "abuse@example.com"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not body :raw :contains "This message is spam!" { + test_fail "report does not contain user text"; + } + + if not body :raw :contains "Klutsefluts" { + test_fail "report does not contain message body"; + } +} + +/* + * Simple - :headers_only test + */ + +test_result_reset; + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test "Simple - :headers_only" { + report :headers_only "abuse" + "This message is spam!" "abuse@example.com"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not body :raw :contains "This message is spam!" { + test_fail "report does not contain user text"; + } + + if body :raw :contains "Klutsefluts" { + test_fail "report contains message body"; + } +} + +/* + * Configuration + */ + +set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +/* default */ + +test_set "message" "${message}"; +test_set "envelope.from" "from@example.com"; +test_set "envelope.to" "to@example.com"; +test_set "envelope.orig_to" "orig_to@example.com"; + +test_result_reset; + +test "Configuration - from default" { + report "abuse" "This message is spam!" "abuse@example.com"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not address :localpart "from" "postmaster" { + test_fail "not sent from postmaster"; + } +} + +/* from sender */ + +test_set "message" "${message}"; +test_set "envelope.from" "from@example.com"; +test_set "envelope.to" "to@example.com"; +test_set "envelope.orig_to" "orig_to@example.com"; + +test_config_set "sieve_report_from" "sender"; +test_config_reload :extension "vnd.dovecot.report"; +test_result_reset; + +test "Configuration - from sender" { + report "abuse" "This message is spam!" "abuse@example.com"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not address :localpart "from" "from" { + test_fail "not sent from sender"; + } +} + +/* from recipient */ + +test_set "message" "${message}"; +test_set "envelope.from" "from@example.com"; +test_set "envelope.to" "to@example.com"; +test_set "envelope.orig_to" "orig_to@example.com"; + +test_config_set "sieve_report_from" "recipient"; +test_config_reload :extension "vnd.dovecot.report"; +test_result_reset; + +test "Configuration - from recipient" { + report "abuse" "This message is spam!" "abuse@example.com"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not address :localpart "from" "to" { + test_fail "not sent from recipient"; + } +} + +/* from original recipient */ + +test_set "message" "${message}"; +test_set "envelope.from" "from@example.com"; +test_set "envelope.to" "to@example.com"; +test_set "envelope.orig_to" "orig_to@example.com"; + +test_config_set "sieve_report_from" "orig_recipient"; +test_config_reload :extension "vnd.dovecot.report"; +test_result_reset; + +test "Configuration - from original recipient" { + report "abuse" "This message is spam!" "abuse@example.com"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not address :localpart "from" "orig_to" { + test_fail "not sent from original recipient"; + } +} + +/* from user email */ + +test_set "message" "${message}"; +test_set "envelope.from" "from@example.com"; +test_set "envelope.to" "to@example.com"; +test_set "envelope.orig_to" "orig_to@example.com"; + +test_config_set "sieve_report_from" "user_email"; +test_config_set "sieve_user_email" "user@example.com"; +test_config_reload; +test_config_reload :extension "vnd.dovecot.report"; +test_result_reset; + +test "Configuration - from user email" { + report "abuse" "This message is spam!" "abuse@example.com"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not address :localpart "from" "user" { + test_fail "not sent from user email"; + } +} + +/* explicit */ + +test_set "message" "${message}"; +test_set "envelope.from" "from@example.com"; +test_set "envelope.to" "to@example.com"; +test_set "envelope.orig_to" "orig_to@example.com"; + +test_config_set "sieve_report_from" "<frop@example.com>"; +test_config_reload :extension "vnd.dovecot.report"; +test_result_reset; + +test "Configuration - explicit" { + report "abuse" "This message is spam!" "abuse@example.com"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not address :localpart "from" "frop" { + test_fail "not sent from explicit address"; + } +} + +/* + * Reporting-User + */ + +/* sieve_user_email */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org +Subject: Frop! + +Klutsefluts. +. +; + +test_set "envelope.orig_to" "orig_to@example.com"; + +test_config_set "sieve_user_email" "newuser@example.com"; +test_config_reload; +test_result_reset; + +test "Reporting-User - sieve_user_email" { + report "abuse" "This message is spam!" "abuse@example.com"; + + if not test_result_execute { + test_fail "failed to execute notify"; + } + + test_message :smtp 0; + + if not body :raw :contains "Dovecot-Reporting-User: <newuser@example.com>" { + test_fail "Reporting-User field is wrong."; + } +}
\ No newline at end of file diff --git a/pigeonhole/tests/failures/fuzz1.svtest b/pigeonhole/tests/failures/fuzz1.svtest new file mode 100644 index 0000000..a6fe086 --- /dev/null +++ b/pigeonhole/tests/failures/fuzz1.svtest @@ -0,0 +1,33 @@ +# Used to cause the test suite to segfault + +require "vnd.dovecot.testsuite"; +require "fileinto"; +require "imap4flags"; +require "mailbox"; + + +test_set "message" text: +Subject: Test message. + +Test message. +. +; + +test "Flag changes between stores" { + fileinto :create "FolderA"; + + if not test_result_execute { + test_fail "failed to execute first result"; + } + + test_message :folder "FolderA" 0; + + test_result_reset; + + test_message :folder "Uninteiesting" 0; + + if not hasflag "$label1" { + test_fail "flags not stored for fired for third message"; + } + +} diff --git a/pigeonhole/tests/failures/fuzz2.svtest b/pigeonhole/tests/failures/fuzz2.svtest new file mode 100644 index 0000000..9fa63ea --- /dev/null +++ b/pigeonhole/tests/failures/fuzz2.svtest @@ -0,0 +1,37 @@ +require "vnd.dovecot.testsuite"; +require "fileinto"; +require "variables"; +require "mailbox"; + +set "message" text: +From:.org +To:rg +Subject: First message + +Frop +. +; + + +test "sometest" { + test_set "message" "${message}"; + + fileinto :create "Folder"; + + if not test_result_execute { + test_fail ""; + } + + test_message :folder "Folder" 0; + + if not header "subject" "First message" { + test_fail ""; + } + + test_message :folder " .Folder" 1; + + if not header "subject" "Second message" { + test_fail ""; + } + +} diff --git a/pigeonhole/tests/failures/fuzz3.svtest b/pigeonhole/tests/failures/fuzz3.svtest new file mode 100644 index 0000000..c1c22dc --- /dev/null +++ b/pigeonhole/tests/failures/fuzz3.svtest @@ -0,0 +1,12 @@ +require "vnd.dovecot.testsuite"; +require "fileinto"; +require "mailbox"; + +test"" { + fileinto :create "Folder"; + + if test_result_execute { + } + + test_message :folder "Folder" 2; +} diff --git a/pigeonhole/tests/failures/mailbox-bad-utf8.svtest b/pigeonhole/tests/failures/mailbox-bad-utf8.svtest new file mode 100644 index 0000000..ad104e5 --- /dev/null +++ b/pigeonhole/tests/failures/mailbox-bad-utf8.svtest @@ -0,0 +1,6 @@ +require "vnd.dovecot.testsuite"; +require "encoded-character"; + +test "Mailbox parameter with bad UTF-8" { + test_message :folder "I${hex:9b}BOX" 0; +} diff --git a/pigeonhole/tests/lexer.svtest b/pigeonhole/tests/lexer.svtest new file mode 100644 index 0000000..491309d --- /dev/null +++ b/pigeonhole/tests/lexer.svtest @@ -0,0 +1,39 @@ +require "vnd.dovecot.testsuite"; +require "variables"; + +/* Test conformance to RFC 5228 - 2.4.2. Strings */ + +set "text" text: # Comment +Line 1 +.Line 2 +..Line 3 +.Line 4 +Line 5 +. +; + +set "quoted" +"Line 1 +.Line 2 +.Line 3 +.Line 4 +Line 5 +"; + +test "String Literal" { + if not string :is "${text}" "${quoted}" { + test_fail "lexer messed-up dot stuffing"; + } + + if string :is "${text}" "" { + test_fail "variable substitution failed"; + } +} + +test "Unknown Escapes" { + if not string :is "\a\a\a\a\a" "aaaaa" { + test_fail "unknown quoted string escape sequences are handled inappropriately"; + } +} + + diff --git a/pigeonhole/tests/match-types/contains.svtest b/pigeonhole/tests/match-types/contains.svtest new file mode 100644 index 0000000..710afca --- /dev/null +++ b/pigeonhole/tests/match-types/contains.svtest @@ -0,0 +1,81 @@ +require "vnd.dovecot.testsuite"; + +test_set "message" text: +From: stephan@example.org +Cc: frop@example.com +To: test@dovecot.example.net +X-Bullshit: f fr fro frop frob frobn frobnitzn +Subject: Test Message +Comment: + +Test! +. +; + +# Match tests + +test "Match empty" { + if not header :contains "x-bullshit" "" { + test_fail "contains tests fails to match \"\" against non-empty string"; + } + + if not header :contains "comment" "" { + test_fail "contains tests fails to match \"\" against empty string"; + } +} + +test "Match full" { + if not address :contains "from" "stephan@example.org" { + test_fail "should have matched"; + } +} + +test "Match begin" { + if not address :contains "from" "stephan" { + test_fail "should have matched"; + } +} + +test "Match end" { + if not address :contains "from" "example.org" { + test_fail "should have matched"; + } +} + +test "Match middle" { + if not address :contains "from" "@" { + test_fail "should have matched"; + } +} + +test "Match similar beginnings" { + if not header :contains "x-bullshit" "frobnitzn" { + test_fail "should have matched"; + } +} + +test "Match case-insensitive" { + if not address :contains :comparator "i;ascii-casemap" "from" "EXAMPLE" { + test_fail "match fails to apply correct comparator"; + } + + if not address :contains "from" "EXAMPLE" { + test_fail "default comparator is wrong"; + } +} + +# Non-match tests + +test "No match full (typo)" { + if address :contains "to" "frob@example.com" { + test_fail "should not have matched"; + } +} + +test "No match end (typo)" { + if header :contains "x-bullshit" "frobnitzm" { + test_fail "should not have matched"; + } +} + + diff --git a/pigeonhole/tests/match-types/is.svtest b/pigeonhole/tests/match-types/is.svtest new file mode 100644 index 0000000..c715db8 --- /dev/null +++ b/pigeonhole/tests/match-types/is.svtest @@ -0,0 +1,22 @@ +require "vnd.dovecot.testsuite"; + +test_set "message" text: +From: Stephan Bosch <stephan@example.org> +To: nico@frop.example.org +Subject: Test message +Comment: + +Test! + +. +; + +test "Empty key" { + if header :is "from" "" { + test_fail "erroneously matched empty key against non-empty string"; + } + + if not header :is "comment" "" { + test_fail "failed to match empty string"; + } +} diff --git a/pigeonhole/tests/match-types/matches.svtest b/pigeonhole/tests/match-types/matches.svtest new file mode 100644 index 0000000..bcc188d --- /dev/null +++ b/pigeonhole/tests/match-types/matches.svtest @@ -0,0 +1,241 @@ +require "vnd.dovecot.testsuite"; + +test_set "message" text: +From: stephan+sieve@friep.example.com +To: sirius@example.org +To: nico@frop.example.org +Cc: me@example.com +Cc: timo@dovecot.example.com +X-Hufter: TRUE +Subject: make your money very fast!!! +X-Spam-Score: ********** +X-Bullshit: 33333???a +Message-ID: <90a02fe01fc25e131d0e9c4c45975894@example.com> +Comment: +X-Subject: Log for successful build of Dovecot. + +Het werkt! +. +; + +/* + * General conformance testing + */ + +test "Empty string" { + if not header :matches "comment" "" { + test_fail "failed to match \"\" against \"\""; + } + + if not header :matches "comment" "*" { + test_fail "failed to match \"\" against \"*\""; + } + + if header :matches "comment" "?" { + test_fail "inappropriately matched \"\" against \"?\""; + } +} + +test "Multiple '*'" { + if not address :matches "from" "*@fri*p*examp*.com" { + test_fail "should have matched"; + } + + if address :matches "from" "*@f*pex*mple.com" { + test_fail "should not have matched"; + } +} + +test "End '*'" { + if not address :matches "from" "stephan+sieve@friep.*" { + test_fail "should have matched"; + } + + if address :matches "from" "stepan+sieve@friep.*" { + test_fail "should not have matched"; + } +} + +test "Begin '*'" { + if not address :matches "from" "*+sieve@friep.example.com" { + test_fail "should have matched"; + } + + if address :matches "from" "*+sieve@friep.example.om" { + test_fail "should not have matched"; + } +} + +test "Middle '?'" { + if not address :matches "from" "stephan+sieve?friep.example.com" { + test_fail "should have matched"; + } + + if address :matches "from" "stephan+sieve?fiep.example.com" { + test_fail "should not have matched"; + } +} + +test "Begin '?'" { + if not address :matches "from" "?tephan+sieve@friep.example.com" { + test_fail "should have matched"; + } + + if address :matches "from" "?tephan+sievefriep.example.com" { + test_fail "should not have matched"; + } +} + +test "End '?'" { + if not address :matches "from" "stephan+sieve@friep.example.co?" { + test_fail "should have matched"; + } + + if address :matches "from" "sephan+sieve@friep.example.co?" { + test_fail "should not have matched"; + } +} + +test "Multiple '?'" { + if not address :matches "from" "?t?phan?sieve?fri?p.exampl?.co?" { + test_fail "should have matched"; + } + + if address :matches "from" "?t?phan?sieve?fiep.exam?le.co?" { + test_fail "should not have matched"; + } +} + +test "Escaped '?'" { + if not header :matches "x-bullshit" "33333\\?\\?\\??" { + test_fail "should have matched"; + } + + if header :matches "x-bullshit" "33333\\?\\?\\?" { + test_fail "should not have matched"; + } +} + +test "Escaped '?' following '*'" { + if not header :matches "x-bullshit" "33333*\\?\\??" { + test_fail "should have matched"; + } + +} + +test "Escaped '?' directly following initial '*'" { + if not header :matches "X-Bullshit" "*\\?\\?\\?a" { + test_fail "should have matched"; + } +} + +test "Escaped '?' following initial '*'" { + if not header :matches "x-bullshit" "*3333\\?\\?\\?a" { + test_fail "should have matched"; + } +} + +test "Escaped '*' with active '*' at the end" { + if not header :matches "x-spam-score" "\\*\\*\\*\\*\\**" { + test_fail "should have matched"; + } +} + +test "All escaped '*'" { + if not header :matches "x-spam-score" "\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*" { + test_fail "should have matched"; + } + + if header :matches "x-spam-score" "\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*" { + test_fail "should not have matched"; + } +} + +test "Middle not escaped '*'" { + if not header :matches "x-spam-score" "\\*\\*\\***\\*\\*" { + test_fail "should have matched"; + } +} + +test "Escaped '*' alternating with '?'" { + if not header :matches "x-spam-score" "\\*?\\*?\\*?\\*?\\*?" { + test_fail "should have matched"; + } + + if header :matches "x-spam-score" "\\*?\\*?\\*?\\*?\\*??" { + test_fail "should not have matched"; + } +} + +test "All escaped" { + if header :matches "x-bullshit" "\\*3333\\?\\?\\?a" { + test_fail "should not have matched"; + } + + + if header :matches "x-bullshit" "33333\\?\\?\\?aa" { + test_fail "should not have matched"; + } + + if header :matches "x-bullshit" "\\f3333\\?\\?\\?a" { + test_fail "should not have matched"; + } +} + +test "Put '*' directly before '?'" { + if header :matches "x-subject" "Log for *??????????? build of *" { + test_fail "should not have matched"; + } + + if not header :matches "x-subject" "Log for *?????????? build of *" { + test_fail "should have matched"; + } + + if not header :matches "x-subject" "Log for *? build of *" { + test_fail "should have matched"; + } +} + +test "Put '?' directly before '*'" { + if header :matches "x-subject" "Log for ???????????* build of *" { + test_fail "should not have matched"; + } + + if not header :matches "x-subject" "Log for ??????????* build of *" { + test_fail "should have matched"; + } + + if not header :matches "x-subject" "Log for ?* build of *" { + test_fail "should have matched"; + } +} + +test "Fixed beginning" { + if not header :matches "subject" "make your *" { + test_fail "should have matched"; + } +} + +test "Fixed end" { + if not header :matches "subject" "* very fast!!!" { + test_fail "should have matched"; + } + + if header :matches "subject" "* very fast!!" { + test_fail "should not have matched"; + } +} + +test "Fixed string" { + if not address :matches "to" "sirius@example.org" { + test_fail "should have matched"; + } + + if address :matches "to" "example.org" { + test_fail "should not have matched"; + } + + if address :matches "to" "sirius" { + test_fail "should not have matched"; + } +} diff --git a/pigeonhole/tests/multiscript/basic.svtest b/pigeonhole/tests/multiscript/basic.svtest new file mode 100644 index 0000000..ce9bb66 --- /dev/null +++ b/pigeonhole/tests/multiscript/basic.svtest @@ -0,0 +1,91 @@ +require "vnd.dovecot.testsuite"; + +test_set "message" text: +From: stephan@example.org +Message-ID: <frop33333333333333333@frutsens.example.nl> +To: nico@frop.example.org +Subject: Frop. + +Friep. +. +; + +test "Append" { + if not allof ( + test_script_compile "fileinto-inbox.sieve", + test_script_run ){ + test_fail "failed to compile and run first script"; + } + + if not allof ( + test_script_compile "vacation.sieve", + test_script_run :append_result ) { + test_fail "failed to compile and run second script"; + } + + if not allof ( + test_script_compile "notify.sieve", + test_script_run :append_result ) { + test_fail "failed to compile and run third script"; + } + + if not test_result_action :index 1 "store" { + test_fail "first action is not 'store'"; + } + + if not test_result_action :index 2 "vacation" { + test_fail "second action is not 'vacation'"; + } + + if not test_result_action :index 3 "notify" { + test_fail "third action is not 'notify'"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } +} + +test "Sequential Execute" { + if not allof ( + test_script_compile "fileinto-inbox.sieve", + test_script_run ) { + test_fail "failed to compile and run first script"; + } + + if not test_result_execute { + test_fail "result execute failed after first script"; + } + + if not allof ( + test_script_compile "vacation.sieve", + test_script_run :append_result ) { + test_fail "failed to compile and run second script"; + } + + if not test_result_execute { + test_fail "result execute failed after second script"; + } + + if not allof ( + test_script_compile "notify.sieve", + test_script_run :append_result ) { + test_fail "failed to compile and run third script"; + } + + if not test_result_execute { + test_fail "result execute failed after third script"; + } + + if not test_result_action :index 1 "store" { + test_fail "first action is not 'store'"; + } + + if not test_result_action :index 2 "vacation" { + test_fail "second action is not 'vacation'"; + } + + if not test_result_action :index 3 "notify" { + test_fail "third action is not 'notify'"; + } +} diff --git a/pigeonhole/tests/multiscript/conflicts.svtest b/pigeonhole/tests/multiscript/conflicts.svtest new file mode 100644 index 0000000..a2b8fab --- /dev/null +++ b/pigeonhole/tests/multiscript/conflicts.svtest @@ -0,0 +1,100 @@ +require "vnd.dovecot.testsuite"; + +test_set "message" text: +From: stephan@example.org +Message-ID: <frop33333333333333333@nl.example.com> +To: nico@frop.example.org +Subject: Frop. + +Friep. +. +; + +test "Graceful Conflicts" { + if not allof ( + test_script_compile "fileinto-inbox.sieve", + test_script_run ){ + test_fail "failed to compile and run first script"; + } + + if not test_result_execute { + test_fail "result execute failed after first script"; + } + + if not allof ( + test_script_compile "reject-1.sieve", + test_script_run :append_result ) { + test_fail "failed to compile and run second script"; + } + + if not test_result_execute { + test_fail "result execute failed after second script"; + } + + if not allof ( + test_script_compile "reject-2.sieve", + test_script_run :append_result ) { + test_fail "failed to compile and run third script"; + } + + if not test_result_execute { + test_fail "result execute failed after third script"; + } + + if not test_result_action :index 1 "store" { + test_result_print; + test_fail "first action is not 'store'"; + } + + if not test_result_action :index 2 "reject" { + test_result_print; + test_fail "first reject action not retained"; + } + + if test_result_action :index 3 "reject" { + test_result_print; + test_fail "second reject action not discarded"; + } + +} + +test "Duplicates" { + if not allof ( + test_script_compile "fileinto-inbox.sieve", + test_script_run ){ + test_fail "failed to compile and run first script"; + } + + if not test_result_execute { + test_fail "result execute failed after first script"; + } + + if not allof ( + test_script_compile "fileinto-inbox.sieve", + test_script_run :append_result ) { + test_fail "failed to compile and run second script"; + } + + if not test_result_execute { + test_fail "result execute failed after second script"; + } + + if not allof ( + test_script_compile "keep.sieve", + test_script_run :append_result ) { + test_fail "failed to compile and run third script"; + } + + if not test_result_execute { + test_fail "result execute failed after third script"; + } + + if not test_result_action :index 1 "keep" { + test_fail "first action is not 'keep'"; + } + + if test_result_action :index 2 "store" { + test_fail "fileinto action not discarded"; + } +} + diff --git a/pigeonhole/tests/multiscript/fileinto-frop.sieve b/pigeonhole/tests/multiscript/fileinto-frop.sieve new file mode 100644 index 0000000..9aafb95 --- /dev/null +++ b/pigeonhole/tests/multiscript/fileinto-frop.sieve @@ -0,0 +1,3 @@ +require "fileinto"; + +fileinto "frop"; diff --git a/pigeonhole/tests/multiscript/fileinto-inbox.sieve b/pigeonhole/tests/multiscript/fileinto-inbox.sieve new file mode 100644 index 0000000..b5da850 --- /dev/null +++ b/pigeonhole/tests/multiscript/fileinto-inbox.sieve @@ -0,0 +1,4 @@ +require "fileinto"; + +fileinto "INBOX"; + diff --git a/pigeonhole/tests/multiscript/keep.sieve b/pigeonhole/tests/multiscript/keep.sieve new file mode 100644 index 0000000..6203a21 --- /dev/null +++ b/pigeonhole/tests/multiscript/keep.sieve @@ -0,0 +1 @@ +keep; diff --git a/pigeonhole/tests/multiscript/notify.sieve b/pigeonhole/tests/multiscript/notify.sieve new file mode 100644 index 0000000..af47ad9 --- /dev/null +++ b/pigeonhole/tests/multiscript/notify.sieve @@ -0,0 +1,3 @@ +require "enotify"; + +notify "mailto:stephan@example.org"; diff --git a/pigeonhole/tests/multiscript/reject-1.sieve b/pigeonhole/tests/multiscript/reject-1.sieve new file mode 100644 index 0000000..06744f6 --- /dev/null +++ b/pigeonhole/tests/multiscript/reject-1.sieve @@ -0,0 +1,3 @@ +require "reject"; + +reject "Message is not wanted."; diff --git a/pigeonhole/tests/multiscript/reject-2.sieve b/pigeonhole/tests/multiscript/reject-2.sieve new file mode 100644 index 0000000..96b7564 --- /dev/null +++ b/pigeonhole/tests/multiscript/reject-2.sieve @@ -0,0 +1,3 @@ +require "reject"; + +reject "Will not accept this nonsense."; diff --git a/pigeonhole/tests/multiscript/vacation.sieve b/pigeonhole/tests/multiscript/vacation.sieve new file mode 100644 index 0000000..d735da5 --- /dev/null +++ b/pigeonhole/tests/multiscript/vacation.sieve @@ -0,0 +1,3 @@ +require "vacation"; + +vacation "I am not home"; diff --git a/pigeonhole/tests/plugins/extprograms/bin/addheader b/pigeonhole/tests/plugins/extprograms/bin/addheader new file mode 100755 index 0000000..8f9805a --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/bin/addheader @@ -0,0 +1,6 @@ +#!/bin/sh + +echo "$1: $2" +cat + +exit 0 diff --git a/pigeonhole/tests/plugins/extprograms/bin/big b/pigeonhole/tests/plugins/extprograms/bin/big new file mode 100755 index 0000000..ce1df51 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/bin/big @@ -0,0 +1,8 @@ +#!/bin/sh + +N="0123456701234567012345670123456701234567012345670123456701234567" +N="$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N" +echo -n "$N$N" + +exit 0 + diff --git a/pigeonhole/tests/plugins/extprograms/bin/cat b/pigeonhole/tests/plugins/extprograms/bin/cat new file mode 100755 index 0000000..02b9858 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/bin/cat @@ -0,0 +1,3 @@ +#!/bin/sh + +cat diff --git a/pigeonhole/tests/plugins/extprograms/bin/cat-stdin b/pigeonhole/tests/plugins/extprograms/bin/cat-stdin new file mode 100755 index 0000000..781d70b --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/bin/cat-stdin @@ -0,0 +1,3 @@ +#!/bin/sh + +cat /dev/stdin diff --git a/pigeonhole/tests/plugins/extprograms/bin/crlf b/pigeonhole/tests/plugins/extprograms/bin/crlf new file mode 100755 index 0000000..a0028cf --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/bin/crlf @@ -0,0 +1,3 @@ +#!/bin/sh + +tr -s '\r' '#' diff --git a/pigeonhole/tests/plugins/extprograms/bin/env b/pigeonhole/tests/plugins/extprograms/bin/env new file mode 100755 index 0000000..a7b81ac --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/bin/env @@ -0,0 +1,3 @@ +#!/bin/sh + +eval echo -n "\${$1}" diff --git a/pigeonhole/tests/plugins/extprograms/bin/frame b/pigeonhole/tests/plugins/extprograms/bin/frame new file mode 100755 index 0000000..225005e --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/bin/frame @@ -0,0 +1,7 @@ +#!/bin/sh + +echo -n "FRAMED $1{ " +cat +echo -n " }" + +exit 0 diff --git a/pigeonhole/tests/plugins/extprograms/bin/modify b/pigeonhole/tests/plugins/extprograms/bin/modify new file mode 100755 index 0000000..ce87014 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/bin/modify @@ -0,0 +1,8 @@ +#!/bin/sh + +echo "X-Frop: Extra header" +cat +echo +echo "Extra body content!" + +exit 0 diff --git a/pigeonhole/tests/plugins/extprograms/bin/program b/pigeonhole/tests/plugins/extprograms/bin/program new file mode 100755 index 0000000..4b5edbf --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/bin/program @@ -0,0 +1,5 @@ +#!/bin/sh + +cat > /dev/null + +exit 0 diff --git a/pigeonhole/tests/plugins/extprograms/bin/replace b/pigeonhole/tests/plugins/extprograms/bin/replace new file mode 100755 index 0000000..b010f06 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/bin/replace @@ -0,0 +1,12 @@ +#!/bin/sh + +cat > /dev/null + +echo "From: hatseflat@example.com" +echo "To: frutsel@example.org" +echo "Subject: replacement message" +echo +echo "Replaced!" + + +exit 0 diff --git a/pigeonhole/tests/plugins/extprograms/bin/sleep10 b/pigeonhole/tests/plugins/extprograms/bin/sleep10 new file mode 100755 index 0000000..8c1b96d --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/bin/sleep10 @@ -0,0 +1,3 @@ +#!/bin/sh + +sleep 10 diff --git a/pigeonhole/tests/plugins/extprograms/bin/sleep2 b/pigeonhole/tests/plugins/extprograms/bin/sleep2 new file mode 100755 index 0000000..a814acd --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/bin/sleep2 @@ -0,0 +1,3 @@ +#!/bin/sh + +sleep 2 diff --git a/pigeonhole/tests/plugins/extprograms/bin/spamc b/pigeonhole/tests/plugins/extprograms/bin/spamc new file mode 100755 index 0000000..a3232f4 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/bin/spamc @@ -0,0 +1,6 @@ +#!/bin/sh + +echo 'X-Spam-Status: Yes, score=66.5/5.0 tests=CONTAINS_LARGE_ROOSTER' +cat + +exit 0 diff --git a/pigeonhole/tests/plugins/extprograms/bin/stderr b/pigeonhole/tests/plugins/extprograms/bin/stderr new file mode 100755 index 0000000..75b94b0 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/bin/stderr @@ -0,0 +1,20 @@ +#!/bin/sh + +echo "========================================" 1>&2 +echo "Test shell script successfully executed!" 1>&2 +echo 1>&2 +echo "Arguments: $1 $2" 1>&2 +echo 1>&2 +echo "Environment:" 1>&2 +env 1>&2 +echo 1>&2 +echo "Message:" 1>&2 +cat 1>&2 +echo "========================================" 1>&2 +echo 1>&2 + +echo "Subject: frop!" +echo "From: stephan@example.org" +echo "To: tss@example.com" +echo +echo "Frop!" diff --git a/pigeonhole/tests/plugins/extprograms/errors.svtest b/pigeonhole/tests/plugins/extprograms/errors.svtest new file mode 100644 index 0000000..148f4da --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/errors.svtest @@ -0,0 +1,32 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +/* + * Invalid program names + */ + +test "Invalid Program Names" { + if test_script_compile "errors/programname.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "8" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Invalid arguments + */ + +test "Invalid Arguments" { + if test_script_compile "errors/arguments.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "2" { + test_fail "wrong number of errors reported"; + } +} diff --git a/pigeonhole/tests/plugins/extprograms/errors/arguments.sieve b/pigeonhole/tests/plugins/extprograms/errors/arguments.sieve new file mode 100644 index 0000000..04f0aa0 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/errors/arguments.sieve @@ -0,0 +1,5 @@ +require "vnd.dovecot.pipe"; + +pipe :args "aaaa + aaaa" "frop"; + diff --git a/pigeonhole/tests/plugins/extprograms/errors/programname.sieve b/pigeonhole/tests/plugins/extprograms/errors/programname.sieve new file mode 100644 index 0000000..1d2d19c --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/errors/programname.sieve @@ -0,0 +1,25 @@ +require "variables"; +require "encoded-character"; +require "vnd.dovecot.pipe"; + +# Slash +pipe "../frop"; + +# More slashes +pipe "../../james/sieve/vacation"; + +# 0000-001F; [CONTROL CHARACTERS] +pipe "idiotic${unicode: 001a}"; + +# 007F; DELETE +pipe "idiotic${unicode: 007f}"; + +# 0080-009F; [CONTROL CHARACTERS] +pipe "idiotic${unicode: 0085}"; + +# 2028; LINE SEPARATOR +pipe "idiotic${unicode: 2028}"; + +# 2029; PARAGRAPH SEPARATOR +pipe "idiotic${unicode: 2029}"; + diff --git a/pigeonhole/tests/plugins/extprograms/execute/command.svtest b/pigeonhole/tests/plugins/extprograms/execute/command.svtest new file mode 100644 index 0000000..92c1fd1 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/execute/command.svtest @@ -0,0 +1,27 @@ +require "vnd.dovecot.testsuite"; +require "vnd.dovecot.execute"; +require "variables"; + +test_config_set "sieve_execute_bin_dir" "${tst.path}/../bin"; +test_config_reload :extension "vnd.dovecot.execute"; + +test "Basic" { + execute "program"; +} + +test "Input message" { + execute :pipe "program"; +} + +test "Input string" { + execute :input "DATA" "program"; +} + +test "Input variable" { + set "DATA" "DATA"; + execute :input "${DATA}" "program"; +} + +test "Output variable" { + execute :output "DATA" "program"; +} diff --git a/pigeonhole/tests/plugins/extprograms/execute/errors.svtest b/pigeonhole/tests/plugins/extprograms/execute/errors.svtest new file mode 100644 index 0000000..3dd2d5f --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/execute/errors.svtest @@ -0,0 +1,53 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +test_config_set "sieve_execute_bin_dir" "${tst.path}/../bin"; +test_config_reload :extension "vnd.dovecot.execute"; + +/* + * Command syntax + */ + +test "Command syntax" { + if test_script_compile "errors/syntax.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "13" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Variables + */ + +test "Variables" { + if test_script_compile "errors/variables.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "2" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Unknown program + */ + +test "Unknown program" { + if not test_script_compile "errors/unknown-program.sieve" { + test_fail "compile should have succeeded"; + } + + if test_script_run { + test_fail "execution should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "1" { + test_fail "wrong number of errors reported"; + } +} diff --git a/pigeonhole/tests/plugins/extprograms/execute/errors/syntax.sieve b/pigeonhole/tests/plugins/extprograms/execute/errors/syntax.sieve new file mode 100644 index 0000000..1f4646a --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/execute/errors/syntax.sieve @@ -0,0 +1,38 @@ +require "vnd.dovecot.execute"; + +# 1: error: no arguments +execute; + +# 2: error: numeric argument +execute 1; + +# 3: error: tag argument +execute :frop; + +# 4: error: numeric second argument +execute "sdfd" 1; + +# 5: error: stringlist first argument +execute ["sdfd","werwe"] "sdfs"; + +# 6: error: too many arguments +execute "sdfs" "sdfd" "werwe"; + +# 7: error: inappropriate :copy argument +execute :copy "234234" ["324234", "23423"]; + +# 8: error: invalid :input argument; missing parameter +execute :input "frop"; + +# 9: error: invalid :input argument; invalid parameter +execute :input 1 "frop"; + +# 10: error: invalid :input argument; invalid parameter +execute :input ["23423","21342"] "frop"; + +# 11: error: invalid :input argument; invalid parameter +execute :input :friep "frop"; + +# 12: error: :output not allowed without variables extension +execute :output "${frop}" "frop"; + diff --git a/pigeonhole/tests/plugins/extprograms/execute/errors/unknown-program.sieve b/pigeonhole/tests/plugins/extprograms/execute/errors/unknown-program.sieve new file mode 100644 index 0000000..3a79bb6 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/execute/errors/unknown-program.sieve @@ -0,0 +1,3 @@ +require "vnd.dovecot.execute"; + +execute "unknown"; diff --git a/pigeonhole/tests/plugins/extprograms/execute/errors/variables.sieve b/pigeonhole/tests/plugins/extprograms/execute/errors/variables.sieve new file mode 100644 index 0000000..3d0b3e7 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/execute/errors/variables.sieve @@ -0,0 +1,7 @@ +require "vnd.dovecot.execute"; +require "variables"; + +# 1: invalid variable name +execute :output "wqwe-aeqwe" "frop"; + + diff --git a/pigeonhole/tests/plugins/extprograms/execute/execute.svtest b/pigeonhole/tests/plugins/extprograms/execute/execute.svtest new file mode 100644 index 0000000..f16af11 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/execute/execute.svtest @@ -0,0 +1,177 @@ +require "vnd.dovecot.testsuite"; +require "vnd.dovecot.execute"; +require "vnd.dovecot.debug"; +require "variables"; +require "relational"; +require "environment"; +require "encoded-character"; + +test_set "message" text: +From: stephan@example.com +To: pipe@example.net +Subject: Frop! + +Frop! +. +; + +test_config_set "sieve_execute_bin_dir" "${tst.path}/../bin"; +test_config_reload :extension "vnd.dovecot.execute"; +test_result_reset; + +test "Execute - bare" { + execute "program"; +} + +test_result_reset; +test "Execute - i/-" { + execute :input "FROP" "frame"; +} + +test_result_reset; +test "Execute - -/o" { + execute :output "out" "frame"; + + if not string "${out}" "FRAMED { }" { + test_fail "wrong string returned: ${out}"; + } +} + +test_result_reset; +test "Execute - i/o" { + execute :input "FROP" :output "out" "frame"; + + if not string "${out}" "FRAMED { FROP }" { + test_fail "wrong string returned: ${out}"; + } +} + +test_result_reset; +test "Execute - i/o and arguments" { + execute :input "FROP" :output "out" "frame" ["FRIEP "]; + + if not string "${out}" "FRAMED FRIEP { FROP }" { + test_fail "wrong string returned: ${out}"; + } +} + +test_result_reset; +test "Execute - pipe" { + execute :pipe :output "msg" "cat"; + + if not string :contains "${msg}" "Subject: Frop!" { + test_fail "wrong string returned: ${out}"; + } +} + +test_result_reset; +test "Execute - pipe /dev/stdin" { + execute :pipe :output "msg" "cat-stdin"; + + if not string :contains "${msg}" "Subject: Frop!" { + test_fail "wrong string returned: ${out}"; + } +} + +test_result_reset; +test "Execute - env" { + test_set "envelope.from" "stephan@sub.example.com"; + test_set "envelope.to" "stephan@sub.example.net"; + test_set "envelope.orig_to" "all@sub.example.net"; + + execute :output "out" "env" "SENDER"; + if not string :is "${out}" "stephan@sub.example.com" { + test_fail "wrong SENDER env returned: '${out}'"; + } + + execute :output "out" "env" "RECIPIENT"; + if not string :is "${out}" "stephan@sub.example.net" { + test_fail "wrong RECIPIENT env returned: '${out}'"; + } + + execute :output "out" "env" "ORIG_RECIPIENT"; + if not string :is "${out}" "all@sub.example.net" { + test_fail "wrong ORIG_RECIPIENT env returned: '${out}'"; + } + + execute :output "out" "env" "HOST"; + if not environment :is "host" "${out}" { + test_fail "wrong HOST env returned: '${out}'"; + } + + execute :output "out" "env" "HOME"; + if string :count "eq" "${out}" "0" { + test_fail "empty HOME env returned"; + } + + execute :output "out" "env" "USER"; + if string :count "eq" "${out}" "0" { + test_fail "empty USER env returned"; + } +} + +test_result_reset; +test "Execute - used as test" { + if execute :pipe :output "msg" "dog" { + test_fail "execute action indicated success with invalid program"; + } + + if not execute :pipe :output "msg" "cat" { + test_fail "execute action indicated failure with valid program"; + } + + if not string :contains "${msg}" "Subject: Frop!" { + test_fail "wrong string returned: ${out}"; + } +} + +test_config_set "sieve_execute_input_eol" "crlf"; +test_config_reload :extension "vnd.dovecot.execute"; +test_result_reset; +set "out" ""; + +test "Execute - CRLF" { + execute + :input "FROP${hex:0A}FRIEP${hex:0a}" + :output "out" + "crlf"; + + if not string "${out}" "FROP#${hex:0A}FRIEP#${hex:0a}" { + test_fail "wrong string returned: '${out}'"; + } +} + +test_config_set "sieve_execute_input_eol" "lf"; +test_config_reload :extension "vnd.dovecot.execute"; +test_result_reset; +set "out" ""; + +test "Execute - LF" { + execute + :input "FROP${hex:0D 0A}FRIEP${hex:0d 0a}" + :output "out" + "crlf"; + + if not string "${out}" "FROP${hex:0A}FRIEP${hex:0a}" { + test_fail "wrong string returned: '${out}'"; + } +} + +set "D" "0123456701234567012345670123456701234567012345670123456701234567"; +set "D" "${D}${D}${D}${D}${D}${D}${D}${D}${D}${D}${D}${D}${D}${D}${D}${D}"; +set "data" "${D}${D}"; + +test_config_set "sieve_execute_input_eol" "crlf"; +test_config_reload :extension "vnd.dovecot.execute"; +test_result_reset; +set "out" ""; + +test "Execute - big" { + execute + :output "out" + "big"; + + if not string "${out}" "${data}" { + test_fail "wrong string returned: '${out}'"; + } +} diff --git a/pigeonhole/tests/plugins/extprograms/filter/command.svtest b/pigeonhole/tests/plugins/extprograms/filter/command.svtest new file mode 100644 index 0000000..50f949a --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/filter/command.svtest @@ -0,0 +1,10 @@ +require "vnd.dovecot.testsuite"; +require "vnd.dovecot.filter"; +require "variables"; + +test_config_set "sieve_filter_bin_dir" "${tst.path}/../bin"; +test_config_reload :extension "vnd.dovecot.filter"; + +test "Basic" { + filter "program"; +} diff --git a/pigeonhole/tests/plugins/extprograms/filter/errors.svtest b/pigeonhole/tests/plugins/extprograms/filter/errors.svtest new file mode 100644 index 0000000..1d04ba1 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/filter/errors.svtest @@ -0,0 +1,39 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +/* + * Command syntax + */ + +test_config_set "sieve_filter_bin_dir" "${tst.path}/../bin"; +test_config_reload :extension "vnd.dovecot.filter"; + +test "Command syntax" { + if test_script_compile "errors/syntax.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "8" { + test_fail "wrong number of errors reported"; + } +} + +/* + * Unknown program + */ + +test "Unknown program" { + if not test_script_compile "errors/unknown-program.sieve" { + test_fail "compile should have succeeded"; + } + + if test_script_run { + test_fail "execution should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "1" { + test_fail "wrong number of errors reported"; + } +} diff --git a/pigeonhole/tests/plugins/extprograms/filter/errors/syntax.sieve b/pigeonhole/tests/plugins/extprograms/filter/errors/syntax.sieve new file mode 100644 index 0000000..00a3a23 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/filter/errors/syntax.sieve @@ -0,0 +1,22 @@ +require "vnd.dovecot.filter"; + +# 1: error: no arguments +filter; + +# 2: error: numeric argument +filter 1; + +# 3: error: tag argument +filter :frop; + +# 4: error: numeric second argument +filter "sdfd" 1; + +# 5: error: stringlist first argument +filter ["sdfd","werwe"] "sdfs"; + +# 6: error: too many arguments +filter "sdfd" "werwe" "sdfs"; + +# 7: error: inappropriate :copy argument +filter :try :copy "234234" ["324234", "23423"]; diff --git a/pigeonhole/tests/plugins/extprograms/filter/errors/unknown-program.sieve b/pigeonhole/tests/plugins/extprograms/filter/errors/unknown-program.sieve new file mode 100644 index 0000000..7e530ee --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/filter/errors/unknown-program.sieve @@ -0,0 +1,3 @@ +require "vnd.dovecot.filter"; + +filter "unknown"; diff --git a/pigeonhole/tests/plugins/extprograms/filter/execute.svtest b/pigeonhole/tests/plugins/extprograms/filter/execute.svtest new file mode 100644 index 0000000..15fab69 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/filter/execute.svtest @@ -0,0 +1,213 @@ +require "vnd.dovecot.testsuite"; +require "vnd.dovecot.filter"; +require "vnd.dovecot.debug"; +require "variables"; +require "editheader"; +require "spamtest"; +require "body"; +require "fileinto"; +require "mailbox"; + +test_set "message" text: +From: stephan@example.com +To: pipe@example.net +Subject: Frop! + +Frop! +. +; + +test_config_set "sieve_filter_bin_dir" "${tst.path}/../bin"; +test_config_reload :extension "vnd.dovecot.filter"; +test_result_reset; + +test_result_reset; +test "Replace" { + if header :contains "subject" "replacement" { + test_fail "message already replaced"; + } + + filter "replace"; + + if not header :contains "subject" "replacement" { + test_fail "message not replaced"; + } +} + +test_result_reset; +test "Used as test" { + if filter "nonsense" { + test_fail "filter action indicated success with invalid program"; + } + + if not filter "replace" { + test_fail "filter action indicated failure with valid program"; + } + + if not header :contains "subject" "replacement" { + test_fail "message not replaced; filter not actually executed"; + } +} + +test_result_reset; +test "Modify" { + if anyof ( + body :contains "extra", + exists "x-frop") { + test_fail "message already modified"; + } + + if not header "subject" "Frop!" { + test_fail "message is wrong"; + } + + filter "modify"; + + if not header "subject" "Frop!" { + test_fail "message replaced erroneously"; + } + + if not header :contains "x-frop" "extra" { + test_fail "message header not modified"; + } + + if not body :contains "Extra" { + test_fail "message body not modified"; + } +} + +test_result_reset; +test "Editheader" { + if anyof ( exists "X-A", exists "X-B", exists "X-C", exists "X-D", + exists "X-E") { + test_fail "message already modified"; + } + + addheader "X-A" "1"; + if not header "X-A" "1" { + test_fail "X-A header missing"; + } + + fileinto :create "A"; + + filter "addheader" ["X-B", "2"]; + if not header "X-B" "2" { + test_fail "X-B header missing"; + } + + fileinto :create "B"; + + addheader "X-C" "3"; + if not header "X-C" "3" { + test_fail "X-C header missing"; + } + + fileinto :create "C"; + + filter "addheader" ["X-D", "4"]; + if not header "X-D" "4" { + test_fail "X-D header missing"; + } + + fileinto :create "D"; + + addheader "X-E" "5"; + if not header "X-E" "5" { + test_fail "X-E header missing"; + } + + fileinto :create "E"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + test_message :folder "A" 0; + + if not header "X-A" "1" { + test_fail "X-A header missing"; + } + if anyof ( + header "X-B" "2", header "X-C" "3", + header "X-D" "4", header "X-E" "5") { + test_fail "X-B, X-C, X-D or X-E header found"; + } + + test_message :folder "B" 0; + + if not header "X-B" "2" { + test_fail "X-B header missing"; + } + if anyof ( + header "X-C" "3", header "X-D" "4", header "X-E" "5") { + test_fail "X-C, X-D or X-E header found"; + } + + test_message :folder "C" 0; + + if not header "X-C" "3" { + test_fail "X-C header missing"; + } + if anyof (header "X-D" "4", header "X-E" "5") { + test_fail "X-D or X-E header found"; + } + + test_message :folder "D" 0; + + if not header "X-D" "4" { + test_fail "X-D header missing"; + } + if anyof (header "X-E" "5") { + test_fail "X-E header found"; + } + + test_message :folder "E" 0; + + if not header "X-A" "1" { + test_fail "X-A header missing in final message"; + } + if not header "X-B" "2" { + test_fail "X-B header missing in final message"; + } + if not header "X-C" "3" { + test_fail "X-C header missing in final message"; + } + if not header "X-D" "4" { + test_fail "X-D header missing in final message"; + } + if not header "X-E" "5" { + test_fail "X-E header missing in final message"; + } +} + +test_config_set "sieve_spamtest_status_header" + "X-Spam-Status: [^,]*, score=(-?[[:digit:]]+\\.[[:digit:]]).*"; +test_config_set "sieve_spamtest_max_value" "10"; +test_config_set "sieve_spamtest_status_type" "score"; +test_config_reload :extension "spamtest"; + +test_result_reset; +test "Spamtest" { + if exists "x-spam-status" { + test_fail "message already modified"; + } + + if not header "subject" "Frop!" { + test_fail "message is wrong"; + } + + filter "spamc"; + + if not exists "x-spam-status" { + test_fail "x-spam-score header not added"; + } + + if spamtest :is "0" { + test_fail "spamtest not configured or test failed"; + } + + if not spamtest :is "10" { + test_fail "spamtest yields incorrect value"; + } +} + diff --git a/pigeonhole/tests/plugins/extprograms/pipe/command.svtest b/pigeonhole/tests/plugins/extprograms/pipe/command.svtest new file mode 100644 index 0000000..dabd970 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/pipe/command.svtest @@ -0,0 +1,10 @@ +require "vnd.dovecot.testsuite"; +require "vnd.dovecot.pipe"; + +test_config_set "sieve_pipe_bin_dir" "${tst.path}/../bin"; +test_config_reload :extension "vnd.dovecot.pipe"; + +test "Basic" { + pipe "program"; +} + diff --git a/pigeonhole/tests/plugins/extprograms/pipe/errors.svtest b/pigeonhole/tests/plugins/extprograms/pipe/errors.svtest new file mode 100644 index 0000000..af36b91 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/pipe/errors.svtest @@ -0,0 +1,94 @@ +require "vnd.dovecot.testsuite"; +require "variables"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +/* + * Command syntax + */ + +test "Command syntax" { + if test_script_compile "errors/syntax.sieve" { + test_fail "compile should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "8" { + test_fail "wrong number of errors reported"; + } +} + +/* Unknown program */ + +test_set "message" text: +From: stephan@example.com +To: pipe@example.net +Subject: Frop! + +Frop! +. +; + +test_config_set "sieve_pipe_bin_dir" "${tst.path}/../bin"; +test_config_reload :extension "vnd.dovecot.pipe"; +test_result_reset; + +test "Unknown program" { + if not test_script_compile "errors/unknown-program.sieve" { + test_fail "compile failed"; + } + + if not test_script_run { + test_fail "execute failed"; + } + + if test_result_execute { + test_fail "pipe should have failed"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "1" { + test_fail "wrong number of errors reported"; + } + + if not test_error :index 1 :contains "failed to pipe" { + test_fail "wrong error reported"; + } +} + +/* Timeout */ + +test_set "message" text: +From: stephan@example.com +To: pipe@example.net +Subject: Frop! + +Frop! +. +; + +test_config_set "sieve_pipe_bin_dir" "${tst.path}/../bin"; +test_config_set "sieve_pipe_exec_timeout" "1s"; +test_config_reload :extension "vnd.dovecot.pipe"; +test_result_reset; + +test "Timeout" { + if not test_script_compile "errors/timeout.sieve" { + test_fail "compile failed"; + } + + if not test_script_run { + test_fail "execute failed"; + } + + if test_result_execute { + test_fail "pipe should have timed out"; + } + + if not test_error :count "eq" :comparator "i;ascii-numeric" "2" { + test_fail "wrong number of errors reported"; + } + + if not test_error :index 2 :contains "failed to pipe" { + test_fail "wrong error reported"; + } +} diff --git a/pigeonhole/tests/plugins/extprograms/pipe/errors/syntax.sieve b/pigeonhole/tests/plugins/extprograms/pipe/errors/syntax.sieve new file mode 100644 index 0000000..64d5310 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/pipe/errors/syntax.sieve @@ -0,0 +1,22 @@ +require "vnd.dovecot.pipe"; + +# 1: error: no arguments +pipe; + +# 2: error: numeric argument +pipe 1; + +# 3: error: tag argument +pipe :frop; + +# 4: error: numeric second argument +pipe "sdfd" 1; + +# 5: error: stringlist first argument +pipe ["sdfd","werwe"] "sdfs"; + +# 6: error: too many arguments +pipe "sdfd" "werwe" "sdfs"; + +# 7: error: inappropriate :copy argument +pipe :try :copy "234234" ["324234", "23423"]; diff --git a/pigeonhole/tests/plugins/extprograms/pipe/errors/timeout.sieve b/pigeonhole/tests/plugins/extprograms/pipe/errors/timeout.sieve new file mode 100644 index 0000000..7a940c8 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/pipe/errors/timeout.sieve @@ -0,0 +1,3 @@ +require "vnd.dovecot.pipe"; + +pipe "sleep10"; diff --git a/pigeonhole/tests/plugins/extprograms/pipe/errors/unknown-program.sieve b/pigeonhole/tests/plugins/extprograms/pipe/errors/unknown-program.sieve new file mode 100644 index 0000000..fd6338b --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/pipe/errors/unknown-program.sieve @@ -0,0 +1,3 @@ +require "vnd.dovecot.pipe"; + +pipe "unknown"; diff --git a/pigeonhole/tests/plugins/extprograms/pipe/execute.svtest b/pigeonhole/tests/plugins/extprograms/pipe/execute.svtest new file mode 100644 index 0000000..34b6798 --- /dev/null +++ b/pigeonhole/tests/plugins/extprograms/pipe/execute.svtest @@ -0,0 +1,56 @@ +require "vnd.dovecot.testsuite"; +require "vnd.dovecot.pipe"; +require "vnd.dovecot.debug"; +require "variables"; + +test_set "message" text: +From: stephan@example.com +To: pipe@example.net +Subject: Frop! + +Frop! +. +; + +/* Basic pipe */ + +test_config_set "sieve_pipe_bin_dir" "${tst.path}/../bin"; +test_config_reload :extension "vnd.dovecot.pipe"; +test_result_reset; + +test "Pipe" { + pipe "stderr" ["ONE", "TWO"]; + + if not test_result_execute { + test_fail "failed to pipe message to script"; + } +} + +/* Timeout */ + +test_config_set "sieve_pipe_bin_dir" "${tst.path}/../bin"; +test_config_set "sieve_pipe_exec_timeout" "3s"; +test_config_reload :extension "vnd.dovecot.pipe"; +test_result_reset; + +test "Timeout 3s" { + pipe "sleep2"; + + if not test_result_execute { + test_fail "failed to pipe message to script"; + } +} + +test_result_reset; +test_config_set "sieve_pipe_bin_dir" "${tst.path}/../bin"; +test_config_set "sieve_pipe_exec_timeout" "0"; +test_config_reload :extension "vnd.dovecot.pipe"; +test_result_reset; + +test "Timeout infinite" { + pipe "sleep2"; + + if not test_result_execute { + test_fail "failed to pipe message to script"; + } +} diff --git a/pigeonhole/tests/test-address.svtest b/pigeonhole/tests/test-address.svtest new file mode 100644 index 0000000..135d549 --- /dev/null +++ b/pigeonhole/tests/test-address.svtest @@ -0,0 +1,434 @@ +require "vnd.dovecot.testsuite"; + +/* + * ## RFC 5228, Section 5.1. Test address (page 26) ## + */ + +/* + * TEST: Basic functionionality + */ + +/* "The "address" test matches Internet addresses in structured headers + * that contain addresses. It returns true if any header contains any + * key in the specified part of the address, as modified by the + * comparator and the match keyword. Whether there are other addresses + * present in the header doesn't affect this test; this test does not + * provide any way to determine whether an address is the only address + * in a header. + * + * Like envelope and header, this test returns true if any combination + * of the header-list and key-list arguments match and returns false + * otherwise. + * " + */ + +test_set "message" text: +From: stephan@example.com +To: nico@nl.example.com, harry@de.example.com +cc: Timo <tss(no spam)@fi.iki> +Subject: Frobnitzm + +Test. +. +; + +test "Basic functionality" { + /* Must match */ + if not address :contains ["to", "from"] "harry" { + test_fail "failed to match address (1)"; + } + + if not address :contains ["to", "from"] "de.example" { + test_fail "failed to match address (2)"; + } + + if not address :matches "to" "*@*.example.com" { + test_fail "failed to match address (3)"; + } + + if not address :is "to" "harry@de.example.com" { + test_fail "failed to match address (4)"; + } + + /* Must not match */ + if address :is ["to", "from"] "nonsense@example.com" { + test_fail "matches erroneous address"; + } + + /* Match first key */ + if not address :contains ["to"] ["nico", "fred", "henk"] { + test_fail "failed to match first key"; + } + + /* Match second key */ + if not address :contains ["to"] ["fred", "nico", "henk"] { + test_fail "failed to match second key"; + } + + /* Match last key */ + if not address :contains ["to"] ["fred", "henk", "nico"] { + test_fail "failed to match last key"; + } + + /* First header */ + if not address :contains ["to", "from"] ["fred", "nico", "henk"] { + test_fail "failed to match first header"; + } + + /* Second header */ + if not address :contains ["from", "to"] ["fred", "nico", "henk"] { + test_fail "failed to match second header"; + } + + /* Comment */ + if not address :is "cc" "tss@fi.iki" { + test_fail "failed to ignore comment in address"; + } +} + +/* + * TEST: Case-sensitivity + */ + +/* "Internet email addresses [RFC 2822] have the somewhat awkward characteristic + * that the local-part to the left of the at-sign is considered case sensitive, + * and the domain-part to the right of the at-sign is case insensitive. The + * "address" command does not deal with this itself, but provides the + * ADDRESS-PART argument for allowing users to deal with it. + * " + */ + +test_set "message" text: +From: stephan@example.com +To: Nico@nl.example.com, harry@DE.EXAMPLE.COM +Subject: Case-sensitivity + +Test. +. +; + + +test "Case-sensitivity" { + /* Default: i;ascii-casemap */ + + if not address :is ["to", "from"] "nico@nl.example.com" { + test_fail "address comparator is i;octet by default (1)"; + } + + if not address :is ["to", "from"] "harry@de.example.com" { + test_fail "address comparator is i;octet by default (2)"; + } + + if not address :is ["to", "from"] "STEPHAN@example.com" { + test_fail "address comparator is i;octet by default (3)"; + } + + if not address :is :localpart ["to"] "nico" { + test_fail "address comparator is i;octet by default (4)"; + } + + /* Match case-sensitively */ + + if not address :is :comparator "i;octet" ["to"] "Nico@nl.example.com" { + test_fail "failed to match case-sensitive address (1)"; + } + + if not address :is :comparator "i;octet" ["to"] "harry@DE.EXAMPLE.COM" { + test_fail "failed to match case-sensitive address (2)"; + } + + if address :is :comparator "i;octet" ["to"] "harry@de.example.com" { + test_fail "failed to notice case difference in address with i;octet (1)"; + } + + if address :is :comparator "i;octet" ["from"] "STEPHAN@example.com" { + test_fail "failed to notice case difference in address with i;octet (2)"; + } + + if not address :is :localpart :comparator "i;octet" ["to"] "Nico" { + test_fail "failed to match case-sensitive localpart"; + } + + if address :is :localpart :comparator "i;octet" ["to"] "nico" { + test_fail "failed to notice case difference in local_part with i;octet"; + } + + if not address :is :domain :comparator "i;octet" ["to"] "DE.EXAMPLE.COM" { + test_fail "failed to match case-sensitive localpart"; + } + + if address :is :domain :comparator "i;octet" ["to"] "de.example.com" { + test_fail "failed to notice case difference in domain with i;octet"; + } +} + +/* + * TEST: Phrase part, comments and group names + */ + +/* "The address primitive never acts on the phrase part of an email + * address or on comments within that address. It also never acts on + * group names, ... + * " + */ + +test_set "message" text: +From: Stephan Bosch <stephan(the author)@example.com> +To: Nico Thalens <nico@nl.example.com>, Harry Becker <harry@de.example.com> +cc: tukkers: henk@tukkerland.ex, theo@tukkerland.ex, frits@tukkerland.ex; +Subject: Frobnitzm + +Test. +. +; + +test "Phrase part, comments and group names" { + if address :contains :all :comparator "i;ascii-casemap" + ["to","from"] ["Bosch", "Thalens", "Becker"] { + test_fail "matched phrase part"; + } + + if address :contains :all :comparator "i;ascii-casemap" "from" "author" { + test_fail "matched comment"; + } + + + if address :contains :all :comparator "i;ascii-casemap" ["cc"] ["tukkers"] { + test_fail "matched group name"; + } +} + + +/* + * TEST: Group addresses + */ + +/* "... although it does act on the addresses within the group + * construct. + * " + */ + +test_set "message" text: +From: stephan@friep.frop +To: undisclosed-recipients:; +cc: tukkers: henk@tukkerland.ex, theo@tukkerland.ex, frits@tukkerland.ex; +Subject: Invalid addresses + +Test. +. +; + +test "Group addresses" { + if not address :is :domain ["cc"] ["tukkerland.ex"] { + test_fail "failed to match group address (1)"; + } + + if not address :is :localpart ["cc"] ["henk"] { + test_fail "failed to match group address (2)"; + } + + if not address :is :localpart ["cc"] ["theo"] { + test_fail "failed to match group address (3)"; + } + + if not address :is :localpart ["cc"] ["frits"] { + test_fail "failed to match group address (4)"; + } +} + +/* + * TEST: Address headers + */ + +/* "Implementations MUST restrict the address test to headers that + * contain addresses, but MUST include at least From, To, Cc, Bcc, + * Sender, Resent-From, and Resent-To, and it SHOULD include any other + * header that utilizes an "address-list" structured header body. + * " + */ + +test_set "message" text: +From: stephan@friep.frop +To: henk@tukkerland.ex +CC: ivo@boer.ex +Bcc: joop@hooibaal.ex +Sender: s.bosch@friep.frop +Resent-From: ivo@boer.ex +Resent-To: idioot@dombo.ex +Subject: Berichtje + +Test. +. +; + + +test "Address headers" { + if not address "from" "stephan@friep.frop" { + test_fail "from header not recognized"; + } + + if not address "to" "henk@tukkerland.ex" { + test_fail "to header not recognized"; + } + + if not address "cc" "ivo@boer.ex" { + test_fail "cc header not recognized"; + } + + if not address "bcc" "joop@hooibaal.ex" { + test_fail "bcc header not recognized"; + } + + if not address "sender" "s.bosch@friep.frop" { + test_fail "sender header not recognized"; + } + + if not address "resent-from" "ivo@boer.ex" { + test_fail "resent-from header not recognized"; + } + + if not address "resent-to" "idioot@dombo.ex" { + test_fail "resent-to header not recognized"; + } +} + +/* ## RFC 5228, Section 2.7.4. Comparisons against Addresses (page 16) ## */ + +/* + * TEST: Invalid addresses + */ + +/* + * "If an address is not syntactically valid, then it will not be matched + * by tests specifying ":localpart" or ":domain". + * " + */ + +test_set "message" text: +From: stephan@ +To: @example.org +Cc: nonsense +Resent-To: +Bcc: nico@frop.example.com, @example.org +Resent-Cc:<jürgen@example.com> +Subject: Invalid addresses + +Test. +. +; + +test "Invalid addresses" { + if address :localpart "from" "stephan" { + test_fail ":localpart matched invalid address"; + } + + if address :localpart "resent-cc" "jürgen" { + test_fail ":localpart matched invalid UTF-8 address"; + } + + if address :domain "to" "example.org" { + test_fail ":domain matched invalid address"; + } + + if address :domain "resent-cc" "example.com" { + test_fail ":domain matched invalid UTF-8 address"; + } + + if not address :is :all "resent-to" "" { + test_fail ":all failed to match empty address"; + } + + if not address :is :all "cc" "nonsense" { + test_fail ":all failed to match invalid address"; + } + + if not address :is :all "resent-cc" "<jürgen@example.com>" { + test_fail ":all failed to match invalid UTF-8 address"; + } + + if address :is :localpart "bcc" "" { + test_fail ":localpart matched invalid address"; + } + + if address :is :domain "cc" "example.org" { + test_fail ":domain matched invalid address"; + } +} + +/* + * TEST: Default address part + */ + +/* "If an optional address-part is omitted, the default is ":all". + * " + */ + +test_set "message" text: +From: stephan@example.com +To: nico@nl.example.com, harry@de.example.com +Subject: Frobnitzm + +Test. +. +; + +test "Default address part" { + if not address :is :comparator "i;ascii-casemap" "from" "stephan@example.com" + { + test_fail "invalid default address part (1)"; + } + + if not address :is :comparator "i;ascii-casemap" "to" + ["harry@de.example.com"] { + test_fail "invalid default address part (2)"; + } +} + +/* + * TEST: Mime encoding of '@' in display name + */ + +test_set "message" text: +From: "Frop <frop@example.org>" +To: =?UTF-8?B?RnJpZXBAZnJvcA0K?= + <friep@example.com> +Subject: Test + +Frop! +. +; + + +test "Mime encoding of '@' in display name" { + # Relevant sieve rule: + + if not address :is "To" + ["friep@example.com"] { + test_fail "Invalid address extracted"; + } +} + +/* + * TEST: Erroneous mime encoding + */ + +test_set "message" text: +From: "William Wallace <william@scotsmen.ex>" +To: "=?UTF-8?B?IkR1bWIgTWFpbGVyIg==?=" + <horde@lists.scotsmen.ex> +Subject: Test + +Frop! +. +; + + +test "Erroneous mime encoding" { + # Relevant sieve rule: + + if not address :is ["To","CC"] ["horde@lists.scotsmen.ex","archers@lists.scotsmen.ex"] { + test_fail "Failed to match improperly encoded address headers"; + } +} + + diff --git a/pigeonhole/tests/test-allof.svtest b/pigeonhole/tests/test-allof.svtest new file mode 100644 index 0000000..1ebef67 --- /dev/null +++ b/pigeonhole/tests/test-allof.svtest @@ -0,0 +1,446 @@ +require "vnd.dovecot.testsuite"; + +/* + * ## RFC 5228, Section 5.2. Test allof (page 27) ## + */ + +/* "The "allof" test performs a logical AND on the tests supplied to it. + * + * Example: allof (false, false) => false + * allof (false, true) => false + * allof (true, true) => true + * + * The allof test takes as its argument a test-list. + * " + */ + +test_set "message" text: +From: stephan@example.org +To: test@dovecot.example.net +cc: stephan@idiot.ex +Subject: Test + +Test! +. +; + +/* + * TEST: Basic functionality: static + */ + +test "Basic functionality: static" { + if allof ( true ) { + /* Correct */ + } else { + test_fail "chose wrong single outcome: false"; + } + + if allof ( false ) { + test_fail "chose wrong single outcome: true"; + } else { + /* Correct */ + } + + if allof ( true, true, true ) { + /* Correct */ + } else { + test_fail "chose wrong all-true outcome: false"; + } + + if allof ( false, false, false ) { + test_fail "chose wrong all-false outcome: true"; + } else { + /* Correct */ + } + + if allof ( true, false, false ) { + test_fail "chose wrong first-true outcome: true"; + } else { + /* Correct */ + } + + if allof ( false, true, false ) { + test_fail "chose wrong second-true outcome: true"; + } else { + /* Correct */ + } + + if allof ( false, false, true ) { + test_fail "chose wrong last-true outcome: true"; + } else { + /* Correct */ + } + + if allof ( false, true, true ) { + test_fail "chose wrong first-false outcome: true"; + } else { + /* Correct */ + } + + if allof ( true, false, true ) { + test_fail "chose wrong second-false outcome: true"; + } else { + /* Correct */ + } + + if allof ( true, true, false ) { + test_fail "chose wrong last-false outcome: true"; + } else { + /* Correct */ + } +} + +/* + * TEST: Basic functionality: dynamic + */ + +test "Basic functionality: dynamic" { + if allof ( exists "from" ) { + /* Correct */ + } else { + test_fail "chose wrong single outcome: false"; + } + + if allof ( exists "friep" ) { + test_fail "chose wrong single outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "from", exists "to", exists "cc" ) { + /* Correct */ + } else { + test_fail "chose wrong all-true outcome: false"; + } + + if allof ( exists "friep", exists "frop", exists "frml" ) { + test_fail "chose wrong all-false outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "to", exists "frop", exists "frml" ) { + test_fail "chose wrong first-true outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "friep", exists "from", exists "frml" ) { + test_fail "chose wrong second-true outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "friep", exists "frop", exists "cc" ) { + test_fail "chose wrong last-true outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "friep", exists "from", exists "cc" ) { + test_fail "chose wrong first-false outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "to", exists "frop", exists "cc" ) { + test_fail "chose wrong second-false outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "to", exists "from", exists "frml" ) { + test_fail "chose wrong last-false outcome: true"; + } else { + /* Correct */ + } +} + +/* + * TEST: Basic functionality: static/dynamic + */ + +test "Basic functionality: static/dynamic" { + /* All true */ + + if allof ( true, exists "to", exists "cc" ) { + /* Correct */ + } else { + test_fail "chose wrong all-true first-static outcome: false"; + } + + if allof ( exists "from", true, exists "cc" ) { + /* Correct */ + } else { + test_fail "chose wrong all-true second-static outcome: false"; + } + + if allof ( exists "from", exists "to", true ) { + /* Correct */ + } else { + test_fail "chose wrong all-true third-static outcome: false"; + } + + /* All false */ + + if allof ( false, exists "frop", exists "frml" ) { + test_fail "chose wrong all-false first-static outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "friep", false, exists "frml" ) { + test_fail "chose wrong all-false second-static outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "friep", exists "frop", false ) { + test_fail "chose wrong all-false third-static outcome: true"; + } else { + /* Correct */ + } + + /* First true */ + + if allof ( true, exists "frop", exists "frml" ) { + test_fail "chose wrong first-true first-static outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "to", false, exists "frml" ) { + test_fail "chose wrong first-true second-static outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "to", exists "frop", false ) { + test_fail "chose wrong first-true third-static outcome: true"; + } else { + /* Correct */ + } + + /* Second true */ + + if allof ( false, exists "from", exists "frml" ) { + test_fail "chose wrong second-true first-static outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "friep", true, exists "frml" ) { + test_fail "chose wrong second-true second-static outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "friep", exists "from", false ) { + test_fail "chose wrong second-true third-static outcome: true"; + } else { + /* Correct */ + } + + /* Last true */ + + if allof ( false, exists "frop", exists "cc" ) { + test_fail "chose wrong last-true first-static outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "friep", false, exists "cc" ) { + test_fail "chose wrong last-true second-static outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "friep", exists "frop", true ) { + test_fail "chose wrong last-true third-static outcome: true"; + } else { + /* Correct */ + } + + /* First false */ + + if allof ( false, exists "from", exists "cc" ) { + test_fail "chose wrong first-false first-static outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "friep", true, exists "cc" ) { + test_fail "chose wrong first-false second-static outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "friep", exists "from", true ) { + test_fail "chose wrong first-false third-static outcome: true"; + } else { + /* Correct */ + } + + /* Second false */ + + if allof ( true, exists "frop", exists "cc" ) { + test_fail "chose wrong second-false first-static outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "to", false, exists "cc" ) { + test_fail "chose wrong second-false second-static outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "to", exists "frop", true ) { + test_fail "chose wrong second-false third-static outcome: true"; + } else { + /* Correct */ + } + + /* Last false */ + + if allof ( true, exists "from", exists "frml" ) { + test_fail "chose wrong last-false first-static outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "to", true, exists "frml" ) { + test_fail "chose wrong last-false second-static outcome: true"; + } else { + /* Correct */ + } + + if allof ( exists "to", exists "from", false ) { + test_fail "chose wrong last-false last-static outcome: true"; + } else { + /* Correct */ + } +} + +/* + * TEST: Basic functionality: nesting + */ + +test "Basic functionality: nesting" { + /* Static */ + + if allof ( allof(true, true), allof(true, true) ) { + /* Correct */ + } else { + test_fail "chose wrong static nesting ((true, true),(true,true)) outcome: false"; + } + + if allof ( allof(false, true), allof(true, true) ) { + test_fail "chose wrong static nesting ((false, true),(true,true)) outcome: true"; + } else { + /* Correct */ + } + + if allof ( allof(true, false), allof(true, true) ) { + test_fail "chose wrong static nesting ((true,false),(true,true)) outcome: true"; + } else { + /* Correct */ + } + + if allof ( allof(true, true), allof(false, true) ) { + test_fail "chose wrong static nesting ((true, true),(false,true)) outcome: true"; + } else { + /* Correct */ + } + + if allof ( allof(true, true), allof(true, false) ) { + test_fail "chose wrong static nesting ((true, true),(true,false)) outcome: true"; + } else { + /* Correct */ + } + + if allof ( allof(true, false), allof(true, false) ) { + test_fail "chose wrong static nesting ((true, false),(true,false)) outcome: true"; + } else { + /* Correct */ + } + + /* Dynamic */ + + if allof ( allof(exists "to", exists "from"), allof(exists "cc", exists "subject") ) { + /* Correct */ + } else { + test_fail "chose wrong dynamic nesting ((true, true),(true,true)) outcome: false"; + } + + if allof ( allof(exists "frop", exists "from"), allof(exists "cc", exists "subject") ) { + test_fail "chose wrong dynamic nesting ((false, true),(true,true)) outcome: true"; + } else { + /* Correct */ + } + + if allof ( allof(exists "to", exists "friep"), allof(exists "cc", exists "subject") ) { + test_fail "chose wrong dynamic nesting ((true,false),(true,true)) outcome: true"; + } else { + /* Correct */ + } + + if allof ( allof(exists "to", exists "from"), allof(exists "frml", exists "subject") ) { + test_fail "chose wrong dynamic nesting ((true, true),(false,true)) outcome: true"; + } else { + /* Correct */ + } + + if allof ( allof(exists "to", exists "from"), allof(exists "cc", exists "fruts") ) { + test_fail "chose wrong dynamic nesting ((true, true),(true,false)) outcome: true"; + } else { + /* Correct */ + } + + if allof ( allof(exists "to", exists "friep"), allof(exists "cc", exists "fruts") ) { + test_fail "chose wrong dynamic nesting ((true, false),(true,false)) outcome: true"; + } else { + /* Correct */ + } + + /* Static/Dynamic */ + + if allof ( allof(exists "to", true), allof(true, exists "subject") ) { + /* Correct */ + } else { + test_fail "chose wrong static/dynamic nesting ((true, true),(true,true)) outcome: false"; + } + + if allof ( allof(false, exists "from"), allof(exists "cc", exists "subject") ) { + test_fail "chose wrong static/dynamic nesting ((false, true),(true,true)) outcome: true"; + } else { + /* Correct */ + } + + if allof ( allof(exists "to", false), allof(exists "cc", exists "subject") ) { + test_fail "chose wrong static/dynamic nesting ((true,false),(true,true)) outcome: true"; + } else { + /* Correct */ + } + + if allof ( allof(exists "to", exists "from"), allof(false, exists "subject") ) { + test_fail "chose wrong static/dynamic nesting ((true, true),(false,true)) outcome: true"; + } else { + /* Correct */ + } + + if allof ( allof(exists "to", exists "from"), allof(exists "cc", false) ) { + test_fail "chose wrong static/dynamic nesting ((true, true),(true,false)) outcome: true"; + } else { + /* Correct */ + } + + if allof ( allof(exists "to", false), allof(true, exists "fruts") ) { + test_fail "chose wrong static/dynamic nesting ((true, false),(true,false)) outcome: true"; + } else { + /* Correct */ + } + +} + + diff --git a/pigeonhole/tests/test-anyof.svtest b/pigeonhole/tests/test-anyof.svtest new file mode 100644 index 0000000..77a9c79 --- /dev/null +++ b/pigeonhole/tests/test-anyof.svtest @@ -0,0 +1,445 @@ +require "vnd.dovecot.testsuite"; + +/* + * ## RFC 5228, Section 5.3. Test anyof (page 27) ## + */ + +/* "The "anyof" test performs a logical OR on the tests supplied to it. + * + * Example: anyof (false, false) => false + * anyof (false, true) => true + * anyof (true, true) => true + * " + */ + +test_set "message" text: +From: stephan@example.org +To: test@dovecot.example.net +cc: stephan@idiot.ex +Subject: Test + +Test! +. +; + +/* + * TEST: Basic functionality: static + */ + +test "Basic functionality: static" { + if anyof ( true ) { + /* Correct */ + } else { + test_fail "chose wrong single outcome: false"; + } + + if anyof ( false ) { + test_fail "chose wrong single outcome: true"; + } else { + /* Correct */ + } + + if anyof ( true, true, true ) { + /* Correct */ + } else { + test_fail "chose wrong all-true outcome: false"; + } + + if anyof ( false, false, false ) { + test_fail "chose wrong all-false outcome: true"; + } else { + /* Correct */ + } + + if anyof ( true, false, false ) { + /* Correct */ + } else { + test_fail "chose wrong first-true outcome: false"; + } + + if anyof ( false, true, false ) { + /* Correct */ + } else { + test_fail "chose wrong second-true outcome: false"; + } + + if anyof ( false, false, true ) { + /* Correct */ + } else { + test_fail "chose wrong last-true outcome: false"; + } + + if anyof ( false, true, true ) { + /* Correct */ + } else { + test_fail "chose wrong first-false outcome: false"; + } + + if anyof ( true, false, true ) { + /* Correct */ + } else { + test_fail "chose wrong second-false outcome: false"; + } + + if anyof ( true, true, false ) { + /* Correct */ + } else { + test_fail "chose wrong last-false outcome: false"; + } +} + +/* + * TEST: Basic functionality: dynamic + */ + +test "Basic functionality: dynamic" { + if anyof ( exists "from" ) { + /* Correct */ + } else { + test_fail "chose wrong single outcome: false"; + } + + if anyof ( exists "friep" ) { + test_fail "chose wrong single outcome: true"; + } else { + /* Correct */ + } + + if anyof ( exists "from", exists "to", exists "cc" ) { + /* Correct */ + } else { + test_fail "chose wrong all-true outcome: false"; + } + + if anyof ( exists "friep", exists "frop", exists "frml" ) { + test_fail "chose wrong all-false outcome: true"; + } else { + /* Correct */ + } + + if anyof ( exists "to", exists "frop", exists "frml" ) { + /* Correct */ + } else { + test_fail "chose wrong first-true outcome: false"; + } + + if anyof ( exists "friep", exists "from", exists "frml" ) { + /* Correct */ + } else { + test_fail "chose wrong second-true outcome: false"; + } + + if anyof ( exists "friep", exists "frop", exists "cc" ) { + /* Correct */ + } else { + test_fail "chose wrong last-true outcome: false"; + } + + if anyof ( exists "friep", exists "from", exists "cc" ) { + /* Correct */ + } else { + test_fail "chose wrong first-false outcome: false"; + } + + if anyof ( exists "to", exists "frop", exists "cc" ) { + /* Correct */ + } else { + test_fail "chose wrong second-false outcome: false"; + } + + if anyof ( exists "to", exists "from", exists "frml" ) { + /* Correct */ + } else { + test_fail "chose wrong last-false outcome: false"; + } +} + +/* + * TEST: Basic functionality: static/dynamic + */ + +test "Basic functionality: static/dynamic" { + /* All true */ + + if anyof ( true, exists "to", exists "cc" ) { + /* Correct */ + } else { + test_fail "chose wrong all-true first-static outcome: false"; + } + + if anyof ( exists "from", true, exists "cc" ) { + /* Correct */ + } else { + test_fail "chose wrong all-true second-static outcome: false"; + } + + if anyof ( exists "from", exists "to", true ) { + /* Correct */ + } else { + test_fail "chose wrong all-true third-static outcome: false"; + } + + /* All false */ + + if anyof ( false, exists "frop", exists "frml" ) { + test_fail "chose wrong all-false first-static outcome: true"; + } else { + /* Correct */ + } + + if anyof ( exists "friep", false, exists "frml" ) { + test_fail "chose wrong all-false second-static outcome: true"; + } else { + /* Correct */ + } + + if anyof ( exists "friep", exists "frop", false ) { + test_fail "chose wrong all-false third-static outcome: true"; + } else { + /* Correct */ + } + + /* First true */ + + if anyof ( true, exists "frop", exists "frml" ) { + /* Correct */ + } else { + test_fail "chose wrong first-true first-static outcome: false"; + } + + if anyof ( exists "to", false, exists "frml" ) { + /* Correct */ + } else { + test_fail "chose wrong first-true second-static outcome: false"; + } + + if anyof ( exists "to", exists "frop", false ) { + /* Correct */ + } else { + test_fail "chose wrong first-true third-static outcome: false"; + } + + /* Second true */ + + if anyof ( false, exists "from", exists "frml" ) { + /* Correct */ + } else { + test_fail "chose wrong second-true first-static outcome: false"; + } + + if anyof ( exists "friep", true, exists "frml" ) { + /* Correct */ + } else { + test_fail "chose wrong second-true second-static outcome: false"; + } + + if anyof ( exists "friep", exists "from", false ) { + /* Correct */ + } else { + test_fail "chose wrong second-true third-static outcome: false"; + } + + /* Last true */ + + if anyof ( false, exists "frop", exists "cc" ) { + /* Correct */ + } else { + test_fail "chose wrong last-true first-static outcome: false"; + } + + if anyof ( exists "friep", false, exists "cc" ) { + /* Correct */ + } else { + test_fail "chose wrong last-true second-static outcome: false"; + } + + if anyof ( exists "friep", exists "frop", true ) { + /* Correct */ + } else { + test_fail "chose wrong last-true third-static outcome: false"; + } + + /* First false */ + + if anyof ( false, exists "from", exists "cc" ) { + /* Correct */ + } else { + test_fail "chose wrong first-false first-static outcome: false"; + } + + if anyof ( exists "friep", true, exists "cc" ) { + /* Correct */ + } else { + test_fail "chose wrong first-false second-static outcome: false"; + } + + if anyof ( exists "friep", exists "from", true ) { + /* Correct */ + } else { + test_fail "chose wrong first-false third-static outcome: false"; + } + + /* Second false */ + + if anyof ( true, exists "frop", exists "cc" ) { + /* Correct */ + } else { + test_fail "chose wrong second-false first-static outcome: false"; + } + + if anyof ( exists "to", false, exists "cc" ) { + /* Correct */ + } else { + test_fail "chose wrong second-false second-static outcome: false"; + } + + if anyof ( exists "to", exists "frop", true ) { + /* Correct */ + } else { + test_fail "chose wrong second-false third-static outcome: false"; + } + + /* Third false */ + + if anyof ( true, exists "from", exists "frml" ) { + /* Correct */ + } else { + test_fail "chose wrong last-false first-static outcome: false"; + } + + if anyof ( exists "to", true, exists "frml" ) { + /* Correct */ + } else { + test_fail "chose wrong last-false second-static outcome: false"; + } + + if anyof ( exists "to", exists "from", false ) { + /* Correct */ + } else { + test_fail "chose wrong last-false third-static outcome: false"; + } +} + +/* + * TEST: Basic functionality: nesting + */ + +test "Basic functionality: nesting" { + /* Static */ + + if anyof ( anyof(false, false), anyof(false, false) ) { + test_fail "chose wrong static nesting ((false, false),(false,false)) outcome: true"; + } else { + /* Correct */ + } + + if anyof ( anyof(true, false), anyof(false, false) ) { + /* Correct */ + } else { + test_fail "chose wrong static nesting ((true, false),(false,false)) outcome: false"; + } + + if anyof ( anyof(false, true), anyof(false, false) ) { + /* Correct */ + } else { + test_fail "chose wrong static nesting ((false, true),(false,false)) outcome: false"; + } + + if anyof ( anyof(false, false), anyof(true, false) ) { + /* Correct */ + } else { + test_fail "chose wrong static nesting ((false, false),(true,false)) outcome: false"; + } + + if anyof ( anyof(false, false), anyof(false, true) ) { + /* Correct */ + } else { + test_fail "chose wrong static nesting ((false, false),(false,true)) outcome: false"; + } + + if anyof ( anyof(true, false), anyof(false, true) ) { + /* Correct */ + } else { + test_fail "chose wrong static nesting ((true, false),(false,true)) outcome: false"; + } + + /* Dynamic */ + + if anyof ( anyof(exists "frop", exists "friep"), anyof(exists "frml", exists "fruts") ) { + test_fail "chose wrong dynamic nesting ((false, false),(false,false)) outcome: true"; + } else { + /* Correct */ + } + + if anyof ( anyof(exists "to", exists "friep"), anyof(exists "frml", exists "fruts") ) { + /* Correct */ + } else { + test_fail "chose wrong dynamic nesting ((true, false),(false,false)) outcome: false"; + } + + if anyof ( anyof(exists "frop", exists "from"), anyof(exists "frml", exists "fruts") ) { + /* Correct */ + } else { + test_fail "chose wrong dynamic nesting ((false, true),(false,false)) outcome: false"; + } + + if anyof ( anyof(exists "frop", exists "friep"), anyof(exists "cc", exists "fruts") ) { + /* Correct */ + } else { + test_fail "chose wrong dynamic nesting ((false, false),(true,false)) outcome: false"; + } + + if anyof ( anyof(exists "frop", exists "friep"), anyof(exists "frml", exists "subject") ) { + /* Correct */ + } else { + test_fail "chose wrong dynamic nesting ((false, false),(false,true)) outcome: false"; + } + + if anyof ( anyof(exists "to", exists "friep"), anyof(exists "frml", exists "subject") ) { + /* Correct */ + } else { + test_fail "chose wrong dynamic nesting ((true, false),(false,true)) outcome: false"; + } + + /* Static/Dynamic */ + + if anyof ( anyof(false, exists "friep"), anyof(exists "frml", exists "fruts") ) { + test_fail "chose wrong static/dynamic nesting ((false, false),(false,false)) outcome: true"; + } else { + /* Correct */ + } + + if anyof ( anyof(exists "to", false), anyof(exists "frml", exists "fruts") ) { + /* Correct */ + } else { + test_fail "chose wrong static/dynamic nesting ((true, false),(false,false)) outcome: false"; + } + + if anyof ( anyof(exists "frop", exists "from"), anyof(false, exists "fruts") ) { + /* Correct */ + } else { + test_fail "chose wrong static/dynamic nesting ((false, true),(false,false)) outcome: false"; + } + + if anyof ( anyof(exists "frop", exists "friep"), anyof(exists "cc", false) ) { + /* Correct */ + } else { + test_fail "chose wrong static/dynamic nesting ((false, false),(true,false)) outcome: false"; + } + + if anyof ( anyof(exists "frop", exists "friep"), anyof(exists "frml", true) ) { + /* Correct */ + } else { + test_fail "chose wrong static/dynamic nesting ((false, false),(false,true)) outcome: false"; + } + + if anyof ( anyof(true, exists "friep"), anyof(false, exists "subject") ) { + /* Correct */ + } else { + test_fail "chose wrong dynamic nesting ((true, false),(false,true)) outcome: false"; + } + +} + + + diff --git a/pigeonhole/tests/test-exists.svtest b/pigeonhole/tests/test-exists.svtest new file mode 100644 index 0000000..8c4c2fc --- /dev/null +++ b/pigeonhole/tests/test-exists.svtest @@ -0,0 +1,93 @@ +require "vnd.dovecot.testsuite"; + +/* "The "exists" test is true if the headers listed in the header-names + * argument exist within the message. All of the headers must exist or + * the test is false. + * " + */ + +test_set "message" text: +From: stephan@example.org +To: nico@vestingbar.bl +Subject: Test message +Date: Wed, 29 Jul 2009 18:21:44 +0300 +X-Spam-Status: Not Spam +Resent-To: nico@frop.example.com + +Test! +. +; + +/* + * TEST: One header + */ + +test "One header" { + if not exists "from" { + test_fail "exists test missed from header"; + } + + if exists "x-nonsense" { + test_fail "exists test found non-existent header"; + } +} + +/* + * TEST: Two headers + */ + +test "Two headers" { + if not exists ["from","to"] { + test_fail "exists test missed from or to header"; + } + + if exists ["from","x-nonsense"] { + test_fail "exists test found non-existent header (1)"; + } + + if exists ["x-nonsense","to"] { + test_fail "exists test found non-existent header (2)"; + } + + if exists ["x-nonsense","x-nonsense2"] { + test_fail "exists test found non-existent header (3)"; + } +} + +/* + * TEST: Three headers + */ + +test "Three headers" { + if not exists ["Subject","date","resent-to"] { + test_fail "exists test missed subject, date or resent-to header"; + } + + if exists ["x-nonsense","date","resent-to"] { + test_fail "exists test found non-existent header (1)"; + } + + if exists ["subject", "x-nonsense","resent-to"] { + test_fail "exists test found non-existent header (2)"; + } + + if exists ["subject","date","x-nonsense"] { + test_fail "exists test found non-existent header (3)"; + } + + if exists ["subject", "x-nonsense","x-nonsense2"] { + test_fail "exists test found non-existent header (4)"; + } + + if exists ["x-nonsense","date","x-nonsense2"] { + test_fail "exists test found non-existent header (5)"; + } + + if exists ["x-nonsense","x-nonsense2","resent-to"] { + test_fail "exists test found non-existent header (6)"; + } + + if exists ["x-nonsense","x-nonsense2","x-nonsense3"] { + test_fail "exists test found non-existent header (7)"; + } +} diff --git a/pigeonhole/tests/test-header.svtest b/pigeonhole/tests/test-header.svtest new file mode 100644 index 0000000..138fb82 --- /dev/null +++ b/pigeonhole/tests/test-header.svtest @@ -0,0 +1,280 @@ +require "vnd.dovecot.testsuite"; +require "variables"; + +/* + * ## RFC 5228, Section 5.7. Test header (page 29) ## + */ + +/* + * TEST: Basic functionality + */ + +/* "The "header" test evaluates to true if the value of any of the named + * headers, ignoring leading and trailing whitespace, matches any key. + * The type of match is specified by the optional match argument, which + * defaults to ":is" if not specified, as specified in section 2.6. + * + * Like address and envelope, this test returns true if any combination + * of the header-names list and key-list arguments match and returns + * false otherwise. + * " + */ + +test_set "message" text: +From: stephan@example.com +To: nico@nl.example.com, harry@de.example.com +Subject: Frobnitzm +Comments: This is nonsense. +Keywords: nonsense, strange, testing +X-Spam: Yes + +Test. +. +; + +test "Basic functionality" { + /* Must match */ + if not header :contains ["Subject", "Comments"] "Frobnitzm" { + test_fail "failed to match header (1)"; + } + + if not header :contains ["Subject", "Comments"] "nonsense" { + test_fail "failed to match header(2)"; + } + + if not header :matches "Keywords" "*, strange, *" { + test_fail "failed to match header (3)"; + } + + if not header :is "Comments" "This is nonsense." { + test_fail "failed to match header (4)"; + } + + /* Must not match */ + if header ["subject", "comments", "keywords"] "idiotic" { + test_fail "matched nonsense"; + } + + /* Match first key */ + if not header :contains ["keywords"] ["strange", "snot", "vreemd"] { + test_fail "failed to match first key"; + } + + /* Match second key */ + if not header :contains ["keywords"] ["raar", "strange", "vreemd"] { + test_fail "failed to match second key"; + } + + /* Match last key */ + if not header :contains ["keywords"] ["raar", "snot", "strange"] { + test_fail "failed to match last key"; + } + + /* First header */ + if not header :contains ["keywords", "subject"] + ["raar", "strange", "vreemd"] { + test_fail "failed to match first header"; + } + + /* Second header */ + if not header :contains ["subject", "keywords"] + ["raar", "strange", "vreemd"] { + test_fail "failed to match second header"; + } +} + +/* + * TEST: Matching empty key + */ + +/* "If a header listed in the header-names argument exists, it contains + * the empty key (""). However, if the named header is not present, it + * does not match any key, including the empty key. So if a message + * contained the header + * + * X-Caffeine: C8H10N4O2 + * + * these tests on that header evaluate as follows: + * + * header :is ["X-Caffeine"] [""] => false + * header :contains ["X-Caffeine"] [""] => true + * " + */ + + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.com +X-Caffeine: C8H10N4O2 +Subject: I need coffee! +Comments: + +Text +. +; + +test "Matching empty key" { + if header :is "X-Caffeine" "" { + test_fail ":is-matched non-empty header with empty string"; + } + + if not header :contains "X-Caffeine" "" { + test_fail "failed to match existing header with empty string"; + } + + if not header :is "comments" "" { + test_fail "failed to match empty header with empty string"; + } + + if header :contains "X-Nonsense" "" { + test_fail ":contains-matched non-existent header with empty string"; + } +} + +/* + * TEST: Ignoring whitespace + */ + +/* "The "header" test evaluates to true if the value of any of the named + * headers, ignoring leading and trailing whitespace, matches any key. + * ... + * " + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.com +Subject: Help +X-A: Text +X-B: Text + +Text +. +; + +test "Ignoring whitespace" { + if not header :is "x-a" "Text" { + if header :matches "x-a" "*" { + set "header" "${1}"; + } + test_fail "header test does not strip leading whitespace (header=`${header}`)"; + } + + if not header :is "x-b" "Text" { + if header :matches "x-b" "*" { + set "header" "${1}"; + } + test_fail "header test does not strip trailing whitespace (header=`${header}`)"; + } + + if not header :is "subject" "Help" { + if header :matches "subject" "*" { + set "header" "${1}"; + } + test_fail "header test does not strip both leading and trailing whitespace (header=`${header}`)"; + } +} + +/* + * TEST: Absent or empty header + */ + +/* "Testing whether a given header is either absent or doesn't contain + * any non-whitespace characters can be done using a negated "header" + * test: + * + * not header :matches "Cc" "?*" + * " + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.com +CC: harry@nonsense.ex +Subject: +Comments: + +Text +. +; + +test "Absent or empty header" { + if not header :matches "Cc" "?*" { + test_fail "CC header is not absent or empty"; + } + + if header :matches "Subject" "?*" { + test_fail "Subject header is empty, but matched otherwise"; + } + + if header :matches "Comment" "?*" { + test_fail "Comment header is empty, but matched otherwise"; + } +} + +/* + * ## RFC 5228, Section 2.4.2.2. Headers (page 9) + */ + +/* + * TEST: Invalid header name + */ + +/* "A header name never contains a colon. The "From" header refers to a + * line beginning "From:" (or "From :", etc.). No header will match + * the string "From:" due to the trailing colon. + * + * Similarly, no header will match a syntactically invalid header name. + * An implementation MUST NOT cause an error for syntactically invalid + * header names in tests. + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.com +Subject: Valid message +X-Multiline: This is a multi-line + header body, which should be + unfolded correctly. + +Text +. +; + +test "Invalid header name" { + if header :contains "subject:" "" { + test_fail "matched invalid header name"; + } + + if header :contains "to!" "" { + test_fail "matched invalid header name"; + } +} + +/* + * TEST: Folded headers + */ + +/* "Header lines are unfolded as described in [RFC 2822] section 2.2.3. + * ... + * " + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.com +Subject: Not enough space on a line! +X-Multiline: This is a multi-line + header body, which should be + unfolded correctly. + +Text +. +; + +test "Folded header" { + if not header :is "x-multiline" + "This is a multi-line header body, which should be unfolded correctly." { + test_fail "failed to properly unfold folded header."; + } +} diff --git a/pigeonhole/tests/test-size.svtest b/pigeonhole/tests/test-size.svtest new file mode 100644 index 0000000..dd5cdc4 --- /dev/null +++ b/pigeonhole/tests/test-size.svtest @@ -0,0 +1,74 @@ +require "vnd.dovecot.testsuite"; + +/* + * ## RFC 5228, Section 5.9. Test size (page 29) ## + */ + +/* + * TEST: Basic functionality + */ + +/* "The "size" test deals with the size of a message. It takes either a + * tagged argument of ":over" or ":under", followed by a number + * representing the size of the message. + * + * If the argument is ":over", and the size of the message is greater + * than the number provided, the test is true; otherwise, it is false. + + * If the argument is ":under", and the size of the message is less than + * the number provided, the test is true; otherwise, it is false. + * " + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.com +Subject: Help +X-A: Text +X-B: Text +X-Multiline: This is a multi-line + header body, which should be + unfolded correctly. + +Text + +. +; + +test "Basic functionality" { + if not size :under 1000 { + test_fail "size test produced unexpected result (1)"; + } + + if size :under 10 { + test_fail "size test produced unexpected result (2)"; + } + + if not size :over 10 { + test_fail "size test produced unexpected result (3)"; + } + + if size :over 1000 { + test_fail "size test produced unexpected result (4)"; + } +} + +/* + * TEST: Exact size + */ + +/* "Note that for a message that is exactly 4,000 octets, the message is + * neither ":over" nor ":under" 4000 octets. + * " + */ + +test "Exact size" { + if size :under 221 { + test_fail "size :under matched exact limit"; + } + + if size :over 221 { + test_fail "size :over matched exact limit"; + } +} + diff --git a/pigeonhole/tests/testsuite.svtest b/pigeonhole/tests/testsuite.svtest new file mode 100644 index 0000000..349ba89 --- /dev/null +++ b/pigeonhole/tests/testsuite.svtest @@ -0,0 +1,75 @@ +require "vnd.dovecot.testsuite"; +require "envelope"; + +/* Test message environment */ + +test "Message Environment" { + test_set "message" text: +From: sirius@example.org +To: nico@frop.example.com +Subject: Frop! + +Frop! +. + ; + + if not header :contains "from" "example.org" { + test_fail "message data not set properly."; + } + + test_set "message" text: +From: nico@frop.example.com +To: stephan@nl.example.com +Subject: Friep! + +Friep! +. + ; + + if not header :is "from" "nico@frop.example.com" { + test_fail "message data not set properly."; + } + + keep; +} + +/* Test envelope environment */ + +test "Envelope Environment" { + test_set "envelope.from" "stephan@hutsefluts.example.net"; + + if not envelope :is "from" "stephan@hutsefluts.example.net" { + test_fail "envelope.from data not set properly (1)."; + } + + test_set "envelope.to" "news@example.org"; + + if not envelope :is "to" "news@example.org" { + test_fail "envelope.to data not set properly (1)."; + } + + test_set "envelope.auth" "sirius"; + + if not envelope :is "auth" "sirius" { + test_fail "envelope.auth data not set properly (1)."; + } + + test_set "envelope.from" "stephan@example.org"; + + if not envelope :is "from" "stephan@example.org" { + test_fail "envelope.from data not reset properly (2)."; + } + + test_set "envelope.to" "past-news@example.org"; + + if not envelope :is "to" "past-news@example.org" { + test_fail "envelope.to data not reset properly (2)."; + } + + test_set "envelope.auth" "zilla"; + + if not envelope :is "auth" "zilla" { + test_fail "envelope.auth data not reset properly (2)."; + } +} + diff --git a/pigeonhole/update-version.sh b/pigeonhole/update-version.sh new file mode 100644 index 0000000..ec47deb --- /dev/null +++ b/pigeonhole/update-version.sh @@ -0,0 +1,64 @@ +#!/bin/sh + +SRCDIR="${1:-`pwd`}" +BUILDDIR="${2:-`pwd`}" +VERSION_H="pigeonhole-version.h" +VERSION_HT="pigeonhole-version.h.tmp" + +abspath() +{ #$1 the path + #$2 1 -> SRCDIR || 2 -> BUILDDIR + old=`pwd` + cd "${1}" + if [ ${2} -eq 1 ]; then + SRCDIR=`pwd` + else + BUILDDIR=`pwd` + fi + cd "$old" +} + +abspath "${SRCDIR}" 1 +abspath "${BUILDDIR}" 2 + +# when using a different BUILDDIR just copy from SRCDIR, if there is no .git +if [ "${BUILDDIR}" != "${SRCDIR}" ]; then + if [ ! -d "${SRCDIR}/.git" ] && [ -f "${SRCDIR}/${VERSION_H}" ]; then + cmp -s "${SRCDIR}/${VERSION_H}" "${BUILDDIR}/${VERSION_H}" + if [ $? -ne 0 ]; then + cp "${SRCDIR}/${VERSION_H}" "${BUILDDIR}/${VERSION_H}" + exit 0 + fi + fi +fi + +# Don't generate dovecot-version.h if the source tree has no .git dir but +# a dovecot-version.h. This may be the result of a release/nightly tarball. +[ ! -d "${SRCDIR}/.git" ] && [ -f "${BUILDDIR}/${VERSION_H}" ] && exit 0 + +# Lets generate the dovecot-version.h +[ -f "${BUILDDIR}/${VERSION_HT}" ] && rm -f "${BUILDDIR}/${VERSION_HT}" +if true; then + GITID=`git --git-dir ${SRCDIR}/.git rev-parse --short HEAD` + cat > "${BUILDDIR}/${VERSION_HT}" <<EOF +#ifndef PIGEONHOLE_VERSION_H +#define PIGEONHOLE_VERSION_H + +#define PIGEONHOLE_VERSION_FULL PIGEONHOLE_VERSION" (${GITID})" + +#endif /* PIGEONHOLE_VERSION_H */ +EOF +else + cat > "${BUILDDIR}/${VERSION_HT}" <<EOF +#ifndef PIGEONHOLE_VERSION_H +#define PIGEONHOLE_VERSION_H + +#define PIGEONHOLE_VERSION_FULL PIGEONHOLE_VERSION + +#endif /* PIGEONHOLE_VERSION_H */ +EOF +fi + +cmp -s "${BUILDDIR}/${VERSION_H}" "${BUILDDIR}/${VERSION_HT}" && \ + rm -f "${BUILDDIR}/${VERSION_HT}" || \ + mv -f "${BUILDDIR}/${VERSION_HT}" "${BUILDDIR}/${VERSION_H}" |